public JsonBinaryReader( ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) : base(skipValidation) { if (buffer.Length < 2) { throw new ArgumentException($"{nameof(buffer)} must have at least two byte."); } if (buffer.Span[0] != (byte)JsonSerializationFormat.Binary) { throw new ArgumentNullException("buffer must be binary encoded."); } // offset for the 0x80 (128) binary serialization type marker. buffer = buffer.Slice(1); // Only navigate the outer most json value and trim off trailing bytes int jsonValueLength = JsonBinaryEncoding.GetValueLength(buffer.Span); if (buffer.Length < jsonValueLength) { throw new ArgumentException("buffer is shorter than the length prefix."); } buffer = buffer.Slice(0, jsonValueLength); this.jsonBinaryBuffer = new JsonBinaryMemoryReader(buffer); this.arrayAndObjectEndStack = new Stack <int>(); this.jsonStringDictionary = jsonStringDictionary; }
/// <summary> /// Initializes a new instance of the JsonBinaryNavigator class /// </summary> /// <param name="buffer">The (UTF-8) buffer to navigate.</param> /// <param name="jsonStringDictionary">The JSON string dictionary.</param> /// <param name="skipValidation">whether to skip validation or not.</param> public JsonBinaryNavigator( ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary, bool skipValidation = false) { if (buffer.Length < 2) { throw new ArgumentException($"{nameof(buffer)} must have at least two byte."); } if (buffer.Span[0] != (byte)JsonSerializationFormat.Binary) { throw new ArgumentNullException("buffer must be binary encoded."); } // offset for the 0x80 (128) binary serialization type marker. buffer = buffer.Slice(1); // Only navigate the outer most json value and trim off trailing bytes int jsonValueLength = JsonBinaryEncoding.GetValueLength(buffer.Span); if (buffer.Length < jsonValueLength) { throw new ArgumentException("buffer is shorter than the length prefix."); } buffer = buffer.Slice(0, jsonValueLength); this.buffer = buffer; this.jsonStringDictionary = jsonStringDictionary; this.rootNode = new BinaryNavigatorNode(this.buffer, NodeTypes.GetNodeType(this.buffer.Span[0])); }
public static JsonStringDictionary CreateFromStringArray(IReadOnlyList <string> userStrings) { if (userStrings == null) { throw new ArgumentNullException(nameof(userStrings)); } JsonStringDictionary jsonStringDictionary = new JsonStringDictionary(userStrings.Count); for (int i = 0; i < userStrings.Count; i++) { string userString = userStrings[i]; if (!jsonStringDictionary.TryAddString(Encoding.UTF8.GetBytes(userString).AsSpan(), out int index)) { throw new ArgumentException($"Failed to add {userString} to {nameof(JsonStringDictionary)}."); } if (index != i) { throw new ArgumentException($"Tried to add {userString} at index {i}, but instead it was inserted at index {index}."); } } return(jsonStringDictionary); }
/// <summary> /// Creates a JsonReader that can read a supplied stream (assumes UTF-8 encoding). /// </summary> /// <param name="stream">the stream to read.</param> /// <param name="jsonStringDictionary">The dictionary to use for binary user string encoding.</param> /// <param name="skipvalidation">whether or not to skip validation.</param> /// <returns>a concrete JsonReader that can read the supplied stream.</returns> public static IJsonReader Create(Stream stream, JsonStringDictionary jsonStringDictionary = null, bool skipvalidation = false) { if (stream == null) { throw new ArgumentNullException("stream"); } BinaryReader tempBinaryReader = new BinaryReader(stream, Encoding.UTF8); // examine the first buffer byte to determine the serialization format byte firstbyte = tempBinaryReader.ReadByte(); // you have to rewind the stream since even "peeking" still reads it into the bufferedstream stream.Seek(0, SeekOrigin.Begin); // explicitly pick from the set of supported formats, or otherwise assume text format switch ((JsonSerializationFormat)firstbyte) { case JsonSerializationFormat.Binary: return(new JsonBinaryReader(stream, jsonStringDictionary, skipvalidation)); default: return(new JsonTextReader(stream, Encoding.UTF8, skipvalidation)); } }
/// <summary> /// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding). /// </summary> /// <param name="buffer">The byte array to read from.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="skipValidation">Whether or not to skip validation.</param> /// <returns>A concrete JsonReader that can read the supplied byte array.</returns> public static IJsonReader Create(ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) { byte firstByte = buffer.Span[0]; // Explicitly pick from the set of supported formats, or otherwise assume text format switch ((JsonSerializationFormat)firstByte) { case JsonSerializationFormat.Binary: return(new JsonBinaryReader(buffer, jsonStringDictionary, skipValidation)); default: return(new JsonTextReader(buffer, skipValidation)); } }
/// <summary> /// Try Get Encoded User String Type Marker /// </summary> /// <param name="utf8Span">The value.</param> /// <param name="jsonStringDictionary">The optional json string dictionary.</param> /// <param name="multiByteTypeMarker">The multi byte type marker if found.</param> /// <returns>Whether or not the Encoded User String Type Marker was found.</returns> private static bool TryGetEncodedUserStringTypeMarker( Utf8Span utf8Span, JsonStringDictionary jsonStringDictionary, out MultiByteTypeMarker multiByteTypeMarker) { if (jsonStringDictionary == null) { multiByteTypeMarker = default; return(false); } const int MinStringLength = 2; const int MaxStringLength = 128; if ((utf8Span.Length < MinStringLength) || (utf8Span.Length > MaxStringLength)) { multiByteTypeMarker = default; return(false); } const byte OneByteCount = TypeMarker.UserString1ByteLengthMax - TypeMarker.UserString1ByteLengthMin; if (!jsonStringDictionary.TryAddString(utf8Span, out int index)) { multiByteTypeMarker = default; return(false); } // Convert the index to a multibyte type marker if (index < OneByteCount) { multiByteTypeMarker = new MultiByteTypeMarker( length: 1, one: (byte)(TypeMarker.UserString1ByteLengthMin + index)); } else { int twoByteOffset = index - OneByteCount; multiByteTypeMarker = new MultiByteTypeMarker( length: 2, one: (byte)((twoByteOffset / 0xFF) + TypeMarker.UserString2ByteLengthMin), two: (byte)(twoByteOffset % 0xFF)); } return(true); }
/// <summary> /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text) /// </summary> /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="skipValidation">Whether or not to skip validation</param> /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns> public static IJsonWriter Create( JsonSerializationFormat jsonSerializationFormat, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) { switch (jsonSerializationFormat) { case JsonSerializationFormat.Text: return(new JsonTextWriter(Encoding.UTF8, skipValidation)); case JsonSerializationFormat.Binary: return(new JsonBinaryWriter(skipValidation, jsonStringDictionary, serializeCount: false)); default: throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat)); } }
/// <summary> /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text) /// </summary> /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param> /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns> public static IJsonWriter Create( JsonSerializationFormat jsonSerializationFormat, JsonStringDictionary jsonStringDictionary = null, int initalCapacity = 256) { return(jsonSerializationFormat switch { JsonSerializationFormat.Text => new JsonTextWriter(initalCapacity), JsonSerializationFormat.Binary => new JsonBinaryWriter( jsonStringDictionary, serializeCount: false), _ => throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat)), });
/// <summary> /// Try Get Encoded String Type Marker /// </summary> /// <param name="utf8Span">the value</param> /// <param name="jsonStringDictionary">The JSON string dictionary.</param> /// <param name="multiByteTypeMarker">The encoded string type marker if found.</param> /// <returns>Whether or not the type marker was found.</returns> public static bool TryGetEncodedStringTypeMarker( Utf8Span utf8Span, JsonStringDictionary jsonStringDictionary, out MultiByteTypeMarker multiByteTypeMarker) { if (JsonBinaryEncoding.TryGetEncodedSystemStringTypeMarker(utf8Span, out multiByteTypeMarker)) { return(true); } if (JsonBinaryEncoding.TryGetEncodedUserStringTypeMarker(utf8Span, jsonStringDictionary, out multiByteTypeMarker)) { return(true); } multiByteTypeMarker = default; return(false); }
/// <summary> /// Initializes a new instance of the JsonBinaryWriter class. /// </summary> /// <param name="jsonStringDictionary">The JSON string dictionary used for user string encoding.</param> /// <param name="serializeCount">Whether to serialize the count for object and array typemarkers.</param> public JsonBinaryWriter( JsonStringDictionary jsonStringDictionary = null, bool serializeCount = false) { this.binaryWriter = new JsonBinaryMemoryWriter(); this.bufferedContexts = new Stack <BeginOffsetAndCount>(); this.serializeCount = serializeCount; this.reservationSize = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength + (this.serializeCount ? JsonBinaryEncoding.OneByteCount : 0); // Write the serialization format as the very first byte byte binaryTypeMarker = (byte)JsonSerializationFormat.Binary; this.binaryWriter.Write(binaryTypeMarker); // Push on the outermost context this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength)); this.jsonStringDictionary = jsonStringDictionary; }
/// <summary> /// Initializes a new instance of the JsonBinaryWriter class. /// </summary> /// <param name="skipValidation">Whether to skip validation on the JsonObjectState.</param> /// <param name="jsonStringDictionary">The JSON string dictionary used for user string encoding.</param> /// <param name="serializeCount">Whether to serialize the count for object and array typemarkers.</param> public JsonBinaryWriter( bool skipValidation, JsonStringDictionary jsonStringDictionary = null, bool serializeCount = false) : base(skipValidation) { this.binaryWriter = new BinaryWriter(new MemoryStream()); this.bufferedContexts = new Stack <BeginOffsetAndCount>(); this.serializeCount = serializeCount; this.reservationSize = TypeMarker + TwoByteLength + (this.serializeCount ? TwoByteCount : 0); // Write the serialization format as the very first byte this.binaryWriter.Write((byte)JsonSerializationFormat.Binary); // Push on the outermost context this.bufferedContexts.Push(new BeginOffsetAndCount(this.CurrentLength)); this.jsonStringDictionary = jsonStringDictionary; }
/// <summary> /// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding). /// </summary> /// <param name="buffer">The byte array to read from.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <returns>A concrete JsonReader that can read the supplied byte array.</returns> public static IJsonReader Create(ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary = null) { if (buffer.IsEmpty) { throw new ArgumentOutOfRangeException($"{nameof(buffer)} can not be empty."); } byte firstByte = buffer.Span[0]; // Explicitly pick from the set of supported formats, or otherwise assume text format switch ((JsonSerializationFormat)firstByte) { case JsonSerializationFormat.Binary: return(new JsonBinaryReader(buffer, jsonStringDictionary)); default: return(new JsonTextReader(buffer)); } }
/// <summary> /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text) /// </summary> /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param> /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns> public static IJsonWriter Create( JsonSerializationFormat jsonSerializationFormat, JsonStringDictionary jsonStringDictionary = null, int initalCapacity = 256) { switch (jsonSerializationFormat) { case JsonSerializationFormat.Text: return(new JsonTextWriter(initalCapacity)); case JsonSerializationFormat.Binary: return(new JsonBinaryWriter( jsonStringDictionary, serializeCount: false)); default: throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, RMResources.UnexpectedJsonSerializationFormat, jsonSerializationFormat)); } }
/// <summary> /// Creates a JsonReader that can read from the supplied byte array (assumes utf-8 encoding). /// </summary> /// <param name="buffer">The byte array to read from.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="skipValidation">Whether or not to skip validation.</param> /// <returns>A concrete JsonReader that can read the supplied byte array.</returns> public static IJsonReader Create(byte[] buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) { if (buffer == null) { throw new ArgumentNullException("buffer"); } byte firstByte = buffer[0]; // Explicitly pick from the set of supported formats, or otherwise assume text format switch ((JsonSerializationFormat)firstByte) { case JsonSerializationFormat.Binary: return(new JsonBinaryReader(buffer, jsonStringDictionary, skipValidation)); default: return(new JsonTextReader(buffer, skipValidation)); } }
/// <summary> /// Creates a JsonNavigator that can navigate a supplied buffer /// </summary> /// <param name="buffer">The buffer to navigate</param> /// <param name="jsonStringDictionary">The optional json string dictionary for binary encoding.</param> /// <param name="skipValidation">Whether validation should be skipped.</param> /// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns> public static IJsonNavigator Create( ReadOnlyMemory <byte> buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) { // Examine the first buffer byte to determine the serialization format byte firstByte = buffer.Span[0]; switch ((JsonSerializationFormat)firstByte) { // Explicitly pick from the set of supported formats case JsonSerializationFormat.Binary: return(new JsonBinaryNavigator(buffer, jsonStringDictionary, skipValidation)); default: // or otherwise assume text format return(new JsonTextNavigator(buffer, skipValidation)); } }
/// <summary> /// Initializes a new instance of the JsonBinaryNavigator class /// </summary> /// <param name="buffer">The (UTF-8) buffer to navigate.</param> /// <param name="jsonStringDictionary">The JSON string dictionary.</param> /// <param name="skipValidation">whether to skip validation or not.</param> public JsonBinaryNavigator(byte[] buffer, JsonStringDictionary jsonStringDictionary, bool skipValidation = false) { if (buffer == null) { throw new ArgumentNullException($"{nameof(buffer)} can not be null"); } if (buffer.Length < 1) { throw new ArgumentException($"{nameof(buffer)} must have at least one byte."); } this.rootNode = new BinaryNode(1, JsonBinaryEncoding.GetNodeType(buffer[1])); // false, since stream is not writeable // true, since buffer is visible this.binaryReader = new LittleEndianBinaryReader(new MemoryStream(buffer, 0, buffer.Length, false, true)); this.buffer = buffer; this.jsonStringDictionary = jsonStringDictionary; }
/// <summary> /// Creates a JsonNavigator that can navigate a supplied buffer /// </summary> /// <param name="buffer">The buffer to navigate</param> /// <param name="jsonStringDictionary">The optional json string dictionary for binary encoding.</param> /// <param name="skipValidation">Whether validation should be skipped.</param> /// <returns>A concrete JsonNavigator that can navigate the supplied buffer.</returns> public static IJsonNavigator Create(byte[] buffer, JsonStringDictionary jsonStringDictionary = null, bool skipValidation = false) { if (buffer == null) { throw new ArgumentNullException("buffer"); } // Examine the first buffer byte to determine the serialization format byte firstByte = buffer[0]; switch ((JsonSerializationFormat)firstByte) { // Explicitly pick from the set of supported formats case JsonSerializationFormat.Binary: return(new JsonBinaryNavigator(buffer, jsonStringDictionary, skipValidation)); default: // or otherwise assume text format return(new JsonTextNavigator(buffer, skipValidation)); } }
/// <summary> /// Creates a JsonWriter that can write in a particular JsonSerializationFormat (utf8 if text) /// </summary> /// <param name="jsonSerializationFormat">The JsonSerializationFormat of the writer.</param> /// <param name="jsonStringDictionary">The dictionary to use for user string encoding.</param> /// <param name="initalCapacity">Initial capacity to help avoid intermeidary allocations.</param> /// <returns>A JsonWriter that can write in a particular JsonSerializationFormat</returns> public static IJsonWriter Create( JsonSerializationFormat jsonSerializationFormat, JsonStringDictionary jsonStringDictionary = null, int initalCapacity = 256) => jsonSerializationFormat switch {