Пример #1
0
            /// <inheritdoc />
            public override bool TryGetObjectProperty(
                IJsonNavigatorNode objectNode,
                string propertyName,
                out ObjectProperty objectProperty)
            {
                _ = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                Utf8Span utf8StringPropertyName = Utf8Span.TranscodeUtf16(propertyName);

                foreach (ObjectProperty objectPropertyNode in this.GetObjectProperties(objectNode))
                {
                    if (this.TryGetBufferedStringValue(objectPropertyNode.NameNode, out Utf8Memory bufferedUtf8StringValue))
                    {
                        // First try and see if we can avoid materializing the UTF16 string.
                        if (utf8StringPropertyName.Equals(bufferedUtf8StringValue.Span))
                        {
                            objectProperty = objectPropertyNode;
                            return(true);
                        }
                    }
                    else
                    {
                        if (this.GetStringValue(objectPropertyNode.NameNode) == propertyName)
                        {
                            objectProperty = objectPropertyNode;
                            return(true);
                        }
                    }
                }

                objectProperty = default;
                return(false);
            }
Пример #2
0
            /// <inheritdoc />
            public override bool TryGetBufferedRawJson(
                IJsonNavigatorNode jsonNode,
                out ReadOnlyMemory <byte> bufferedRawJson)
            {
                if (jsonNode == null)
                {
                    throw new ArgumentNullException(nameof(jsonNode));
                }

                if (!(jsonNode is BinaryNavigatorNode binaryNavigatorNode))
                {
                    throw new ArgumentException($"{nameof(jsonNode)} must be a {nameof(BinaryNavigatorNode)}");
                }

                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);
            }
Пример #3
0
            /// <inheritdoc />
            public override bool TryGetObjectProperty(
                IJsonNavigatorNode objectNode,
                string propertyName,
                out ObjectProperty objectProperty)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                ReadOnlySpan <byte> utf8StringPropertyName = Encoding.UTF8.GetBytes(propertyName);

                foreach (ObjectProperty objectPropertyNode in this.GetObjectProperties(objectNode))
                {
                    if (this.TryGetBufferedUtf8StringValue(objectPropertyNode.NameNode, out ReadOnlyMemory <byte> bufferedUtf8StringValue))
                    {
                        // First try and see if we can avoid materializing the UTF16 string.
                        if (utf8StringPropertyName.SequenceEqual(bufferedUtf8StringValue.Span))
                        {
                            objectProperty = objectPropertyNode;
                            return(true);
                        }
                    }
                    else
                    {
                        if (this.GetStringValue(objectPropertyNode.NameNode) == propertyName)
                        {
                            objectProperty = objectPropertyNode;
                            return(true);
                        }
                    }
                }

                objectProperty = default(ObjectProperty);
                return(false);
            }
            /// <inheritdoc />
            public override IEnumerable <ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                byte typeMarker       = buffer.Span[0];
                int  firstValueOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker);

                buffer = buffer.Slice(firstValueOffset);
                while (buffer.Length != 0)
                {
                    int nameNodeLength = JsonBinaryEncoding.GetValueLength(buffer.Span);
                    if (nameNodeLength > buffer.Length)
                    {
                        throw new JsonInvalidTokenException();
                    }
                    ReadOnlyMemory <byte> nameNode = buffer.Slice(0, nameNodeLength);
                    buffer = buffer.Slice(nameNodeLength);

                    int valueNodeLength = JsonBinaryEncoding.GetValueLength(buffer.Span);
                    if (valueNodeLength > buffer.Length)
                    {
                        throw new JsonInvalidTokenException();
                    }
                    ReadOnlyMemory <byte> valueNode = buffer.Slice(0, valueNodeLength);
                    buffer = buffer.Slice(valueNodeLength);

                    yield return(new ObjectProperty(
                                     new BinaryNavigatorNode(nameNode, JsonNodeType.FieldName),
                                     new BinaryNavigatorNode(valueNode, NodeTypes.GetNodeType(valueNode.Span[0]))));
                }
            }
            /// <inheritdoc />
            public override string GetStringValue(IJsonNavigatorNode stringNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.String,
                    stringNode);

                return(JsonBinaryEncoding.GetStringValue(buffer.Span, this.jsonStringDictionary));
            }
            /// <inheritdoc />
            public override uint GetUInt32Value(IJsonNavigatorNode numberNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.UInt32,
                    numberNode);

                return(JsonBinaryEncoding.GetUInt32Value(buffer.Span));
            }
            /// <inheritdoc />
            public override Guid GetGuidValue(IJsonNavigatorNode guidNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Guid,
                    guidNode);

                return(JsonBinaryEncoding.GetGuidValue(buffer.Span));
            }
