< Summary

Information
Line coverage
0%
Covered lines: 0
Uncovered lines: 41
Coverable lines: 41
Total lines: 92
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 45
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
Equals(...)100%110%
Equals(...)0%220%
GetHashCode()100%110%
Equals(...)0%440%
GetKey(...)0%39390%

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Metadata\PropertyRef.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Runtime.CompilerServices;
 6using System.Runtime.InteropServices;
 7
 8namespace System.Text.Json.Serialization.Metadata
 9{
 10    /// <summary>
 11    /// Represents a UTF-8 encoded JSON property name and its associated <see cref="JsonPropertyInfo"/>, if available.
 12    /// PropertyRefs use byte sequence equality, so equal JSON strings with alternate encodings or casings are not equal
 13    /// Used as a first-level cache for property lookups before falling back to UTF decoding and string comparison.
 14    /// </summary>
 15    internal readonly struct PropertyRef(ulong key, JsonPropertyInfo? info, byte[] utf8PropertyName) : IEquatable<Proper
 16    {
 17        // The length of the property name embedded in the key (in bytes).
 18        // The key is a ulong (8 bytes) containing the first 7 bytes of the property name
 19        // followed by a byte representing the length.
 20        private const int PropertyNameKeyLength = 7;
 21
 22        /// <summary>
 23        /// A custom hashcode produced from the UTF-8 encoded property name.
 24        /// </summary>
 025        public readonly ulong Key = key;
 26
 27        /// <summary>
 28        /// The <see cref="JsonPropertyInfo"/> associated with the property name, if available.
 29        /// </summary>
 030        public readonly JsonPropertyInfo? Info = info;
 31
 32        /// <summary>
 33        /// Caches a heap allocated copy of the UTF-8 encoded property name.
 34        /// </summary>
 035        public readonly byte[] Utf8PropertyName = utf8PropertyName;
 36
 037        public bool Equals(PropertyRef other) => Equals(other.Utf8PropertyName, other.Key);
 038        public override bool Equals(object? obj) => obj is PropertyRef other && Equals(other);
 039        public override int GetHashCode() => Key.GetHashCode();
 40
 41        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 42        public bool Equals(ReadOnlySpan<byte> propertyName, ulong key)
 043        {
 44            // If the property name is less than 8 bytes, it is embedded in the key so no further comparison is necessar
 045            return key == Key && (propertyName.Length <= PropertyNameKeyLength || propertyName.SequenceEqual(Utf8Propert
 046        }
 47
 48        /// <summary>
 49        /// Get a key from the property name.
 50        /// The key consists of the first 7 bytes of the property name and then the least significant bits of the length
 51        /// </summary>
 52        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 53        public static ulong GetKey(ReadOnlySpan<byte> name)
 054        {
 055            int length = name.Length;
 056            ulong key = (ulong)(byte)length << 56;
 057            key |= length switch
 058            {
 059                0 => 0,
 060                1 => name[0],
 061                2 => MemoryMarshal.Read<ushort>(name),
 062                3 => MemoryMarshal.Read<ushort>(name) | ((ulong)name[2] << 16),
 063                4 => MemoryMarshal.Read<uint>(name),
 064                5 => MemoryMarshal.Read<uint>(name) | ((ulong)name[4] << 32),
 065                6 => MemoryMarshal.Read<uint>(name) | ((ulong)MemoryMarshal.Read<ushort>(name.Slice(4, 2)) << 32),
 066                7 => MemoryMarshal.Read<uint>(name) | ((ulong)MemoryMarshal.Read<ushort>(name.Slice(4, 2)) << 32) | ((ul
 067                _ => MemoryMarshal.Read<ulong>(name) & 0x00ffffffffffffffUL
 068            };
 69#if DEBUG
 70            // Verify key contains the embedded bytes as expected.
 71            // Note: the expected properties do not hold true on big-endian platforms
 072            if (BitConverter.IsLittleEndian)
 073            {
 74                const int BitsInByte = 8;
 075                Debug.Assert(
 076                    // Verify embedded property name.
 077                    (name.Length < 1 || name[0] == ((key & ((ulong)0xFF << BitsInByte * 0)) >> BitsInByte * 0)) &&
 078                    (name.Length < 2 || name[1] == ((key & ((ulong)0xFF << BitsInByte * 1)) >> BitsInByte * 1)) &&
 079                    (name.Length < 3 || name[2] == ((key & ((ulong)0xFF << BitsInByte * 2)) >> BitsInByte * 2)) &&
 080                    (name.Length < 4 || name[3] == ((key & ((ulong)0xFF << BitsInByte * 3)) >> BitsInByte * 3)) &&
 081                    (name.Length < 5 || name[4] == ((key & ((ulong)0xFF << BitsInByte * 4)) >> BitsInByte * 4)) &&
 082                    (name.Length < 6 || name[5] == ((key & ((ulong)0xFF << BitsInByte * 5)) >> BitsInByte * 5)) &&
 083                    (name.Length < 7 || name[6] == ((key & ((ulong)0xFF << BitsInByte * 6)) >> BitsInByte * 6)) &&
 084                    // Verify embedded length.
 085                    (key & ((ulong)0xFF << BitsInByte * 7)) >> BitsInByte * 7 == (byte)name.Length,
 086                    "Embedded bytes not as expected");
 087            }
 88#endif
 089            return key;
 090        }
 91    }
 92}