Struct MsgPackDecoder
- Namespace
- ShapeShift.MsgPack
- Assembly
- ShapeShift.MsgPack.dll
Reads MessagePack tokens from contiguous memory or from a potentially segmented ReadOnlySequence<T>.
public ref struct MsgPackDecoder : IDecoder
- Implements
- Inherited Members
Remarks
Segmented input is walked in place. This decoder never consolidates a ReadOnlySequence<T> into one contiguous buffer, so skipping over (or seeking past) content that a caller does not want costs nothing but pointer arithmetic, no matter how the input happens to be chopped into segments. Only a value that is actually materialized (a string, a byte array, an extension payload) is copied, and even then only when that one value straddles a segment boundary.
Constructors
MsgPackDecoder(in ReadOnlySequence<byte>)
Initializes a new instance of the MsgPackDecoder struct.
public MsgPackDecoder(in ReadOnlySequence<byte> messagePack)
Parameters
messagePackReadOnlySequence<byte>The encoded MessagePack value, which may be split across any number of segments.
Remarks
Multi-segment input is read in place; it is never copied into one contiguous buffer.
MsgPackDecoder(ReadOnlySpan<byte>)
Initializes a new instance of the MsgPackDecoder struct.
public MsgPackDecoder(ReadOnlySpan<byte> messagePack)
Parameters
messagePackReadOnlySpan<byte>The encoded MessagePack value.
Properties
NextTokenType
Gets the type of the next token without consuming it.
public readonly TokenType NextTokenType { get; }
Property Value
- TokenType
The token that the next
Readcall would consume, or EndDocument once the input has been fully consumed.
Exceptions
- DecoderException
Thrown when the next bytes are not a recognizable token.
UnreadLength
Gets the number of unread bytes remaining in the input.
public readonly long UnreadLength { get; }
Property Value
UnreadSpan
Gets the unread bytes that are contiguously available at the decoder's current position.
public readonly ReadOnlySpan<byte> UnreadSpan { get; }
Property Value
Remarks
For a decoder created over contiguous memory this is all the unread input. For a decoder created over a segmented ReadOnlySequence<T> this is only the remainder of the current segment, which may be shorter than UnreadLength.
Methods
EnsureEndOfDocument()
Verifies that one complete MessagePack value consumed the input.
public readonly void EnsureEndOfDocument()
ReadBigInteger()
Consumes an arbitrarily large integer.
public BigInteger ReadBigInteger()
Returns
- BigInteger
The value.
Exceptions
- DecoderException
Thrown when the next token is not an integer.
ReadBoolean()
Consumes a Boolean.
public bool ReadBoolean()
Returns
- bool
The value.
Exceptions
- DecoderException
Thrown when the next token is not a Boolean.
ReadByteArray()
Reads a binary value.
public byte[] ReadByteArray()
Returns
- byte[]
The decoded bytes.
Exceptions
- NotSupportedException
Thrown when the format has no binary representation.
ReadCharSpan()
Consumes text without necessarily allocating a string.
public ReadOnlySpan<char> ReadCharSpan()
Returns
- ReadOnlySpan<char>
The text. The span is valid only until the next read.
Exceptions
- DecoderException
Thrown when the next token is not a string.
ReadDateTime()
Consumes a date and time.
public DateTime ReadDateTime()
Returns
- DateTime
The value.
Exceptions
- DecoderException
Thrown when the next token is not one this format writes dates as.
ReadDecimal()
Consumes an exact decimal number.
public decimal ReadDecimal()
Returns
- decimal
The value.
Exceptions
- DecoderException
Thrown when the next token is not a number a decimal can hold.
ReadDouble()
Consumes a double-precision floating-point number.
public double ReadDouble()
Returns
- double
The value.
Exceptions
- DecoderException
Thrown when the next token is not a number.
ReadDynamicNumber()
Reads a number while preserving the representation available from the format.
public ShapeShiftNumber ReadDynamicNumber()
Returns
- ShapeShiftNumber
The dynamic number.
Remarks
This is what ShapeShiftValue and unknown-property retention use, so a value that arrived as a wide or unsigned integer can be written back the way it came. The default implementation narrows everything to decimal; override it to keep the width the payload actually used.
ReadEndMap()
Consumes the end of the innermost open map.
public void ReadEndMap()
Remarks
A format whose maps are length-prefixed has no end token on the wire and synthesizes one, so callers may always read the end token they saw reported by NextTokenType.
Exceptions
- DecoderException
Thrown when the map is not positioned at its end.
ReadEndVector()
Consumes the end of the innermost open vector.
public void ReadEndVector()
Exceptions
- DecoderException
Thrown when the vector is not positioned at its end.
ReadExtension(sbyte)
Reads an extension value of an expected type code.
public byte[] ReadExtension(sbyte expectedTypeCode)
Parameters
expectedTypeCodesbyteThe extension type code the caller requires.
Returns
- byte[]
The extension's payload.
Exceptions
- DecoderException
Thrown when the next value is not an extension, carries a different type code, or ends prematurely.
ReadExtension(sbyte, scoped Span<byte>)
Reads an extension value of an expected type code into a caller-supplied buffer.
public int ReadExtension(sbyte expectedTypeCode, scoped Span<byte> destination)
Parameters
expectedTypeCodesbyteThe extension type code the caller requires.
destinationSpan<byte>A buffer that receives the payload. It must be at least as long as the payload.
Returns
- int
The number of bytes written to
destination.
Exceptions
- DecoderException
Thrown when the next value is not an extension, carries a different type code, ends prematurely, or has a payload longer than
destination.
ReadHalf()
Consumes a half-precision floating-point number.
public Half ReadHalf()
Returns
- Half
The value.
Exceptions
- DecoderException
Thrown when the next token is not a number.
ReadInt128()
Consumes a signed 128-bit integer.
public Int128 ReadInt128()
Returns
- Int128
The value.
Exceptions
- DecoderException
Thrown when the next token is not an integer this width can hold.
ReadInt64()
Consumes a signed 64-bit integer.
public long ReadInt64()
Returns
- long
The value.
Exceptions
- DecoderException
Thrown when the next token is not an integer this width can hold.
ReadNull()
Consumes a null.
public void ReadNull()
Remarks
The default implementation defers to TryReadNull(), which consumes the token, and throws when it reports false. A decoder overrides it only to produce a more precise error message.
Exceptions
- DecoderException
Thrown when the next token is not Null.
ReadPropertyName()
Consumes the name of the map entry whose value comes next.
public ReadOnlySpan<char> ReadPropertyName()
Returns
- ReadOnlySpan<char>
The property name. The span is valid only until the next read.
Exceptions
- DecoderException
Thrown when the decoder is not positioned at a map key.
ReadSingle()
Consumes a single-precision floating-point number.
public float ReadSingle()
Returns
- float
The value.
Exceptions
- DecoderException
Thrown when the next token is not a number.
ReadStartMap()
Consumes the beginning of a map.
public int? ReadStartMap()
Returns
- int?
The number of entries the map declares, or null when the format does not declare one. A count, once reported, must be correct.
Exceptions
- DecoderException
Thrown when the next token is not StartMap.
ReadStartVector()
Consumes the beginning of a vector.
public int? ReadStartVector()
Returns
- int?
The number of elements the vector declares, or null when the format does not declare one. A count, once reported, must be correct.
Exceptions
- DecoderException
Thrown when the next token is not StartVector.
ReadString()
Consumes a string.
public string ReadString()
Returns
- string
The value.
Exceptions
- DecoderException
Thrown when the next token is not a string.
ReadTimeSpan()
Consumes a duration.
public TimeSpan ReadTimeSpan()
Returns
- TimeSpan
The value.
Exceptions
- DecoderException
Thrown when the next token is not one this format writes durations as.
ReadUInt128()
Consumes an unsigned 128-bit integer.
public UInt128 ReadUInt128()
Returns
- UInt128
The value.
Exceptions
- DecoderException
Thrown when the next token is not an integer this width can hold.
ReadUInt64()
Consumes an unsigned 64-bit integer.
public ulong ReadUInt64()
Returns
- ulong
The value.
Exceptions
- DecoderException
Thrown when the next token is not an integer this width can hold.
Skip()
Consumes the next value in its entirety, however deeply nested, without converting it.
public void Skip()
Remarks
Unknown-property retention, positional contracts, and ShapeShiftPath traversal all build on this, so it is worth implementing in terms of declared widths rather than by decoding each value. A skip walks attacker-controlled structure, so bound its nesting.
Exceptions
- DecoderException
Thrown when there is no value to skip, or the value is malformed.
TryPeekExtensionHeader(out MsgPackExtensionHeader)
Describes the extension value the decoder is positioned at, if any, without consuming it.
public readonly bool TryPeekExtensionHeader(out MsgPackExtensionHeader header)
Parameters
headerMsgPackExtensionHeaderReceives the extension's type code and payload length.
Returns
Remarks
This is a low-level building block for custom converters that define their own extension encodings. See MsgPackExtensionCodes for the codes ShapeShift itself reserves.
Exceptions
- DecoderException
Thrown when the input ends in the middle of the extension's header.
TryReadNull()
Consumes the next token if -- and only if -- it is a null.
public bool TryReadNull()
Returns
- bool
true when the next token was Null and has now been consumed; false when it was anything else, in which case nothing was consumed and the decoder is left exactly where it was.
Remarks
These are the conventional Try semantics: this is ReadNull() without the throw.
A true answer means the null is gone, so the caller must not follow it with
ReadNull().
A converter that needs to know whether a null is coming without consuming it -- because it intends to hand the token to another converter -- asks NextTokenType instead, which is the peek.
Exceptions
- DecoderException
Thrown when the next bytes are not a recognizable token.