Пример #8
0
            /// <inheritdoc />
            public override IEnumerable <IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Array,
                    arrayNode);

                return(this.GetArrayItemsInternal(buffer).Select((node) => (IJsonNavigatorNode)node));
            }
            /// <inheritdoc />
            public override double GetFloat64Value(IJsonNavigatorNode numberNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Float64,
                    numberNode);

                return(JsonBinaryEncoding.GetFloat64Value(buffer.Span));
            }
            /// <inheritdoc />
            public override int GetObjectPropertyCount(IJsonNavigatorNode objectNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                byte typeMarker = buffer.Span[0];
                int  firstObjectPropertyOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
                long count;

                switch (typeMarker)
                {
                // Empty and Single Object
                case JsonBinaryEncoding.TypeMarker.EmptyObject:
                    count = 0;
                    break;

                case JsonBinaryEncoding.TypeMarker.SinglePropertyObject:
                    // This number gets divided by 2 later.
                    count = 2;
                    break;

                // Object with length and count prefix
                case JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount:
                    count = MemoryMarshal.Read <byte>(buffer
                                                      .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength).Span);
                    break;

                case JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount:
                    count = MemoryMarshal.Read <ushort>(buffer
                                                        .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength).Span);
                    break;

                case JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount:
                    count = MemoryMarshal.Read <uint>(buffer
                                                      .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength).Span);
                    break;

                // Object with length prefix
                case JsonBinaryEncoding.TypeMarker.Object1ByteLength:
                case JsonBinaryEncoding.TypeMarker.Object2ByteLength:
                case JsonBinaryEncoding.TypeMarker.Object4ByteLength:
                    count = JsonBinaryNavigator.GetValueCount(buffer.Slice(firstObjectPropertyOffset).Span);
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected object type marker: {typeMarker}");
                }

                // Divide by 2 since the count includes fieldname and value as seperate entities
                count = count / 2;
                if (count > int.MaxValue)
                {
                    throw new InvalidOperationException("count can not be more than int.MaxValue");
                }

                return((int)count);
            }
Пример #11
0
            /// <inheritdoc />
            public override bool TryGetBufferedUtf8StringValue(
                IJsonNavigatorNode stringNode,
                out ReadOnlyMemory <byte> bufferedUtf8StringValue)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.String,
                    stringNode);

                return(JsonBinaryEncoding.TryGetBufferedUtf8StringValue(buffer, this.jsonStringDictionary, out bufferedUtf8StringValue));
            }
Пример #12
0
            /// <inheritdoc />
            public override string GetStringValue(IJsonNavigatorNode stringNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.String,
                    stringNode);

                return(JsonBinaryEncoding.GetStringValue(
                           Utf8Memory.UnsafeCreateNoValidation(buffer),
                           this.jsonStringDictionary));
            }
