Round-trip Data with MemoryStream

Build a small in-memory binary protocol while preserving stream and wrapper lifetimes.

IntermediateIOBuilt and run

Goal and component

Write a small binary record into an owned memory buffer, rewind it, read it back, and preserve the stream through reader/writer teardown. Select IO.

set(SHARP_RUNTIME_COMPONENTS IO)
target_link_libraries(app PRIVATE SharpRuntime::IO)

Write, rewind, and read

#include <System/IO/BinaryReader.hpp>
#include <System/IO/BinaryWriter.hpp>
#include <System/IO/MemoryStream.hpp>

System::IO::MemoryStream stream;

{
    System::IO::BinaryWriter writer(&stream, true);
    writer.Write(static_cast<SharpRuntime::intcs>(42));
    writer.Write(std::string("sharp"));
    writer.Flush();
    writer.Close();
}

stream.setPositionProperty(0);

System::IO::BinaryReader reader(&stream, true);
const auto number = reader.ReadInt32();
const auto text = reader.ReadString();

true is leaveOpen. It gives the writer and reader a borrowed stream rather than ownership of closure. The enclosing MemoryStream remains the owner.

Understand the binary protocol

Numeric primitives are little-endian. Strings are UTF-8 bytes prefixed by a 7-bit encoded byte length. ReadString validates the length and, on a seekable stream, refuses a declared length larger than the remaining bytes before attempting a huge allocation.

ToArray versus GetBuffer

MethodResultLifetime
ToArray()Independent vector copyUnaffected by later stream writes or destruction
GetBuffer()Const reference to live internal vectorWrites can reallocate and invalidate references into it

Both remain callable after MemoryStream::Close. Reads, writes, seeking, length, and position access then reject the disposed stream. CanWrite intentionally continues to report its original writability while CanRead and CanSeek become false, matching the documented source contract.

Start with existing bytes

The buffer constructor copies size bytes and is writable by default. A null pointer is accepted only for a zero-length source; negative lengths are rejected before any read. Because it copies, the source array can be released immediately after construction.

Test protocol failures

  • Truncated primitive and string payloads.
  • Malformed or overlong 7-bit encoded lengths.
  • Invalid UTF-8 character operations where used.
  • Close with leaveOpen true and false.
  • Position beyond current length followed by write/resize.