public ObjectPropertyInternal( BinaryNavigatorNode nameNode, BinaryNavigatorNode valueNode) { this.NameNode = nameNode; this.ValueNode = valueNode; }
/// <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])); }
private IEnumerable <BinaryNavigatorNode> GetArrayItemsInternal(ReadOnlyMemory <byte> buffer) { byte typeMarker = buffer.Span[0]; int firstArrayItemOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker); int arrayLength = JsonBinaryEncoding.GetValueLength(buffer.Span); // Scope to just the array buffer = buffer.Slice(0, (int)arrayLength); // Seek to the first array item buffer = buffer.Slice(firstArrayItemOffset); while (buffer.Length != 0) { int arrayItemLength = JsonBinaryEncoding.GetValueLength(buffer.Span); if (arrayItemLength > buffer.Length) { // Array Item got cut off. throw new JsonInvalidTokenException(); } // Create a buffer for that array item BinaryNavigatorNode arrayItem = new BinaryNavigatorNode( buffer.Slice(0, arrayItemLength), NodeTypes.GetNodeType(buffer.Span[0])); yield return(arrayItem); // Slice off the array item buffer = buffer.Slice(arrayItemLength); } }
private static bool IsStringOrNested(BinaryNavigatorNode binaryNavigatorNode) { switch (binaryNavigatorNode.JsonNodeType) { case JsonNodeType.String: case JsonNodeType.FieldName: case JsonNodeType.Array: case JsonNodeType.Object: return(true); default: return(false); } }
private bool TryGetBufferedRawJsonInternal( BinaryNavigatorNode binaryNavigatorNode, out ReadOnlyMemory <byte> bufferedRawJson) { if ((this.jsonStringDictionary != null) && JsonBinaryNavigator.IsStringOrNested(binaryNavigatorNode)) { // Force a rewrite for dictionary encoding. bufferedRawJson = default; return(false); } ReadOnlyMemory <byte> buffer = binaryNavigatorNode.Buffer; if (buffer.Length == 0) { throw new ArgumentException($"Node must not be empty."); } bufferedRawJson = buffer; return(true); }
private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWriter jsonWriter) { ReadOnlyMemory <byte> buffer = binaryNavigatorNode.Buffer; JsonNodeType nodeType = binaryNavigatorNode.JsonNodeType; switch (nodeType) { case JsonNodeType.Null: jsonWriter.WriteNullValue(); break; case JsonNodeType.False: jsonWriter.WriteBoolValue(false); break; case JsonNodeType.True: jsonWriter.WriteBoolValue(true); break; case JsonNodeType.Number64: { Number64 value = JsonBinaryEncoding.GetNumberValue(buffer.Span); jsonWriter.WriteNumber64Value(value); } break; case JsonNodeType.String: case JsonNodeType.FieldName: bool fieldName = binaryNavigatorNode.JsonNodeType == JsonNodeType.FieldName; if (JsonBinaryEncoding.TryGetBufferedStringValue( this.rootBuffer, buffer, out Utf8Memory bufferedStringValue)) { if (fieldName) { jsonWriter.WriteFieldName(bufferedStringValue.Span); } else { jsonWriter.WriteStringValue(bufferedStringValue.Span); } } else { string value = JsonBinaryEncoding.GetStringValue( this.rootBuffer, buffer); if (fieldName) { jsonWriter.WriteFieldName(value); } else { jsonWriter.WriteStringValue(value); } } break; case JsonNodeType.Array: { jsonWriter.WriteArrayStart(); foreach (BinaryNavigatorNode arrayItem in this.GetArrayItemsInternal(buffer)) { this.WriteToInternal(arrayItem, jsonWriter); } jsonWriter.WriteArrayEnd(); } break; case JsonNodeType.Object: { jsonWriter.WriteObjectStart(); foreach (ObjectPropertyInternal objectProperty in this.GetObjectPropertiesInternal(buffer)) { this.WriteToInternal(objectProperty.NameNode, jsonWriter); this.WriteToInternal(objectProperty.ValueNode, jsonWriter); } jsonWriter.WriteObjectEnd(); } break; case JsonNodeType.Int8: { sbyte value = JsonBinaryEncoding.GetInt8Value(buffer.Span); jsonWriter.WriteInt8Value(value); } break; case JsonNodeType.Int16: { short value = JsonBinaryEncoding.GetInt16Value(buffer.Span); jsonWriter.WriteInt16Value(value); } break; case JsonNodeType.Int32: { int value = JsonBinaryEncoding.GetInt32Value(buffer.Span); jsonWriter.WriteInt32Value(value); } break; case JsonNodeType.Int64: { long value = JsonBinaryEncoding.GetInt64Value(buffer.Span); jsonWriter.WriteInt64Value(value); } break; case JsonNodeType.UInt32: { uint value = JsonBinaryEncoding.GetUInt32Value(buffer.Span); jsonWriter.WriteUInt32Value(value); } break; case JsonNodeType.Float32: { float value = JsonBinaryEncoding.GetFloat32Value(buffer.Span); jsonWriter.WriteFloat32Value(value); } break; case JsonNodeType.Float64: { double value = JsonBinaryEncoding.GetFloat64Value(buffer.Span); jsonWriter.WriteFloat64Value(value); } break; case JsonNodeType.Binary: { ReadOnlyMemory <byte> value = JsonBinaryEncoding.GetBinaryValue(buffer); jsonWriter.WriteBinaryValue(value.Span); } break; case JsonNodeType.Guid: { Guid value = JsonBinaryEncoding.GetGuidValue(buffer.Span); jsonWriter.WriteGuidValue(value); } break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(JsonNodeType)}: {nodeType}."); } }
private void WriteToInternal(BinaryNavigatorNode binaryNavigatorNode, IJsonWriter jsonWriter, bool sameEncoding) { ReadOnlyMemory <byte> buffer = binaryNavigatorNode.Buffer; JsonNodeType nodeType = binaryNavigatorNode.JsonNodeType; if (sameEncoding && this.TryGetBufferedRawJsonInternal(binaryNavigatorNode, out ReadOnlyMemory <byte> bufferedRawJson)) { // Token type doesn't make any difference other than whether it's a value or field name JsonTokenType tokenType = nodeType == JsonNodeType.FieldName ? JsonTokenType.FieldName : JsonTokenType.String; jsonWriter.WriteRawJsonToken(tokenType, bufferedRawJson.Span); return; } switch (nodeType) { case JsonNodeType.Null: jsonWriter.WriteNullValue(); break; case JsonNodeType.False: jsonWriter.WriteBoolValue(false); break; case JsonNodeType.True: jsonWriter.WriteBoolValue(true); break; case JsonNodeType.Number64: { Number64 value = JsonBinaryEncoding.GetNumberValue(buffer.Span); jsonWriter.WriteNumber64Value(value); } break; case JsonNodeType.String: case JsonNodeType.FieldName: bool fieldName = binaryNavigatorNode.JsonNodeType == JsonNodeType.FieldName; Utf8Memory utf8Buffer = Utf8Memory.UnsafeCreateNoValidation(buffer); if (JsonBinaryEncoding.TryGetBufferedStringValue( utf8Buffer, this.jsonStringDictionary, out Utf8Memory bufferedStringValue)) { if (fieldName) { jsonWriter.WriteFieldName(bufferedStringValue.Span); } else { jsonWriter.WriteStringValue(bufferedStringValue.Span); } } else { string value = JsonBinaryEncoding.GetStringValue( utf8Buffer, this.jsonStringDictionary); if (fieldName) { jsonWriter.WriteFieldName(value); } else { jsonWriter.WriteStringValue(value); } } break; case JsonNodeType.Array: { jsonWriter.WriteArrayStart(); foreach (BinaryNavigatorNode arrayItem in this.GetArrayItemsInternal(buffer)) { this.WriteToInternal(arrayItem, jsonWriter, sameEncoding); } jsonWriter.WriteArrayEnd(); } break; case JsonNodeType.Object: { jsonWriter.WriteObjectStart(); foreach (ObjectPropertyInternal objectProperty in this.GetObjectPropertiesInternal(buffer)) { this.WriteToInternal(objectProperty.NameNode, jsonWriter, sameEncoding); this.WriteToInternal(objectProperty.ValueNode, jsonWriter, sameEncoding); } jsonWriter.WriteObjectEnd(); } break; case JsonNodeType.Int8: { sbyte value = JsonBinaryEncoding.GetInt8Value(buffer.Span); jsonWriter.WriteInt8Value(value); } break; case JsonNodeType.Int16: { short value = JsonBinaryEncoding.GetInt16Value(buffer.Span); jsonWriter.WriteInt16Value(value); } break; case JsonNodeType.Int32: { int value = JsonBinaryEncoding.GetInt32Value(buffer.Span); jsonWriter.WriteInt32Value(value); } break; case JsonNodeType.Int64: { long value = JsonBinaryEncoding.GetInt64Value(buffer.Span); jsonWriter.WriteInt64Value(value); } break; case JsonNodeType.UInt32: { uint value = JsonBinaryEncoding.GetUInt32Value(buffer.Span); jsonWriter.WriteUInt32Value(value); } break; case JsonNodeType.Float32: { float value = JsonBinaryEncoding.GetFloat32Value(buffer.Span); jsonWriter.WriteFloat32Value(value); } break; case JsonNodeType.Float64: { double value = JsonBinaryEncoding.GetFloat64Value(buffer.Span); jsonWriter.WriteFloat64Value(value); } break; case JsonNodeType.Binary: { ReadOnlyMemory <byte> value = JsonBinaryEncoding.GetBinaryValue(buffer); jsonWriter.WriteBinaryValue(value.Span); } break; case JsonNodeType.Guid: { Guid value = JsonBinaryEncoding.GetGuidValue(buffer.Span); jsonWriter.WriteGuidValue(value); } break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(JsonNodeType)}: {nodeType}."); } }