Пример #13
0
            /// <inheritdoc />
            public override UtfAnyString GetStringValue(IJsonNavigatorNode stringNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.String,
                    stringNode);

                return(JsonBinaryEncoding.GetUtf8StringValue(
                           this.rootBuffer,
                           buffer));
            }
            /// <inheritdoc />
            public override int GetArrayItemCount(IJsonNavigatorNode arrayNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Array,
                    arrayNode);
                byte typeMarker       = buffer.Span[0];
                int  firstValueOffset = JsonBinaryEncoding.GetFirstValueOffset(typeMarker);
                long count;

                switch (typeMarker)
                {
                // Empty and Single Array
                case JsonBinaryEncoding.TypeMarker.EmptyArray:
                    count = 0;
                    break;

                case JsonBinaryEncoding.TypeMarker.SingleItemArray:
                    count = 1;
                    break;

                // Arrays with length and count prefix
                case JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount:
                    count = MemoryMarshal.Read <byte>(buffer
                                                      .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength).Span);
                    break;

                case JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount:
                    count = MemoryMarshal.Read <ushort>(buffer
                                                        .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength).Span);
                    break;

                case JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount:
                    count = MemoryMarshal.Read <uint>(buffer
                                                      .Slice(JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength).Span);
                    break;

                // Arrays with length prefix
                case JsonBinaryEncoding.TypeMarker.Array1ByteLength:
                case JsonBinaryEncoding.TypeMarker.Array2ByteLength:
                case JsonBinaryEncoding.TypeMarker.Array4ByteLength:
                    count = JsonBinaryNavigator.GetValueCount(buffer.Slice(firstValueOffset).Span);
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected array type marker: {typeMarker}");
                }

                if (count > int.MaxValue)
                {
                    throw new InvalidOperationException("count can not be more than int.MaxValue");
                }

                return((int)count);
            }
            public override bool TryGetBufferedBinaryValue(
                IJsonNavigatorNode binaryNode,
                out ReadOnlyMemory <byte> bufferedBinaryValue)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Binary,
                    binaryNode);

                bufferedBinaryValue = JsonBinaryEncoding.GetBinaryValue(buffer);
                return(true);
            }
Пример #16
0
            /// <inheritdoc />
            public override IEnumerable <ObjectProperty> GetObjectProperties(IJsonNavigatorNode objectNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                return(this.GetObjectPropertiesInternal(buffer)
                       .Select((objectPropertyInternal) => new ObjectProperty(
                                   objectPropertyInternal.NameNode,
                                   objectPropertyInternal.ValueNode)));
            }
Пример #17
0
            /// <inheritdoc />
            public override bool TryGetBufferedStringValue(
                IJsonNavigatorNode stringNode,
                out Utf8Memory value)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.String,
                    stringNode);

                return(JsonBinaryEncoding.TryGetBufferedStringValue(
                           this.rootBuffer,
                           buffer,
                           out value));
            }
            /// <inheritdoc />
            public override bool TryGetObjectProperty(
                IJsonNavigatorNode objectNode,
                string propertyName,
                out ObjectProperty objectProperty)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Object,
                    objectNode);

                foreach (ObjectProperty objectPropertyNode in this.GetObjectProperties(objectNode))
                {
                    if (this.GetStringValue(objectPropertyNode.NameNode) == propertyName)
                    {
                        objectProperty = objectPropertyNode;
                        return(true);
                    }
                }

                objectProperty = default(ObjectProperty);
                return(false);
            }
            /// <inheritdoc />
            public override IJsonNavigatorNode GetArrayItemAt(IJsonNavigatorNode arrayNode, int index)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Array,
                    arrayNode);

                if (index < 0)
                {
                    throw new IndexOutOfRangeException();
                }

                // TODO (brchon): We can optimize for the case where the count is serialized so we can avoid using the linear time call to TryGetValueAt().
                if (!JsonBinaryNavigator.TryGetValueAt(buffer, index, out ReadOnlyMemory <byte> arrayItem))
                {
                    throw new IndexOutOfRangeException($"Tried to access index:{index} in an array.");
                }

                return(new BinaryNavigatorNode(
                           arrayItem,
                           NodeTypes.GetNodeType(arrayItem.Span[0])));
            }
Пример #20
0
            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);
            }
            /// <inheritdoc />
            public override IEnumerable <IJsonNavigatorNode> GetArrayItems(IJsonNavigatorNode arrayNode)
            {
                ReadOnlyMemory <byte> buffer = JsonBinaryNavigator.GetNodeOfType(
                    JsonNodeType.Array,
                    arrayNode);

                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
                    IJsonNavigatorNode arrayItem = new BinaryNavigatorNode(
                        buffer.Slice(0, arrayItemLength),
                        NodeTypes.GetNodeType(buffer.Span[0]));
                    yield return(arrayItem);

                    // Slice off the array item
                    buffer = buffer.Slice(arrayItemLength);
                }
            }