JsonPatch
A struct representing a JSON patch for partial updates to a JSON structure.
using System.Buffers;
using System.Buffers.Text;
using System.ClientModel.Internal;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
namespace System.ClientModel.Primitives
{
[System.Diagnostics.CodeAnalysis.Experimental("SCME0001")]
public struct JsonPatch
{
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate bool PropagatorSetter (ReadOnlySpan<byte> jsonPath, EncodedValue value);
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate bool PropagatorGetter (ReadOnlySpan<byte> jsonPath, out EncodedValue value);
public struct EncodedValue
{
private const byte MaxInt32Utf8Bytes = 11;
private const byte MaxInt64Utf8Bytes = 20;
private const byte MaxDecimalUtf8Bytes = 64;
private const byte MaxGuidUtf8Bytes = 48;
private const byte MaxDateTimeUtf8Bytes = 64;
private const byte MaxTimeSpanUtf8Bytes = 64;
private static readonly ReadOnlyMemory<byte> s_null;
private static readonly ReadOnlyMemory<byte> s_true;
private static readonly ReadOnlyMemory<byte> s_false;
internal static readonly EncodedValue Empty;
internal static readonly EncodedValue Removed;
internal static readonly EncodedValue Null;
internal ValueKind Kind {
[System.Runtime.CompilerServices.IsReadOnly]
get;
set;
}
internal ReadOnlyMemory<byte> Value {
[System.Runtime.CompilerServices.IsReadOnly]
get;
}
private EncodedValue(ValueKind kind)
{
Value = default(ReadOnlyMemory<byte>);
Kind = kind;
}
internal EncodedValue(ValueKind kind, ReadOnlyMemory<byte> value)
{
Kind = kind;
Value = value;
}
internal EncodedValue(bool value)
{
if (value) {
Kind = ValueKind.BooleanTrue;
Value = s_true;
} else {
Kind = ValueKind.BooleanFalse;
Value = s_false;
}
}
internal unsafe EncodedValue(byte value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(DateTime value, StandardFormat format = default(StandardFormat))
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.DateTime;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
if (Utf8Formatter.TryFormat(value, destination, out int bytesWritten, format))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(DateTimeOffset value, StandardFormat format = default(StandardFormat))
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.DateTime;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
if (Utf8Formatter.TryFormat(value, destination, out int bytesWritten, format))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(decimal value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(double value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(float value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(Guid value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Guid;
Span<byte> destination = new Span<byte>(stackalloc byte[48], 48);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(int value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(long value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[20], 20);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(sbyte value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(short value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(TimeSpan value, StandardFormat format = default(StandardFormat))
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.TimeSpan;
Span<byte> destination = new Span<byte>(stackalloc byte[64], 64);
if (Utf8Formatter.TryFormat(value, destination, out int bytesWritten, format))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(uint value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(ulong value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[20], 20);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
internal unsafe EncodedValue(ushort value)
{
Value = default(ReadOnlyMemory<byte>);
Kind = ValueKind.Number;
Span<byte> destination = new Span<byte>(stackalloc byte[11], 11);
int bytesWritten = default(int);
if (Utf8Formatter.TryFormat(value, destination, out bytesWritten, default(StandardFormat)))
Value = destination.Slice(0, bytesWritten).ToArray();
}
[System.Runtime.CompilerServices.NullableContext(1)]
internal EncodedValue(string value)
{
Kind = ValueKind.Utf8String;
Value = Encoding.UTF8.GetBytes(value);
}
[System.Runtime.CompilerServices.NullableContext(1)]
internal EncodedValue(BinaryData value)
{
this = new EncodedValue(value.ToMemory());
}
internal EncodedValue(ReadOnlySpan<byte> value)
{
if (value.SequenceEqual(s_null.Span)) {
Kind = ValueKind.Null;
Value = s_null;
} else if (value.SequenceEqual(s_false.Span)) {
Kind = ValueKind.BooleanFalse;
Value = s_false;
} else if (value.SequenceEqual(s_true.Span)) {
Kind = ValueKind.BooleanTrue;
Value = s_true;
} else {
Kind = ValueKind.Json;
Value = value.ToArray();
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
internal EncodedValue(byte[] value)
{
this = new EncodedValue((ReadOnlyMemory<byte>)value);
}
internal EncodedValue(ReadOnlyMemory<byte> value)
{
ReadOnlySpan<byte> span = value.Span;
if (span.SequenceEqual(s_null.Span)) {
Kind = ValueKind.Null;
Value = s_null;
} else if (span.SequenceEqual(s_false.Span)) {
Kind = ValueKind.BooleanFalse;
Value = s_false;
} else if (span.SequenceEqual(s_true.Span)) {
Kind = ValueKind.BooleanTrue;
Value = s_true;
} else {
Kind = ValueKind.Json;
Value = value;
}
}
internal bool TryDecodeValue(out bool value)
{
if (Utf8Parser.TryParse(Value.Span, out bool value2, out int _, ' ')) {
value = value2;
return true;
}
value = false;
return false;
}
internal bool TryDecodeValue(out byte value)
{
if (Utf8Parser.TryParse(Value.Span, out byte value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out DateTime value, StandardFormat format = default(StandardFormat))
{
if (Utf8Parser.TryParse(Value.Span, out DateTime value2, out int _, format.Symbol)) {
value = value2;
return true;
}
value = default(DateTime);
return false;
}
internal bool TryDecodeValue(out DateTimeOffset value, StandardFormat format = default(StandardFormat))
{
if (Utf8Parser.TryParse(Value.Span, out DateTimeOffset value2, out int _, format.Symbol)) {
value = value2;
return true;
}
value = default(DateTimeOffset);
return false;
}
internal bool TryDecodeValue(out decimal value)
{
if (Utf8Parser.TryParse(Value.Span, out decimal value2, out int _, ' ')) {
value = value2;
return true;
}
value = default(decimal);
return false;
}
internal bool TryDecodeValue(out double value)
{
if (Utf8Parser.TryParse(Value.Span, out double value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out float value)
{
if (Utf8Parser.TryParse(Value.Span, out float value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out Guid value)
{
if (Utf8Parser.TryParse(Value.Span, out Guid value2, out int _, ' ')) {
value = value2;
return true;
}
value = default(Guid);
return false;
}
internal bool TryDecodeValue(out int value)
{
if (Utf8Parser.TryParse(Value.Span, out int value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out long value)
{
if (Utf8Parser.TryParse(Value.Span, out long value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out sbyte value)
{
if (Utf8Parser.TryParse(Value.Span, out sbyte value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out short value)
{
if (Utf8Parser.TryParse(Value.Span, out short value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out TimeSpan value, StandardFormat format = default(StandardFormat))
{
if (Utf8Parser.TryParse(Value.Span, out TimeSpan value2, out int _, format.Symbol)) {
value = value2;
return true;
}
value = default(TimeSpan);
return false;
}
internal bool TryDecodeValue(out uint value)
{
if (Utf8Parser.TryParse(Value.Span, out uint value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out ulong value)
{
if (Utf8Parser.TryParse(Value.Span, out ulong value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
internal bool TryDecodeValue(out ushort value)
{
if (Utf8Parser.TryParse(Value.Span, out ushort value2, out int _, ' ')) {
value = value2;
return true;
}
value = 0;
return false;
}
[System.Runtime.CompilerServices.NullableContext(2)]
internal bool TryDecodeValue(out string value)
{
ReadOnlySpan<byte> other = Value.Span;
if (s_null.Span.SequenceEqual(other)) {
value = null;
return true;
}
if (other.Length >= 2 && other[0] == 34 && other[other.Length - 1] == 34)
other = other.Slice(1, other.Length - 2);
value = Encoding.UTF8.GetString(other.ToArray());
return true;
}
internal bool TryDecodeNullableValue<T>(out T? value, out bool supportedType) where T : struct
{
value = null;
supportedType = true;
ReadOnlyMemory<byte> value2 = Value;
if (value2.Span.SequenceEqual(s_null.Span))
return true;
Type typeFromHandle = typeof(T);
int bytesConsumed;
if (typeFromHandle == typeof(bool)) {
value2 = Value;
bool value3;
bool flag = Utf8Parser.TryParse(value2.Span, out value3, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value3) : null);
return flag;
}
if (typeFromHandle == typeof(byte)) {
value2 = Value;
byte value4;
bool flag = Utf8Parser.TryParse(value2.Span, out value4, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value4) : null);
return flag;
}
if (typeFromHandle == typeof(sbyte)) {
value2 = Value;
sbyte value5;
bool flag = Utf8Parser.TryParse(value2.Span, out value5, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value5) : null);
return flag;
}
if (typeFromHandle == typeof(short)) {
value2 = Value;
short value6;
bool flag = Utf8Parser.TryParse(value2.Span, out value6, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value6) : null);
return flag;
}
if (typeFromHandle == typeof(ushort)) {
value2 = Value;
ushort value7;
bool flag = Utf8Parser.TryParse(value2.Span, out value7, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value7) : null);
return flag;
}
if (typeFromHandle == typeof(int)) {
value2 = Value;
int value8;
bool flag = Utf8Parser.TryParse(value2.Span, out value8, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value8) : null);
return flag;
}
if (typeFromHandle == typeof(uint)) {
value2 = Value;
uint value9;
bool flag = Utf8Parser.TryParse(value2.Span, out value9, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value9) : null);
return flag;
}
if (typeFromHandle == typeof(long)) {
value2 = Value;
long value10;
bool flag = Utf8Parser.TryParse(value2.Span, out value10, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value10) : null);
return flag;
}
if (typeFromHandle == typeof(ulong)) {
value2 = Value;
ulong value11;
bool flag = Utf8Parser.TryParse(value2.Span, out value11, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value11) : null);
return flag;
}
if (typeFromHandle == typeof(float)) {
value2 = Value;
float value12;
bool flag = Utf8Parser.TryParse(value2.Span, out value12, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value12) : null);
return flag;
}
if (typeFromHandle == typeof(double)) {
value2 = Value;
double value13;
bool flag = Utf8Parser.TryParse(value2.Span, out value13, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value13) : null);
return flag;
}
if (typeFromHandle == typeof(decimal)) {
value2 = Value;
decimal value14;
bool flag = Utf8Parser.TryParse(value2.Span, out value14, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value14) : null);
return flag;
}
if (typeFromHandle == typeof(DateTime)) {
value2 = Value;
DateTime value15;
bool flag = Utf8Parser.TryParse(value2.Span, out value15, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value15) : null);
return flag;
}
if (typeFromHandle == typeof(DateTimeOffset)) {
value2 = Value;
DateTimeOffset value16;
bool flag = Utf8Parser.TryParse(value2.Span, out value16, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value16) : null);
return flag;
}
if (typeFromHandle == typeof(Guid)) {
value2 = Value;
Guid value17;
bool flag = Utf8Parser.TryParse(value2.Span, out value17, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value17) : null);
return flag;
}
if (typeFromHandle == typeof(TimeSpan)) {
value2 = Value;
TimeSpan value18;
bool flag = Utf8Parser.TryParse(value2.Span, out value18, out bytesConsumed, ' ');
value = (flag ? ((T?)(object)value18) : null);
return flag;
}
supportedType = false;
return false;
}
unsafe static EncodedValue()
{
ReadOnlySpan<byte> readOnlySpan = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.97CCCB1B1197F11C6EDBB0D93975220592EF8FAF618C8770A131E4F7DFE567CC, 4);
s_null = readOnlySpan.ToArray();
readOnlySpan = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.DEBC2F07DB78D52D2DEF07B7BC620D7042367501D9439A62BA09B559A98E0957, 4);
s_true = readOnlySpan.ToArray();
readOnlySpan = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.98151954F217A510702D236DE168CC35D0AB2F99C4479CC9B07EEEDE7EF73A66, 5);
s_false = readOnlySpan.ToArray();
Empty = new EncodedValue(ValueKind.None, Array.Empty<byte>());
Removed = new EncodedValue(ValueKind.Removed);
Null = new EncodedValue(ValueKind.Null, s_null);
}
}
private class SpanDictionary
{
[System.Runtime.CompilerServices.Nullable(1)]
private readonly Dictionary<byte[], EncodedValue> _inner;
public int MaxKeyLength { get; set; }
public SpanDictionary()
{
_inner = new Dictionary<byte[], EncodedValue>(JsonPathComparer.Default);
}
public unsafe bool TryGetValue(ReadOnlySpan<byte> key, out EncodedValue value)
{
int length = key.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
ReadOnlySpan<byte> normalizedKey = GetNormalizedKey(key, buffer);
return _inner.TryGetValue(normalizedKey.ToArray(), out value);
}
public unsafe void Set(ReadOnlySpan<byte> key, EncodedValue value)
{
int length = key.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
ReadOnlySpan<byte> normalizedKey = GetNormalizedKey(key, buffer);
MaxKeyLength = Math.Max(MaxKeyLength, normalizedKey.Length);
_inner[normalizedKey.ToArray()] = value;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public Dictionary<byte[], EncodedValue>.Enumerator GetEnumerator()
{
return _inner.GetEnumerator();
}
public unsafe void TryUpdateValueKind(ReadOnlySpan<byte> key, ValueKind kind)
{
int length = key.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
byte[] key2 = GetNormalizedKey(key, buffer).ToArray();
if (_inner.TryGetValue(key2, out EncodedValue value)) {
value.Kind = kind;
_inner[key2] = value;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ReadOnlySpan<byte> GetNormalizedKey(ReadOnlySpan<byte> key, Span<byte> buffer)
{
JsonPathComparer.Default.Normalize(key, buffer, out int bytesWritten);
return buffer.Slice(0, bytesWritten);
}
}
private class SpanHashSet
{
[System.Runtime.CompilerServices.Nullable(1)]
private HashSet<byte[]> _inner;
public SpanHashSet()
{
_inner = new HashSet<byte[]>(JsonPathComparer.Default);
}
public unsafe bool Contains(ReadOnlySpan<byte> item)
{
int length = item.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
JsonPathComparer.Default.Normalize(item, buffer, out int bytesWritten);
buffer = buffer.Slice(0, bytesWritten);
return _inner.Contains(buffer.ToArray());
}
public unsafe bool Add(ReadOnlySpan<byte> item)
{
int length = item.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
JsonPathComparer.Default.Normalize(item, buffer, out int bytesWritten);
buffer = buffer.Slice(0, bytesWritten);
return _inner.Add(buffer.ToArray());
}
}
[Flags]
internal enum ValueKind : short
{
None = 0,
Json = 1,
Number = 2,
Utf8String = 4,
Removed = 8,
Null = 16,
BooleanTrue = 32,
BooleanFalse = 64,
ArrayItemAppend = 128,
ModelOwned = 256,
DateTime = 512,
Guid = 1024,
TimeSpan = 2048
}
[System.Runtime.CompilerServices.Nullable(2)]
private SpanDictionary _properties;
private readonly EncodedValue _rawJson;
[System.Runtime.CompilerServices.Nullable(2)]
private PropagatorSetter _propagatorSetter;
[System.Runtime.CompilerServices.Nullable(2)]
private PropagatorGetter _propagatorGetter;
public JsonPatch(ReadOnlyMemory<byte> utf8Json)
{
_properties = null;
_propagatorSetter = null;
_propagatorGetter = null;
_rawJson = new EncodedValue(ValueKind.Json, utf8Json);
}
[System.Runtime.CompilerServices.NullableContext(1)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetPropagators(PropagatorSetter setter, PropagatorGetter getter)
{
_propagatorSetter = setter;
_propagatorGetter = getter;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(ReadOnlySpan<byte> jsonPath)
{
if (_properties == null)
return false;
if (_properties.TryGetValue(jsonPath, out EncodedValue value))
return !value.Kind.HasFlag(ValueKind.ArrayItemAppend);
return false;
}
public void Set(ReadOnlySpan<byte> jsonPath, bool value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, byte value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, DateTime value, StandardFormat format = default(StandardFormat))
{
SetInternal(jsonPath, new EncodedValue(value, format));
}
public void Set(ReadOnlySpan<byte> jsonPath, DateTimeOffset value, StandardFormat format = default(StandardFormat))
{
SetInternal(jsonPath, new EncodedValue(value, format));
}
public void Set(ReadOnlySpan<byte> jsonPath, decimal value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, double value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, float value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, Guid value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, int value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, long value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, sbyte value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, short value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, TimeSpan value, StandardFormat format = default(StandardFormat))
{
SetInternal(jsonPath, new EncodedValue(value, format));
}
public void Set(ReadOnlySpan<byte> jsonPath, uint value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, ulong value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, ushort value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, [System.Runtime.CompilerServices.Nullable(1)] string value)
{
SetInternal(jsonPath, new EncodedValue(value));
}
public void Set(ReadOnlySpan<byte> jsonPath, [System.Runtime.CompilerServices.Nullable(1)] byte[] utf8Json)
{
SetInternal(jsonPath, new EncodedValue(utf8Json));
}
public void Set(ReadOnlySpan<byte> jsonPath, [System.Runtime.CompilerServices.Nullable(1)] BinaryData utf8Json)
{
SetInternal(jsonPath, new EncodedValue(utf8Json));
}
public void Set(ReadOnlySpan<byte> jsonPath, ReadOnlySpan<byte> utf8Json)
{
SetInternal(jsonPath, new EncodedValue(utf8Json));
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void Set(ReadOnlySpan<byte> jsonPath, EncodedValue value)
{
SetInternal(jsonPath, value);
}
public void SetNull(ReadOnlySpan<byte> jsonPath)
{
SetInternal(jsonPath, EncodedValue.Null);
}
public bool GetBoolean(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out bool value2))
return value2;
return ThrowFormatException<bool>(jsonPath);
}
public byte GetByte(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out byte value2))
return value2;
return ThrowFormatException<byte>(jsonPath);
}
public DateTime GetDateTime(ReadOnlySpan<byte> jsonPath, StandardFormat format = default(StandardFormat))
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out DateTime value2, format))
return value2;
return ThrowFormatException<DateTime>(jsonPath);
}
public DateTimeOffset GetDateTimeOffset(ReadOnlySpan<byte> jsonPath, StandardFormat format = default(StandardFormat))
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out DateTimeOffset value2, format))
return value2;
return ThrowFormatException<DateTimeOffset>(jsonPath);
}
public decimal GetDecimal(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out decimal value2))
return value2;
return ThrowFormatException<decimal>(jsonPath);
}
public double GetDouble(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out double value2))
return value2;
return ThrowFormatException<double>(jsonPath);
}
public float GetFloat(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out float value2))
return value2;
return ThrowFormatException<float>(jsonPath);
}
public Guid GetGuid(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out Guid value2))
return value2;
return ThrowFormatException<Guid>(jsonPath);
}
public int GetInt32(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out int value2))
return value2;
return ThrowFormatException<int>(jsonPath);
}
public long GetInt64(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out long value2))
return value2;
return ThrowFormatException<long>(jsonPath);
}
public sbyte GetInt8(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out sbyte value2))
return value2;
return ThrowFormatException<sbyte>(jsonPath);
}
public short GetInt16(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out short value2))
return value2;
return ThrowFormatException<short>(jsonPath);
}
public TimeSpan GetTimeSpan(ReadOnlySpan<byte> jsonPath, StandardFormat format = default(StandardFormat))
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out TimeSpan value2, format))
return value2;
return ThrowFormatException<TimeSpan>(jsonPath);
}
public uint GetUInt32(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out uint value2))
return value2;
return ThrowFormatException<uint>(jsonPath);
}
public ulong GetUInt64(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out ulong value2))
return value2;
return ThrowFormatException<ulong>(jsonPath);
}
public ushort GetUInt16(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeValue(out ushort value2))
return value2;
return ThrowFormatException<ushort>(jsonPath);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public string GetString(ReadOnlySpan<byte> jsonPath)
{
EncodedValue value;
if (TryGetEncodedValueInternal(jsonPath, out value) && value.Kind != ValueKind.Removed && value.TryDecodeValue(out string value2))
return value2;
ThrowKeyNotFoundException(jsonPath);
return null;
}
[return: System.Runtime.CompilerServices.Nullable(1)]
public BinaryData GetJson(ReadOnlySpan<byte> jsonPath)
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
return new BinaryData(value.Value);
}
public T? GetNullableValue<T>(ReadOnlySpan<byte> jsonPath) where T : struct
{
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value) || value.Kind == ValueKind.Removed)
ThrowKeyNotFoundException(jsonPath);
if (value.TryDecodeNullableValue(out T? value2, out bool supportedType))
return value2;
if (supportedType)
return ThrowFormatException<T?>(jsonPath);
return NullableTypeNotSupported<T>();
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out bool value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out bool value3)) {
value = value3;
return true;
}
value = false;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out byte value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out byte value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out DateTime value, StandardFormat format = default(StandardFormat))
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out DateTime value3, format.Symbol)) {
value = value3;
return true;
}
value = default(DateTime);
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out DateTimeOffset value, StandardFormat format = default(StandardFormat))
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out DateTimeOffset value3, format.Symbol)) {
value = value3;
return true;
}
value = default(DateTimeOffset);
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out decimal value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out decimal value3)) {
value = value3;
return true;
}
value = default(decimal);
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out double value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out double value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out float value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out float value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out Guid value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out Guid value3)) {
value = value3;
return true;
}
value = default(Guid);
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out int value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out int value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out long value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out long value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out sbyte value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out sbyte value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out short value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out short value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out TimeSpan value, StandardFormat format = default(StandardFormat))
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out TimeSpan value3, format.Symbol)) {
value = value3;
return true;
}
value = default(TimeSpan);
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out uint value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out uint value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out ulong value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out ulong value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, out ushort value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2) && value2.TryDecodeValue(out ushort value3)) {
value = value3;
return true;
}
value = 0;
return false;
}
public bool TryGetValue(ReadOnlySpan<byte> jsonPath, [System.Runtime.CompilerServices.Nullable(2)] out string value)
{
if (TryGetEncodedValueInternal(jsonPath, out EncodedValue value2)) {
value2.TryDecodeValue(out string value3);
value = value3;
return true;
}
value = null;
return false;
}
public bool TryGetNullableValue<T>(ReadOnlySpan<byte> jsonPath, out T? value) where T : struct
{
value = null;
if (!TryGetEncodedValueInternal(jsonPath, out EncodedValue value2))
return false;
if (value2.Kind.HasFlag(ValueKind.Null))
return true;
if (value2.TryDecodeNullableValue(out T? value3, out bool _)) {
value = value3;
return true;
}
return false;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool TryGetEncodedValue(ReadOnlySpan<byte> jsonPath, out EncodedValue value)
{
return TryGetEncodedValueInternal(jsonPath, out value);
}
public bool TryGetJson(ReadOnlySpan<byte> jsonPath, out ReadOnlyMemory<byte> value)
{
EncodedValue value2;
bool result = TryGetEncodedValueInternal(jsonPath, out value2);
value = value2.Value;
return result;
}
public void Append(ReadOnlySpan<byte> arrayPath, bool value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, byte value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, DateTime value, StandardFormat format = default(StandardFormat))
{
EncodedValue encodedValue = new EncodedValue(value, format);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, DateTimeOffset value, StandardFormat format = default(StandardFormat))
{
EncodedValue encodedValue = new EncodedValue(value, format);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, decimal value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, double value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, float value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, Guid value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, int value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, long value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, sbyte value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, short value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, TimeSpan value, StandardFormat format = default(StandardFormat))
{
EncodedValue encodedValue = new EncodedValue(value, default(StandardFormat));
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, uint value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, ulong value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, ushort value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, [System.Runtime.CompilerServices.Nullable(1)] string value)
{
EncodedValue encodedValue = new EncodedValue(value);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, [System.Runtime.CompilerServices.Nullable(1)] byte[] utf8Json)
{
EncodedValue encodedValue = new EncodedValue(utf8Json);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, [System.Runtime.CompilerServices.Nullable(1)] BinaryData utf8Json)
{
EncodedValue encodedValue = new EncodedValue(utf8Json);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void Append(ReadOnlySpan<byte> arrayPath, ReadOnlySpan<byte> utf8Json)
{
EncodedValue encodedValue = new EncodedValue(utf8Json);
encodedValue.Kind |= ValueKind.ArrayItemAppend;
SetInternal(arrayPath, encodedValue);
}
public void AppendNull(ReadOnlySpan<byte> arrayPath)
{
SetInternal(arrayPath, new EncodedValue(ValueKind.ArrayItemAppend, EncodedValue.Null.Value));
}
public void Remove(ReadOnlySpan<byte> jsonPath)
{
SetInternal(jsonPath, EncodedValue.Removed);
}
public bool IsRemoved(ReadOnlySpan<byte> jsonPath)
{
if (_properties == null)
return false;
if (_properties.TryGetValue(jsonPath, out EncodedValue value))
return value.Kind == ValueKind.Removed;
return false;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public unsafe bool Contains(ReadOnlySpan<byte> prefix, ReadOnlySpan<byte> property)
{
if (_properties == null)
return false;
int length = prefix.Length;
Span<byte> span = new Span<byte>(stackalloc byte[(int)(uint)length], length);
JsonPathComparer.Default.Normalize(prefix, span, out int bytesWritten);
span = span.Slice(0, bytesWritten);
foreach (KeyValuePair<byte[], EncodedValue> property2 in _properties) {
ReadOnlySpan<byte> span2 = property2.Key;
if (span2.StartsWith(span) && property.SequenceEqual(span2.Slice(span.Length).GetPropertyNameFromSlice()))
return true;
}
return false;
}
[System.Runtime.CompilerServices.NullableContext(1)]
public override string ToString()
{
return ToString("JP");
}
[System.Runtime.CompilerServices.NullableContext(1)]
public string ToString(string format)
{
ThrowIfNull(format, "format");
if (format == "J")
return SerializeToJson();
if (format == "JP")
return SerializeToJsonPatch();
return ThrowFormatNotSupportedException(format);
}
private unsafe bool TryGetEncodedValueInternal(ReadOnlySpan<byte> jsonPath, out EncodedValue value)
{
value = EncodedValue.Empty;
if (jsonPath.IsRoot())
return TryGetExactMatch(jsonPath, out value);
if (_propagatorGetter != null && _propagatorGetter(jsonPath, out value))
return true;
ReadOnlySpan<byte> parentPath;
EncodedValue encodedValue;
if (_properties == null) {
if (TryGetParentMatch(jsonPath, true, out parentPath, out encodedValue)) {
value = new EncodedValue(encodedValue.Kind, encodedValue.Value.GetJson(jsonPath));
return true;
}
return false;
}
if (TryGetExactMatch(jsonPath, out value))
return true;
int length = jsonPath.Length;
Span<byte> subPath = new Span<byte>(stackalloc byte[(int)(uint)length], length);
ReadOnlySpan<byte> parent = jsonPath.GetParent();
EncodedValue value2;
if (jsonPath.IsArrayIndex() && _properties.TryGetValue(parent, out value2) && !value2.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
GetSubPath(parent, jsonPath, ref subPath);
value = new EncodedValue(value2.Kind, value2.Value.GetJson(subPath));
return true;
}
if (TryGetParentMatch(jsonPath, true, out ReadOnlySpan<byte> parentPath2, out encodedValue)) {
length = jsonPath.Length;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)length], length);
JsonPathComparer.Default.Normalize(jsonPath, buffer, out int bytesWritten);
ReadOnlySpan<byte> readOnlySpan = buffer.Slice(0, bytesWritten);
JsonPathReader reader = new JsonPathReader(readOnlySpan);
reader.Advance(parentPath2);
ReadOnlySpan<byte> nextArray = reader.GetNextArray();
if (nextArray.IsEmpty) {
GetSubPath(parentPath2, readOnlySpan, ref subPath);
value = new EncodedValue(encodedValue.Kind, encodedValue.Value.GetJson(subPath));
return true;
}
length = readOnlySpan.Length;
Span<byte> span = new Span<byte>(stackalloc byte[(int)(uint)length], length);
readOnlySpan.CopyTo(span);
int length2 = readOnlySpan.Length;
while (!nextArray.IsEmpty) {
if (TryGetArrayItemFromRoot(nextArray, reader, out int indexRequested, out int length3, out ReadOnlyMemory<byte> arrayItem)) {
GetSubPath(nextArray, jsonPath, ref subPath);
value = new EncodedValue(ValueKind.Json, GetCombinedArray(jsonPath, arrayItem.GetJson(subPath), EncodedValue.Empty));
return true;
}
int newIndex = indexRequested - Math.Max(length3, GetMaxSibling(nextArray) + 1);
JsonPathToken current = reader.Current;
parentPath = current.ValueSpan;
int length4 = parentPath.Length;
current = reader.Current;
AdjustJsonPath(newIndex, length4, current.TokenStartIndex, span, ref length2);
nextArray = reader.GetNextArray();
}
GetSubPath(parentPath2, span.Slice(0, length2), ref subPath);
value = new EncodedValue(encodedValue.Kind, encodedValue.Value.GetJson(subPath));
return true;
}
return false;
}
[System.Runtime.CompilerServices.IsReadOnly]
private int GetMaxSibling(ReadOnlySpan<byte> normalizedArrayPath)
{
int num = -1;
ReadOnlySpan<byte> parent = normalizedArrayPath.GetParent();
foreach (KeyValuePair<byte[], EncodedValue> property in _properties) {
EncodedValue value = property.Value;
if (value.Kind != ValueKind.Removed) {
value = property.Value;
if (!value.Kind.HasFlag(ValueKind.ModelOwned)) {
ReadOnlySpan<byte> readOnlySpan = property.Key;
if (readOnlySpan.StartsWith(parent)) {
readOnlySpan = readOnlySpan.Slice(parent.Length);
if (readOnlySpan.IsArrayWrapped() && Utf8Parser.TryParse(readOnlySpan.Slice(1, readOnlySpan.Length - 2), out int value2, out int _, ' '))
num = Math.Max(num, value2);
}
}
}
}
return num;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool TryGetExactMatch(ReadOnlySpan<byte> jsonPath, out EncodedValue value)
{
if (_properties != null && _properties.TryGetValue(jsonPath, out EncodedValue value2)) {
if (value2.Kind.HasFlag(ValueKind.ArrayItemAppend))
value = new EncodedValue(value2.Kind, GetCombinedArray(jsonPath, value2));
else
value = value2;
return true;
}
value = EncodedValue.Empty;
return false;
}
private static void AdjustJsonPath(int newIndex, int indexLength, int indexStart, Span<byte> buffer, ref int length)
{
int bytesWritten = default(int);
Utf8Formatter.TryFormat(newIndex, buffer.Slice(indexStart), out bytesWritten, default(StandardFormat));
int num = indexLength - bytesWritten;
if (num > 0) {
buffer.Slice(indexStart + indexLength).CopyTo(buffer.Slice(indexStart + bytesWritten));
length -= num;
}
}
private bool TryGetArrayItemFromRoot(ReadOnlySpan<byte> jsonPath, JsonPathReader reader, out int indexRequested, out int length, out ReadOnlyMemory<byte> arrayItem)
{
length = 0;
indexRequested = 0;
arrayItem = ReadOnlyMemory<byte>.Empty;
if (!Utf8Parser.TryParse(jsonPath.GetIndexSpan(), out indexRequested, out int _, ' '))
return false;
if (!TryGetRootJson(out ReadOnlyMemory<byte> value))
return false;
Utf8JsonReader jsonReader = new Utf8JsonReader(value.Span, default(JsonReaderOptions));
if (!ref jsonReader.Advance(jsonPath.GetParent()))
return false;
if (jsonReader.TokenType == JsonTokenType.PropertyName)
jsonReader.Read();
if (jsonReader.TokenType != JsonTokenType.StartArray)
return false;
if (!ref jsonReader.SkipToIndex(indexRequested, out length))
return false;
long tokenStartIndex = jsonReader.TokenStartIndex;
jsonReader.Skip();
long bytesConsumed2 = jsonReader.BytesConsumed;
arrayItem = value.Slice((int)tokenStartIndex, (int)(bytesConsumed2 - tokenStartIndex));
return true;
}
private ReadOnlyMemory<byte> GetCombinedArray(ReadOnlySpan<byte> jsonPath, EncodedValue encodedValue)
{
TryGetRootJson(out ReadOnlyMemory<byte> value);
value.TryGetJson(jsonPath, out ReadOnlyMemory<byte> target);
return GetCombinedArray(jsonPath, target, encodedValue);
}
private unsafe ReadOnlyMemory<byte> GetCombinedArray(ReadOnlySpan<byte> jsonPath, ReadOnlyMemory<byte> existingArray, EncodedValue encodedValue)
{
int length = jsonPath.Length;
Span<byte> span = new Span<byte>(stackalloc byte[(int)(uint)length], length);
byte[] array = new byte[_properties.MaxKeyLength];
JsonPathComparer.Default.Normalize(jsonPath, span, out int bytesWritten);
span = span.Slice(0, bytesWritten);
foreach (KeyValuePair<byte[], EncodedValue> property in _properties) {
EncodedValue value = property.Value;
if (value.Kind != ValueKind.Removed) {
value = property.Value;
if (!value.Kind.HasFlag(ValueKind.ModelOwned)) {
ReadOnlySpan<byte> span2 = property.Key;
if (span2.StartsWith(span)) {
ReadOnlyMemory<byte> value2;
if (existingArray.IsEmpty) {
ReadOnlyMemory<byte> readOnlyMemory;
if (!span2.SequenceEqual(span)) {
byte b = 91;
value = property.Value;
value2 = value.Value;
ReadOnlySpan<byte> span3 = value2.Span;
length = 0;
byte[] array2 = new byte[2 + span3.Length];
array2[length] = b;
length++;
span3.CopyTo(new Span<byte>(array2).Slice(length, span3.Length));
length += span3.Length;
array2[length] = 93;
readOnlyMemory = new ReadOnlyMemory<byte>(array2);
} else
readOnlyMemory = encodedValue.Value;
existingArray = readOnlyMemory;
} else {
GetSubPath(span, property.Key, array, out int bytesWritten2);
ReadOnlySpan<byte> readOnlySpan = array.AsSpan(0, bytesWritten2);
if (readOnlySpan.IsArrayIndex()) {
ReadOnlyMemory<byte> json = existingArray;
ReadOnlySpan<byte> arrayPath = readOnlySpan;
value = property.Value;
existingArray = json.InsertAt(arrayPath, value.Value);
} else {
ReadOnlyMemory<byte> json2 = existingArray;
ReadOnlySpan<byte> arrayPath2 = readOnlySpan;
value = property.Value;
value2 = value.Value;
value = property.Value;
existingArray = json2.Append(arrayPath2, value2.Slice(1, value.Value.Length - 2));
}
}
}
}
}
}
if (!existingArray.IsEmpty)
return existingArray;
return encodedValue.Value;
}
private bool TryGetRootJson(out ReadOnlyMemory<byte> value)
{
value = ReadOnlyMemory<byte>.Empty;
if (_rawJson.Value.IsEmpty)
return false;
value = _rawJson.Value;
return !value.IsEmpty;
}
private unsafe bool TryGetParentMatch(ReadOnlySpan<byte> jsonPath, bool includeRoot, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out ReadOnlySpan<byte> parentPath, out EncodedValue encodedValue)
{
parentPath = default(ReadOnlySpan<byte>);
encodedValue = EncodedValue.Empty;
ReadOnlyMemory<byte> value;
if (_properties == null) {
if (includeRoot) {
value = _rawJson.Value;
if (!value.IsEmpty) {
encodedValue = _rawJson;
parentPath = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1);
return true;
}
}
return false;
}
parentPath = jsonPath.GetParent();
while (parentPath.Length > 0) {
if (_properties.TryGetValue(parentPath, out encodedValue))
return true;
parentPath = parentPath.GetParent();
if (parentPath.IsRoot())
break;
}
if (parentPath.IsRoot() & includeRoot) {
if (_properties.TryGetValue(parentPath, out encodedValue))
return true;
value = _rawJson.Value;
if (!value.IsEmpty) {
encodedValue = _rawJson;
return true;
}
}
return false;
}
private unsafe void SetInternal(ReadOnlySpan<byte> jsonPath, EncodedValue encodedValue)
{
if (_propagatorSetter == null || !_propagatorSetter(jsonPath, encodedValue)) {
EncodedValue value = EncodedValue.Empty;
if (_properties != null && _properties.TryGetValue(jsonPath, out value))
_properties.Set(jsonPath, new EncodedValue(encodedValue.Kind, ModifyJson(value, new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1), encodedValue)));
else {
ReadOnlySpan<byte> readOnlySpan = jsonPath;
byte[] array = new byte[jsonPath.Length];
int bytesConsumed = readOnlySpan.Length;
Span<byte> subPath = new Span<byte>(stackalloc byte[(int)(uint)bytesConsumed], bytesConsumed);
ReadOnlyMemory<byte> value2 = _rawJson.Value;
if (!value2.IsEmpty && encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
value2 = _rawJson.Value;
Utf8JsonReader jsonReader = new Utf8JsonReader(value2.Span, default(JsonReaderOptions));
JsonPathReader pathReader = new JsonPathReader(jsonPath);
if (ref jsonReader.Advance(ref pathReader)) {
if (_properties == null)
_properties = new SpanDictionary();
_properties.Set(jsonPath, new EncodedValue(encodedValue.Kind, GetNewJson(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1), encodedValue)));
return;
}
JsonPathToken current = pathReader.Current;
if (current.TokenType != JsonPathTokenType.End) {
ReadOnlySpan<byte> parsedPath = pathReader.GetParsedPath();
if (parsedPath.IsArrayIndex()) {
value2 = _rawJson.Value;
jsonReader = new Utf8JsonReader(value2.Span, default(JsonReaderOptions));
int arrayLength = ref jsonReader.GetArrayLength(parsedPath.GetParent());
current = pathReader.Current;
Utf8Parser.TryParse(current.ValueSpan, out int value3, out bytesConsumed, ' ');
int length = parsedPath.Length;
parsedPath.CopyTo(array);
int newIndex = value3 - arrayLength;
current = pathReader.Current;
int length2 = current.ValueSpan.Length;
current = pathReader.Current;
AdjustJsonPath(newIndex, length2, current.TokenStartIndex, array, ref length);
current = pathReader.Current;
ReadOnlySpan<byte> readOnlySpan2 = jsonPath.Slice(current.TokenStartIndex + 2);
readOnlySpan2.CopyTo(array.AsSpan(length));
readOnlySpan = array.AsSpan(0, length + readOnlySpan2.Length);
}
}
}
ReadOnlySpan<byte> readOnlySpan3 = readOnlySpan.SequenceEqual(jsonPath) ? readOnlySpan : readOnlySpan.GetParent();
ReadOnlySpan<byte> readOnlySpan4 = readOnlySpan;
if (_properties != null) {
while (true) {
if (_properties.TryGetValue(readOnlySpan3, out value)) {
GetSubPath(readOnlySpan3, readOnlySpan, ref subPath);
ValueKind kind = subPath.IsRoot() ? encodedValue.Kind : value.Kind;
_properties.Set(readOnlySpan3, new EncodedValue(kind, ModifyJson(value, subPath, encodedValue)));
return;
}
if (readOnlySpan3.IsRoot())
break;
readOnlySpan4 = readOnlySpan3;
readOnlySpan3 = readOnlySpan3.GetParent();
}
}
if (encodedValue.Kind == ValueKind.Removed && jsonPath.IsArrayIndex()) {
value2 = _rawJson.Value;
Utf8JsonReader jsonReader2 = new Utf8JsonReader(value2.Span, default(JsonReaderOptions));
JsonPathReader pathReader2 = new JsonPathReader(jsonPath);
if (ref jsonReader2.Advance(ref pathReader2)) {
if (_properties == null)
_properties = new SpanDictionary();
_properties.Set(jsonPath, new EncodedValue(encodedValue.Kind, GetNewJson(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1), encodedValue)));
return;
}
ThrowIndexOutOfRangeException(jsonPath);
}
ValueKind valueKind = ValueKind.Json;
ReadOnlySpan<byte> parent = readOnlySpan.GetParent();
if (parent.IsRoot()) {
readOnlySpan4 = readOnlySpan;
readOnlySpan3 = parent;
} else {
value2 = _rawJson.Value;
if (value2.IsEmpty) {
if (_properties == null) {
readOnlySpan4 = readOnlySpan.GetFirstProperty();
readOnlySpan3 = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1);
}
if (readOnlySpan4.IsArrayIndex() && !encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
readOnlySpan4 = readOnlySpan3;
valueKind |= ValueKind.ArrayItemAppend;
}
} else {
JsonPathReader pathReader3 = new JsonPathReader(jsonPath);
value2 = _rawJson.Value;
Utf8JsonReader jsonReader3 = new Utf8JsonReader(value2.Span, default(JsonReaderOptions));
if (ref jsonReader3.Advance(ref pathReader3)) {
readOnlySpan4 = jsonPath;
readOnlySpan3 = parent;
} else {
readOnlySpan4 = pathReader3.GetParsedPath();
readOnlySpan3 = readOnlySpan4.GetParent();
if (readOnlySpan4.IsArrayIndex() && !encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
readOnlySpan4 = readOnlySpan3;
valueKind |= ValueKind.ArrayItemAppend;
}
}
}
}
if (readOnlySpan4.SequenceEqual(readOnlySpan))
valueKind = encodedValue.Kind;
GetSubPath(readOnlySpan4, readOnlySpan, ref subPath);
if (_properties == null)
_properties = new SpanDictionary();
_properties.Set(readOnlySpan4, new EncodedValue(valueKind, GetNewJson(subPath, encodedValue)));
}
}
}
private static void GetSubPath(ReadOnlySpan<byte> parentPath, ReadOnlySpan<byte> fullPath, Span<byte> subPath, out int bytesWritten)
{
if (parentPath.IsRoot()) {
fullPath.CopyTo(subPath);
bytesWritten = fullPath.Length;
} else {
ReadOnlySpan<byte> readOnlySpan = fullPath.Slice(parentPath.Length);
subPath[0] = 36;
readOnlySpan.CopyTo(subPath.Slice(1));
bytesWritten = readOnlySpan.Length + 1;
}
}
private static void GetSubPath(ReadOnlySpan<byte> parentPath, ReadOnlySpan<byte> fullPath, ref Span<byte> subPath)
{
GetSubPath(parentPath, fullPath, subPath, out int bytesWritten);
subPath = subPath.Slice(0, bytesWritten);
}
private static ReadOnlyMemory<byte> ModifyJson(EncodedValue currentValue, ReadOnlySpan<byte> jsonPath, EncodedValue encodedValue)
{
if (!currentValue.Kind.HasFlag(ValueKind.Json) && !currentValue.Kind.HasFlag(ValueKind.ArrayItemAppend))
return encodedValue.Value;
ReadOnlyMemory<byte> value = currentValue.Value;
if (encodedValue.Kind == ValueKind.Removed)
return value.Remove(jsonPath);
JsonPathReader pathReader = new JsonPathReader(jsonPath);
Utf8JsonReader jsonReader = new Utf8JsonReader(value.Span, default(JsonReaderOptions));
bool flag = ref jsonReader.Advance(ref pathReader);
ReadOnlyMemory<byte> readOnlyMemory;
int bytesConsumed;
if (!NeedsQuotes(encodedValue.Kind, jsonPath.IsArrayIndex()))
readOnlyMemory = encodedValue.Value;
else {
byte b = 34;
ReadOnlySpan<byte> span = encodedValue.Value.Span;
bytesConsumed = 0;
byte[] array = new byte[2 + span.Length];
array[bytesConsumed] = b;
bytesConsumed++;
span.CopyTo(new Span<byte>(array).Slice(bytesConsumed, span.Length));
bytesConsumed += span.Length;
array[bytesConsumed] = 34;
readOnlyMemory = new ReadOnlyMemory<byte>(array);
}
ReadOnlyMemory<byte> readOnlyMemory2 = readOnlyMemory;
JsonPathToken current = pathReader.Current;
ReadOnlySpan<byte> valueSpan = current.ValueSpan;
int value2 = 0;
current = pathReader.Current;
if (current.TokenType == JsonPathTokenType.ArrayIndex) {
current = pathReader.Current;
Utf8Parser.TryParse(current.ValueSpan, out value2, out bytesConsumed, ' ');
}
current = pathReader.Current;
if (current.TokenType != JsonPathTokenType.End || jsonReader.TokenType == JsonTokenType.Null)
readOnlyMemory2 = GetNonRootNewJson(ref pathReader, jsonPath.GetParent().IsRoot(), jsonPath.IsArrayIndex(), encodedValue);
if (jsonReader.TokenType == JsonTokenType.PropertyName)
jsonReader.Read();
if (flag && (jsonReader.TokenType != JsonTokenType.StartArray || !encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)))
return jsonReader.SetCurrentValue(flag, valueSpan, value, readOnlyMemory2);
return ref jsonReader.Insert(value, valueSpan, readOnlyMemory2, value2 > 0);
}
private static ReadOnlyMemory<byte> GetNewJson(ReadOnlySpan<byte> jsonPath, EncodedValue encodedValue)
{
if (encodedValue.Kind == ValueKind.Removed)
return encodedValue.Value;
if (jsonPath.IsRoot()) {
if (encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
ReadOnlyMemory<byte> value;
ReadOnlySpan<byte> span;
Span<byte> span2;
byte b;
byte[] array;
int num;
if (!NeedsQuotes(encodedValue.Kind, true)) {
b = 91;
value = encodedValue.Value;
span = value.Span;
num = 0;
array = new byte[2 + span.Length];
array[num] = b;
num++;
span2 = new Span<byte>(array);
span.CopyTo(span2.Slice(num, span.Length));
num += span.Length;
array[num] = 93;
return new ReadOnlyMemory<byte>(array);
}
b = 91;
byte b2 = 34;
value = encodedValue.Value;
span = value.Span;
num = 0;
array = new byte[4 + span.Length];
array[num] = b;
num++;
array[num] = b2;
num++;
span2 = new Span<byte>(array);
span.CopyTo(span2.Slice(num, span.Length));
num += span.Length;
array[num] = 34;
num++;
array[num] = 93;
return new ReadOnlyMemory<byte>(array);
}
return encodedValue.Value;
}
JsonPathReader reader = new JsonPathReader(jsonPath);
return GetNonRootNewJson(ref reader, jsonPath.GetParent().IsRoot(), jsonPath.IsArrayIndex(), encodedValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool NeedsQuotes(ValueKind kind, bool isArrayIndex)
{
ValueKind valueKind = ValueKind.Utf8String | ValueKind.DateTime | ValueKind.Guid | ValueKind.TimeSpan;
if ((kind & valueKind) > ValueKind.None) {
if (!isArrayIndex)
return kind.HasFlag(ValueKind.ArrayItemAppend);
return true;
}
return false;
}
private static ReadOnlyMemory<byte> GetNonRootNewJson(ref JsonPathReader reader, bool isParentRoot, bool isArrayIndex, EncodedValue encodedValue)
{
using (UnsafeBufferSequence unsafeBufferSequence = new UnsafeBufferSequence(16384))
using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(unsafeBufferSequence, default(JsonWriterOptions))) {
if (reader.Peek().TokenType == JsonPathTokenType.End) {
if (encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
utf8JsonWriter.WriteStartArray();
WriteEncodedValueAsJson(utf8JsonWriter, ReadOnlySpan<byte>.Empty, encodedValue);
utf8JsonWriter.WriteEndArray();
} else
WriteEncodedValueAsJson(utf8JsonWriter, ReadOnlySpan<byte>.Empty, encodedValue);
} else
ProjectJson(utf8JsonWriter, ref reader, encodedValue, false);
utf8JsonWriter.Flush();
using (UnsafeBufferSequence.Reader reader2 = unsafeBufferSequence.ExtractReader())
return reader2.ToBinaryData().ToMemory();
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
private static void ProjectJson(Utf8JsonWriter writer, ref JsonPathReader pathReader, EncodedValue encodedValue, bool inArray)
{
while (pathReader.Read()) {
JsonPathToken jsonPathToken = pathReader.Current;
switch (jsonPathToken.TokenType) {
case JsonPathTokenType.ArrayIndex:
writer.WriteStartArray();
jsonPathToken = pathReader.Current;
Utf8Parser.TryParse(jsonPathToken.ValueSpan, out int value, out int _, ' ');
for (int i = 0; i < value; i++) {
writer.WriteNullValue();
}
jsonPathToken = pathReader.Peek();
if (jsonPathToken.TokenType == JsonPathTokenType.End) {
if (encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
writer.WriteStartArray();
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, encodedValue);
writer.WriteEndArray();
} else
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, encodedValue);
} else
ProjectJson(writer, ref pathReader, encodedValue, true);
writer.WriteEndArray();
break;
case JsonPathTokenType.Property:
if (!inArray) {
jsonPathToken = pathReader.Current;
writer.WritePropertyName(jsonPathToken.ValueSpan);
}
jsonPathToken = pathReader.Peek();
if (jsonPathToken.TokenType == JsonPathTokenType.End) {
if (encodedValue.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
writer.WriteStartArray();
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, encodedValue);
writer.WriteEndArray();
} else
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, encodedValue);
} else
ProjectJson(writer, ref pathReader, encodedValue, false);
break;
case JsonPathTokenType.PropertySeparator:
writer.WriteStartObject();
jsonPathToken = pathReader.Peek();
if (jsonPathToken.TokenType == JsonPathTokenType.End)
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, encodedValue);
else
ProjectJson(writer, ref pathReader, encodedValue, false);
writer.WriteEndObject();
break;
default:
jsonPathToken = pathReader.Current;
ThrowInvalidToken(jsonPathToken.TokenType);
break;
case JsonPathTokenType.Root:
case JsonPathTokenType.End:
break;
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public unsafe void WriteTo([System.Runtime.CompilerServices.Nullable(1)] Utf8JsonWriter writer, ReadOnlySpan<byte> jsonPath)
{
if (_properties != null) {
if (_properties.TryGetValue(jsonPath, out EncodedValue value)) {
if (value.Kind == ValueKind.Removed)
return;
if (value.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
_properties.TryUpdateValueKind(jsonPath, value.Kind | ValueKind.ModelOwned);
ReadOnlyMemory<byte> value2 = value.Value;
ReadOnlySpan<byte> span = value2.Span;
value2 = value.Value;
writer.WriteRawValue(span.Slice(1, value2.Length - 2), false);
}
}
int length = jsonPath.Length;
Span<byte> span2 = new Span<byte>(stackalloc byte[(int)(uint)length], length);
JsonPathComparer.Default.Normalize(jsonPath, span2, out int bytesWritten);
span2 = span2.Slice(0, bytesWritten);
Dictionary<byte[], ValueKind> dictionary = new Dictionary<byte[], ValueKind>();
foreach (KeyValuePair<byte[], EncodedValue> property in _properties) {
EncodedValue value3 = property.Value;
if (value3.Kind != ValueKind.Removed) {
value3 = property.Value;
if (!value3.Kind.HasFlag(ValueKind.ModelOwned)) {
ReadOnlySpan<byte> readOnlySpan = property.Key;
if (readOnlySpan.StartsWith(span2)) {
readOnlySpan = readOnlySpan.Slice(span2.Length);
WriteEncodedValueAsJson(writer, readOnlySpan.GetPropertyNameFromSlice(), property.Value);
Dictionary<byte[], ValueKind> dictionary2 = dictionary;
byte[] key = property.Key;
value3 = property.Value;
dictionary2.Add(key, value3.Kind);
}
}
}
}
foreach (KeyValuePair<byte[], ValueKind> item in dictionary) {
_properties.TryUpdateValueKind(item.Key, item.Value | ValueKind.ModelOwned);
}
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
[EditorBrowsable(EditorBrowsableState.Never)]
public unsafe void WriteTo(Utf8JsonWriter writer)
{
bool flag = writer.CurrentDepth == 0 && writer.BytesCommitted == 0 && writer.BytesPending == 0;
ReadOnlyMemory<byte> value = _rawJson.Value;
bool flag2 = !value.IsEmpty;
SpanHashSet spanHashSet = null;
if ((!flag2 && _properties == null) & flag) {
writer.WriteStartObject();
writer.WriteEndObject();
} else if (_properties != null || flag) {
Dictionary<byte[], EncodedValue>.Enumerator enumerator;
EncodedValue value3;
if (_properties != null && (!flag2 || !flag)) {
EncodedValue value2;
bool flag3 = (!flag2 & flag) && !_properties.TryGetValue(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.33B67CB5385CEDDAD93D0EE960679041613BED34B8B4A5E6362FE7539BA2D3CE, 1), out value2) && !value2.Kind.HasFlag(ValueKind.ArrayItemAppend);
if (flag3)
writer.WriteStartObject();
enumerator = _properties.GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<byte[], EncodedValue> current = enumerator.Current;
value3 = current.Value;
if (value3.Kind != ValueKind.Removed) {
value3 = current.Value;
if (!value3.Kind.HasFlag(ValueKind.ModelOwned)) {
value3 = current.Value;
if (value3.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
ReadOnlySpan<byte> firstNonIndexParent = current.Key.GetFirstNonIndexParent();
if (spanHashSet == null || !spanHashSet.Contains(firstNonIndexParent)) {
if (!current.Key.IsRoot() && !current.Key.IsArrayIndex())
writer.WritePropertyName(current.Key.GetPropertyName());
_properties.TryGetValue(firstNonIndexParent, out EncodedValue value4);
writer.WriteRawValue(GetCombinedArray(firstNonIndexParent, value4).Span, false);
if (spanHashSet == null)
spanHashSet = new SpanHashSet();
spanHashSet.Add(firstNonIndexParent);
}
} else
WriteEncodedValueAsJson(writer, current.Key.GetPropertyName(), current.Value);
}
}
}
} finally {
((IDisposable)enumerator).Dispose();
}
if (flag3)
writer.WriteEndObject();
} else if (_properties == null) {
value = _rawJson.Value;
if (!value.IsEmpty && writer.CurrentDepth == 0 && writer.BytesCommitted == 0 && writer.BytesPending == 0) {
value = _rawJson.Value;
writer.WriteRawValue(value.Span, false);
}
} else {
ReadOnlyMemory<byte> readOnlyMemory = _rawJson.Value;
enumerator = _properties.GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<byte[], EncodedValue> current2 = enumerator.Current;
value3 = current2.Value;
if (value3.Kind.HasFlag(ValueKind.Removed))
readOnlyMemory = readOnlyMemory.Remove(current2.Key);
else {
value3 = current2.Value;
if (value3.Kind.HasFlag(ValueKind.ArrayItemAppend)) {
ReadOnlyMemory<byte> json = readOnlyMemory;
ReadOnlySpan<byte> arrayPath = current2.Key;
value3 = current2.Value;
value = value3.Value;
value3 = current2.Value;
readOnlyMemory = json.Append(arrayPath, value.Slice(1, value3.Value.Length - 2));
} else
readOnlyMemory = readOnlyMemory.Set(current2.Key, GetEncodedBytes(current2.Value));
}
}
} finally {
((IDisposable)enumerator).Dispose();
}
writer.WriteRawValue(readOnlyMemory.Span, false);
}
}
}
private static ReadOnlyMemory<byte> GetEncodedBytes(EncodedValue value)
{
ValueKind kind = value.Kind;
if (kind.HasFlag(ValueKind.Utf8String) || kind.HasFlag(ValueKind.DateTime) || kind.HasFlag(ValueKind.Guid) || kind.HasFlag(ValueKind.TimeSpan)) {
byte b = 34;
ReadOnlySpan<byte> span = value.Value.Span;
int num = 0;
byte[] array = new byte[2 + span.Length];
array[num] = b;
num++;
span.CopyTo(new Span<byte>(array).Slice(num, span.Length));
num += span.Length;
array[num] = 34;
return new ReadOnlyMemory<byte>(array);
}
return value.Value;
}
private static void WriteEncodedValueAsJson([System.Runtime.CompilerServices.Nullable(1)] Utf8JsonWriter writer, ReadOnlySpan<byte> propertyName, EncodedValue encodedValue)
{
ReadOnlyMemory<byte> value = encodedValue.Value;
if (value.Length == 0)
throw new ArgumentException("Empty encoded value");
ValueKind valueKind = encodedValue.Kind & ~ValueKind.ArrayItemAppend;
value = encodedValue.Value;
ReadOnlySpan<byte> span = value.Span;
if (!propertyName.IsEmpty)
writer.WritePropertyName(propertyName);
switch (valueKind) {
case ValueKind.Removed:
break;
case ValueKind.Number:
writer.WriteRawValue(span, false);
break;
case ValueKind.BooleanTrue:
case ValueKind.BooleanFalse:
writer.WriteBooleanValue(valueKind == ValueKind.BooleanTrue);
break;
case ValueKind.Json:
writer.WriteRawValue(span, true);
break;
case ValueKind.Null:
writer.WriteNullValue();
break;
case ValueKind.Utf8String:
case ValueKind.DateTime:
case ValueKind.Guid:
case ValueKind.TimeSpan:
writer.WriteStringValue(span);
break;
default:
throw new NotSupportedException($"""{valueKind}");
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
private unsafe void WriteAsJsonPatchTo(Utf8JsonWriter writer)
{
if (_properties != null) {
ReadOnlyMemory<byte> value = _rawJson.Value;
bool flag = !value.IsEmpty;
ReadOnlyMemory<byte> value3 = _rawJson.Value;
int num = _properties.MaxKeyLength << 1;
Span<byte> buffer = new Span<byte>(stackalloc byte[(int)(uint)num], num);
foreach (KeyValuePair<byte[], EncodedValue> property in _properties) {
EncodedValue value2 = property.Value;
bool flag2 = value2.Kind.HasFlag(ValueKind.ArrayItemAppend);
value2 = property.Value;
ReadOnlySpan<byte> utf8Value;
ReadOnlyMemory<byte> target;
if (value2.Kind == ValueKind.Removed)
utf8Value = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.E1DB42A568E5246D5F800C8CB69BCC3E097730572AA5B89B8012AE1400008B4C, 6);
else if (flag2 || !flag || !_rawJson.Value.TryGetJson(property.Key, out target)) {
utf8Value = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.E85D22CC2678869C9425831CBC59ED688F5415192A32129FB2A404D693BCF601, 3);
} else {
value2 = property.Value;
value = value2.Value;
ReadOnlySpan<byte> span = value.Span;
if (span.SequenceEqual(target.Span) || (span.Length > 2 && span[0] == 34 && span[span.Length - 1] == 34 && span.Slice(1, span.Length - 2).SequenceEqual(target.Span)))
continue;
utf8Value = new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.28E9B4CAF31EF6B6F5E415FD4C329980316DF1714DBE2D7798E4035D7228D5FD, 7);
}
writer.WriteStartObject();
writer.WritePropertyName(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.70147C9CC7A38C5E292AE6CB58C4969BC624448EF58138049B67010DE248DC3F, 2));
writer.WriteStringValue(utf8Value);
writer.WritePropertyName(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.0B693A4BBE070FB05B1D70EECD2EB3964059C4739AD3616B02A57B582E4B77F3, 4));
int length = property.Key.ConvertToJsonPointer(buffer, flag2);
writer.WriteStringValue(buffer.Slice(0, length));
value2 = property.Value;
if (value2.Kind != ValueKind.Removed) {
writer.WritePropertyName(new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.2AC3E771679DFE9EC82B8748F6F7718F3AD0E4EAAFABC9F68F4BC25187A5F230, 5));
value2 = property.Value;
ReadOnlyMemory<byte> readOnlyMemory = value2.Value;
value2 = property.Value;
ValueKind kind = value2.Kind;
if (flag2 && readOnlyMemory.IsArrayWrapped()) {
kind = ValueKind.Json;
readOnlyMemory = readOnlyMemory.Slice(1, readOnlyMemory.Length - 2);
}
WriteEncodedValueAsJson(writer, ReadOnlySpan<byte>.Empty, new EncodedValue(kind, readOnlyMemory));
}
writer.WriteEndObject();
}
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
private string SerializeToJson()
{
using (UnsafeBufferSequence unsafeBufferSequence = new UnsafeBufferSequence(16384))
using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(unsafeBufferSequence, default(JsonWriterOptions))) {
WriteTo(utf8JsonWriter);
utf8JsonWriter.Flush();
return Encoding.UTF8.GetString(unsafeBufferSequence.ExtractReader().ToBinaryData().ToArray());
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
private string SerializeToJsonPatch()
{
using (UnsafeBufferSequence unsafeBufferSequence = new UnsafeBufferSequence(16384))
using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(unsafeBufferSequence, default(JsonWriterOptions))) {
utf8JsonWriter.WriteStartArray();
WriteAsJsonPatchTo(utf8JsonWriter);
utf8JsonWriter.WriteEndArray();
utf8JsonWriter.Flush();
return Encoding.UTF8.GetString(unsafeBufferSequence.ExtractReader().ToBinaryData().ToArray());
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static ReadOnlyMemory<byte> ThrowKeyNotFoundException(ReadOnlySpan<byte> jsonPath)
{
throw new KeyNotFoundException("No value found at JSON path '" + Encoding.UTF8.GetString(jsonPath.ToArray()) + "'.");
}
[System.Runtime.CompilerServices.NullableContext(1)]
private static void ThrowIfNull([System.Runtime.CompilerServices.Nullable(2)] object obj, string parameterName)
{
if (obj == null)
ThrowArgumentNullException(parameterName);
}
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static void ThrowArgumentNullException(string parameterName)
{
throw new ArgumentNullException(parameterName);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static string ThrowFormatNotSupportedException(string format)
{
throw new NotSupportedException("The format '" + format + "' is not supported.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
[return: System.Runtime.CompilerServices.Nullable(1)]
private static T ThrowFormatException<[System.Runtime.CompilerServices.Nullable(2)] T>(ReadOnlySpan<byte> jsonPath)
{
throw new FormatException($"""{Encoding.UTF8.GetString(jsonPath.ToArray())}""{typeof(T)}""");
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Runtime.CompilerServices.NullableContext(2)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static T NullableTypeNotSupported<T>()
{
throw new NotSupportedException($"""{typeof(T)}""");
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static void ThrowIndexOutOfRangeException(ReadOnlySpan<byte> jsonPath)
{
throw new IndexOutOfRangeException("Cannot remove non-existing array item at path '" + Encoding.UTF8.GetString(jsonPath.ToArray()) + "'.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static void ThrowInvalidToken(JsonPathTokenType tokenType)
{
throw new InvalidOperationException($"""{tokenType}");
}
}
}