Round-trip Data with MemoryStream
Build a small in-memory binary protocol while preserving stream and wrapper lifetimes.
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
| Method | Result | Lifetime |
|---|---|---|
ToArray() | Independent vector copy | Unaffected by later stream writes or destruction |
GetBuffer() | Const reference to live internal vector | Writes 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
leaveOpentrue and false. - Position beyond current length followed by write/resize.