-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
STJ migration: fix server-side view model cache
- Loading branch information
Showing
11 changed files
with
713 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// From https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Range.cs | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#if CSharp8Polyfill | ||
using System.Diagnostics; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Runtime.CompilerServices; | ||
|
||
#if !DotNetCore | ||
using System.Numerics.Hashing; | ||
#endif | ||
|
||
namespace System | ||
{ | ||
/// <summary>Represent a range has start and end indexes.</summary> | ||
/// <remarks> | ||
/// Range is used by the C# compiler to support the range syntax. | ||
/// <code> | ||
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; | ||
/// int[] subArray1 = someArray[0..2]; // { 1, 2 } | ||
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } | ||
/// </code> | ||
/// </remarks> | ||
internal readonly struct Range : IEquatable<Range> | ||
{ | ||
/// <summary>Represent the inclusive start index of the Range.</summary> | ||
public Index Start { get; } | ||
|
||
/// <summary>Represent the exclusive end index of the Range.</summary> | ||
public Index End { get; } | ||
|
||
/// <summary>Construct a Range object using the start and end indexes.</summary> | ||
/// <param name="start">Represent the inclusive start index of the range.</param> | ||
/// <param name="end">Represent the exclusive end index of the range.</param> | ||
public Range(Index start, Index end) | ||
{ | ||
Start = start; | ||
End = end; | ||
} | ||
|
||
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary> | ||
/// <param name="value">An object to compare with this object</param> | ||
public override bool Equals([NotNullWhen(true)] object? value) => | ||
value is Range r && | ||
r.Start.Equals(Start) && | ||
r.End.Equals(End); | ||
|
||
/// <summary>Indicates whether the current Range object is equal to another Range object.</summary> | ||
/// <param name="other">An object to compare with this object</param> | ||
public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); | ||
|
||
/// <summary>Returns the hash code for this instance.</summary> | ||
public override int GetHashCode() | ||
{ | ||
#if (!NETSTANDARD2_0 && !NETFRAMEWORK) | ||
return HashCode.Combine(Start.GetHashCode(), End.GetHashCode()); | ||
#else | ||
return (Start.GetHashCode(), End.GetHashCode()).GetHashCode(); | ||
#endif | ||
} | ||
|
||
/// <summary>Converts the value of the current Range object to its equivalent string representation.</summary> | ||
public override string ToString() | ||
{ | ||
#if (!NETSTANDARD2_0 && !NETFRAMEWORK) | ||
Span<char> span = stackalloc char[2 + (2 * 11)]; // 2 for "..", then for each index 1 for '^' and 10 for longest possible uint | ||
int pos = 0; | ||
|
||
if (Start.IsFromEnd) | ||
{ | ||
span[0] = '^'; | ||
pos = 1; | ||
} | ||
bool formatted = ((uint)Start.Value).TryFormat(span.Slice(pos), out int charsWritten); | ||
Debug.Assert(formatted); | ||
pos += charsWritten; | ||
|
||
span[pos++] = '.'; | ||
span[pos++] = '.'; | ||
|
||
if (End.IsFromEnd) | ||
{ | ||
span[pos++] = '^'; | ||
} | ||
formatted = ((uint)End.Value).TryFormat(span.Slice(pos), out charsWritten); | ||
Debug.Assert(formatted); | ||
pos += charsWritten; | ||
|
||
return new string(span.Slice(0, pos)); | ||
#else | ||
return Start.ToString() + ".." + End.ToString(); | ||
#endif | ||
} | ||
|
||
/// <summary>Create a Range object starting from start index to the end of the collection.</summary> | ||
public static Range StartAt(Index start) => new Range(start, Index.End); | ||
|
||
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary> | ||
public static Range EndAt(Index end) => new Range(Index.Start, end); | ||
|
||
/// <summary>Create a Range object starting from first element to the end.</summary> | ||
public static Range All => new Range(Index.Start, Index.End); | ||
|
||
/// <summary>Calculate the start offset and length of range object using a collection length.</summary> | ||
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param> | ||
/// <remarks> | ||
/// For performance reason, we don't validate the input length parameter against negative values. | ||
/// It is expected Range will be used with collections which always have non negative length/count. | ||
/// We validate the range is inside the length scope though. | ||
/// </remarks> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public (int Offset, int Length) GetOffsetAndLength(int length) | ||
{ | ||
int start = Start.GetOffset(length); | ||
int end = End.GetOffset(length); | ||
|
||
if ((uint)end > (uint)length || (uint)start > (uint)end) | ||
{ | ||
ThrowArgumentOutOfRangeException(); | ||
} | ||
|
||
return (start, end - start); | ||
} | ||
|
||
private static void ThrowArgumentOutOfRangeException() | ||
{ | ||
throw new ArgumentOutOfRangeException("length"); | ||
} | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
// using System.Linq; | ||
// using System; | ||
// using System.Text.Json; | ||
// using System.Diagnostics; | ||
// using System.Buffers; | ||
// using System.Collections.Generic; | ||
|
||
// namespace DotVVM.Framework.Utils | ||
// { | ||
// ref struct JsonPatchWriter | ||
// { | ||
// static void CopyValue(ref Utf8JsonReader reader, Utf8JsonWriter writer) | ||
// { | ||
// Debug.Assert(reader.TokenType != JsonTokenType.PropertyName); | ||
|
||
// if (reader.TokenType is not JsonTokenType.StartArray and not JsonTokenType.StartObject) | ||
// { | ||
// if (reader.HasValueSequence) | ||
// writer.WriteRawValue(reader.ValueSequence); | ||
// else | ||
// writer.WriteRawValue(reader.ValueSpan); | ||
|
||
// return; | ||
// } | ||
|
||
// var depth = reader.CurrentDepth; | ||
// while (reader.CurrentDepth >= depth) | ||
// { | ||
// switch (reader.TokenType) | ||
// { | ||
// case JsonTokenType.False: | ||
// case JsonTokenType.True: | ||
// case JsonTokenType.Null: | ||
// case JsonTokenType.String: | ||
// case JsonTokenType.Number: { | ||
// if (reader.HasValueSequence) | ||
// writer.WriteRawValue(reader.ValueSequence); | ||
// else | ||
// writer.WriteRawValue(reader.ValueSpan); | ||
// break; | ||
// } | ||
// case JsonTokenType.PropertyName: { | ||
// var length = reader.HasValueSequence ? reader.ValueSequence.Length : reader.ValueSpan.Length; | ||
// Span<byte> buffer = length <= 1024 ? stackalloc byte[(int)length] : new byte[length]; | ||
// var realLength = reader.CopyString(buffer); | ||
// writer.WritePropertyName(buffer.Slice(0, realLength)); | ||
// break; | ||
// } | ||
// case JsonTokenType.StartArray: { | ||
// writer.WriteStartArray(); | ||
// break; | ||
// } | ||
// case JsonTokenType.EndArray: { | ||
// writer.WriteEndArray(); | ||
// break; | ||
// } | ||
// case JsonTokenType.StartObject: { | ||
// writer.WriteStartObject(); | ||
// break; | ||
// } | ||
// case JsonTokenType.EndObject: { | ||
// writer.WriteEndObject(); | ||
// break; | ||
// } | ||
// default: { | ||
// throw new JsonException($"Unexpected token {reader.TokenType}."); | ||
// } | ||
// } | ||
// reader.Read(); | ||
// } | ||
// } | ||
|
||
// private readonly Utf8JsonWriter writer; | ||
// private List<JsonElement> patchStack; | ||
// private Span<byte> nameBuffer; | ||
// private byte[] nameBufferRented; | ||
|
||
// private JsonPatchWriter( | ||
// Utf8JsonWriter writer, | ||
// JsonElement patch, | ||
// Span<byte> nameBuffer | ||
// ) | ||
// { | ||
// this.writer = writer; | ||
// } | ||
|
||
// Span<byte> ReadName(ref Utf8JsonReader reader) | ||
// { | ||
// var length = reader.CopyString(nameBuffer); | ||
// if (length < nameBuffer.Length) | ||
// { | ||
// return nameBuffer.Slice(length); | ||
// } | ||
// var newBuffer = ArrayPool<byte>.Shared.Rent(length); | ||
// nameBuffer.CopyTo(newBuffer); | ||
// if (nameBufferRented is {}) | ||
// ArrayPool<byte>.Shared.Return(nameBufferRented); | ||
// nameBuffer = newBuffer; | ||
// nameBufferRented = newBuffer; | ||
// return ReadName(ref reader); | ||
// } | ||
|
||
// private void Patch(ref Utf8JsonReader original, JsonElement patchValue) | ||
// { | ||
// var patchKind = patchValue.ValueKind; | ||
// if (patchKind == JsonValueKind.Object && original.TokenType == JsonTokenType.StartObject) | ||
// { | ||
// PatchObject(ref original, patchValue); | ||
// } | ||
// else if (patchKind == JsonValueKind.Array && original.TokenType == JsonTokenType.StartArray) | ||
// { | ||
// PatchArray(ref original, patchValue); | ||
// } | ||
// else | ||
// { | ||
// patchValue.WriteTo(writer); | ||
// } | ||
// } | ||
|
||
// void PatchObject(ref Utf8JsonReader original, JsonElement patch) | ||
// { | ||
// original.AssertToken(JsonTokenType.StartObject); | ||
// if (patch.ValueKind != JsonValueKind.Object) | ||
// { | ||
// patch.WriteTo(writer); | ||
// return; | ||
// } | ||
// writer.WriteStartObject(); | ||
// original.Read(); | ||
|
||
// var patchedProperties = 0; | ||
// while (original.TokenType == JsonTokenType.PropertyName) | ||
// { | ||
// var propertyName = ReadName(ref original); | ||
// original.Read(); | ||
// writer.WritePropertyName(propertyName); | ||
|
||
// if (!patch.TryGetProperty(propertyName, out var patchValue)) | ||
// { | ||
// CopyValue(ref original, writer); | ||
// continue; | ||
// } | ||
|
||
// patchedProperties += 1; | ||
|
||
// Patch(ref original, patchValue); | ||
// } | ||
// original.AssertToken(JsonTokenType.EndObject); | ||
|
||
// var remainingProperties = -patchedProperties; | ||
// foreach (var p in patch.EnumerateObject()) | ||
// { | ||
// remainingProperties += 1; | ||
// } | ||
// if (remainingProperties > 0) | ||
// { | ||
// throw new JsonException("Patching failed"); | ||
// } | ||
|
||
// writer.WriteEndObject(); | ||
// } | ||
|
||
// void PatchArray(ref Utf8JsonReader original, JsonElement patch) | ||
// { | ||
// using var patchEnumerator = patch.EnumerateArray(); | ||
// original.AssertRead(JsonTokenType.StartArray); | ||
// writer.WriteStartArray(); | ||
|
||
// while (original.TokenType != JsonTokenType.EndArray) | ||
// { | ||
// if (!patchEnumerator.MoveNext()) | ||
// { | ||
// while (original.TokenType != JsonTokenType.EndArray) | ||
// { | ||
// original.Skip(); | ||
// original.Read(); | ||
// } | ||
// } | ||
|
||
// var patchKind = patchEnumerator.Current.ValueKind; | ||
// var tokenType = original.TokenType; | ||
// if (patchKind == JsonValueKind.Object && tokenType == JsonTokenType.StartObject) | ||
// { | ||
// PatchObject(ref original, patchEnumerator.Current); | ||
// } | ||
// else if (patchKind == JsonValueKind.Array && tokenType == JsonTokenType.StartArray) | ||
// { | ||
// PatchArray(ref original, patchEnumerator.Current); | ||
// } | ||
// else | ||
// { | ||
// patchEnumerator.Current.WriteTo(writer); | ||
// } | ||
// original.Read(); | ||
// } | ||
|
||
// while (patchEnumerator.MoveNext()) | ||
// { | ||
// patchEnumerator.Current.WriteTo(writer); | ||
// } | ||
|
||
// writer.WriteEndArray(); | ||
// } | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.