microsoft / wil

Windows Implementation Library
MIT License
2.59k stars 236 forks source link

Allow getting array_view/span out of IBuffer and IMemoryBuffer #360

Open JaiganeshKumaran opened 1 year ago

JaiganeshKumaran commented 1 year ago

For safety, the conversion operator can be explicit.

kennykerr commented 1 year ago

I've tagged a few project maintainers. If one of them is available to offer guidance and mentorship for this issue, they will reach out according to the contributing guide to discuss and agree on an approach.

@microsoft/cppwinrt-maintainers

jonwis commented 1 year ago

@JaiganeshKumaran can you write a little sample code showing what you'd like to see?

oldnewthing commented 1 year ago
template <typename D>
struct consume_Windows_Foundation_IMemoryBufferReference
{
   /* existing code unchanged */

    auto view() const
    {
        uint8_t* data{};
        uint32_t capacity{};
        check_hresult(static_cast<D const&>(*this).template as<IMemoryBufferByteAccess>()->GetBuffer(&data, &capacity));
        return array_view(data, capacity);
    }
};

template <typename D>
struct consume_Windows_Storage_Streams_IBuffer
{
   /* existing code unchanged */

    auto view() const
    {
        uint8_t* data{};
        check_hresult(static_cast<D const&>(*this).template as<IBufferByteAccess>()->Buffer(&data));
        return array_view(data, Length());
    }
};

Now you can write

IBuffer buffer = get_some_buffer_from_somewhere();
auto view = buffer.view(); // returns an array_view<uint8_t>

IMemoryBufferReference ref = memorybuffer.CreateReference();
auto view = ref.view(); // returns an array_view<uint8_t>

This is much safer than using data(), which gives you a pointer to the start of the data but no information about how much data there is.

JaiganeshKumaran commented 1 year ago

Not really a fan of having a separate view member function - it is not how the standard library does things. An implicit conversion operator also has the advantage of passing an IBuffer directly to a function taking array_view<uint8_t const> (pass-array in WinRT). Now for safety, the rvalue-qualified conversion operator should be deleted. This does, however, prevent some valid code eg: FunctionTakingArrayView(FunctionReturningBuffer()).

Another thing to consider is allowing to take a std::span<std::byte> from buffers, in addition to array_view/span<uint8_t>.

sylveon commented 1 year ago

I don't think it should be deleted, as you've shown there are valid usages of r-values.

oldnewthing commented 1 year ago

If the operator is explicit, then it actually gets worse because you have to perform the wordy conversion explicitly.

The explicit conversion from hstring to wstring_view suffers from this same problem.