< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 281
Coverable lines: 281
Total lines: 399
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 118
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
GetCompressedIntegerSize(...)0%440%
WriteCompressedInteger(...)0%660%
WriteCompressedInteger(...)0%660%
WriteCompressedSignedInteger(...)0%660%
WriteCompressedSignedInteger(...)0%660%
WriteScalarConstant(...)0%30300%
WriteConstant(...)0%30300%
WriteConstant(...)0%30300%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.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.Buffers.Binary;
 5using System.Diagnostics;
 6
 7namespace System.Reflection.Metadata
 8{
 9    internal static class BlobWriterImpl
 10    {
 11        internal const int SingleByteCompressedIntegerMaxValue = 0x7f;
 12        internal const int TwoByteCompressedIntegerMaxValue = 0x3fff;
 13        internal const int MaxCompressedIntegerValue = 0x1fffffff;
 14        internal const int MinSignedCompressedIntegerValue = unchecked((int)0xF0000000);
 15        internal const int MaxSignedCompressedIntegerValue = 0x0FFFFFFF;
 16        internal const int MaxScalarConstantSize = sizeof(ulong);
 17
 18        internal static int GetCompressedIntegerSize(int value)
 019        {
 020            Debug.Assert(value <= MaxCompressedIntegerValue);
 21
 022            if (value <= SingleByteCompressedIntegerMaxValue)
 023            {
 024                return 1;
 25            }
 26
 027            if (value <= TwoByteCompressedIntegerMaxValue)
 028            {
 029                return 2;
 30            }
 31
 032            return 4;
 033        }
 34
 35        internal static void WriteCompressedInteger(ref BlobWriter writer, uint value)
 036        {
 37            unchecked
 038            {
 039                if (value <= SingleByteCompressedIntegerMaxValue)
 040                {
 041                    writer.WriteByte((byte)value);
 042                }
 043                else if (value <= TwoByteCompressedIntegerMaxValue)
 044                {
 045                    writer.WriteUInt16BE((ushort)(0x8000 | value));
 046                }
 047                else if (value <= MaxCompressedIntegerValue)
 048                {
 049                    writer.WriteUInt32BE(0xc0000000 | value);
 050                }
 51                else
 052                {
 053                    Throw.ValueArgumentOutOfRange();
 54                }
 055            }
 056        }
 57
 58        internal static void WriteCompressedInteger(BlobBuilder writer, uint value)
 059        {
 60            unchecked
 061            {
 062                if (value <= SingleByteCompressedIntegerMaxValue)
 063                {
 064                    writer.WriteByte((byte)value);
 065                }
 066                else if (value <= TwoByteCompressedIntegerMaxValue)
 067                {
 068                    writer.WriteUInt16BE((ushort)(0x8000 | value));
 069                }
 070                else if (value <= MaxCompressedIntegerValue)
 071                {
 072                    writer.WriteUInt32BE(0xc0000000 | value);
 073                }
 74                else
 075                {
 076                    Throw.ValueArgumentOutOfRange();
 77                }
 078            }
 079        }
 80
 81        internal static void WriteCompressedSignedInteger(ref BlobWriter writer, int value)
 082        {
 83            unchecked
 084            {
 85                const int b6 = (1 << 6) - 1;
 86                const int b13 = (1 << 13) - 1;
 87                const int b28 = (1 << 28) - 1;
 88
 89                // 0xffffffff for negative value
 90                // 0x00000000 for non-negative
 091                int signMask = value >> 31;
 92
 093                if ((value & ~b6) == (signMask & ~b6))
 094                {
 095                    int n = ((value & b6) << 1) | (signMask & 1);
 096                    writer.WriteByte((byte)n);
 097                }
 098                else if ((value & ~b13) == (signMask & ~b13))
 099                {
 0100                    int n = ((value & b13) << 1) | (signMask & 1);
 0101                    writer.WriteUInt16BE((ushort)(0x8000 | n));
 0102                }
 0103                else if ((value & ~b28) == (signMask & ~b28))
 0104                {
 0105                    int n = ((value & b28) << 1) | (signMask & 1);
 0106                    writer.WriteUInt32BE(0xc0000000 | (uint)n);
 0107                }
 108                else
 0109                {
 0110                    Throw.ValueArgumentOutOfRange();
 111                }
 0112            }
 0113        }
 114
 115        internal static void WriteCompressedSignedInteger(BlobBuilder writer, int value)
 0116        {
 117            unchecked
 0118            {
 119                const int b6 = (1 << 6) - 1;
 120                const int b13 = (1 << 13) - 1;
 121                const int b28 = (1 << 28) - 1;
 122
 123                // 0xffffffff for negative value
 124                // 0x00000000 for non-negative
 0125                int signMask = value >> 31;
 126
 0127                if ((value & ~b6) == (signMask & ~b6))
 0128                {
 0129                    int n = ((value & b6) << 1) | (signMask & 1);
 0130                    writer.WriteByte((byte)n);
 0131                }
 0132                else if ((value & ~b13) == (signMask & ~b13))
 0133                {
 0134                    int n = ((value & b13) << 1) | (signMask & 1);
 0135                    writer.WriteUInt16BE((ushort)(0x8000 | n));
 0136                }
 0137                else if ((value & ~b28) == (signMask & ~b28))
 0138                {
 0139                    int n = ((value & b28) << 1) | (signMask & 1);
 0140                    writer.WriteUInt32BE(0xc0000000 | (uint)n);
 0141                }
 142                else
 0143                {
 0144                    Throw.ValueArgumentOutOfRange();
 145                }
 0146            }
 0147        }
 148
 149        /// <summary>
 150        /// Writes a scalar (non-string) constant to a span.
 151        /// </summary>
 152        /// <param name="bytes">The span where the content will be encoded.</param>
 153        /// <param name="value">The constant value.</param>
 154        /// <returns>The number of bytes that was written.</returns>
 155        internal static int WriteScalarConstant(Span<byte> bytes, object? value)
 0156        {
 0157            if (value == null)
 0158            {
 159                // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 4-by
 0160                BinaryPrimitives.WriteUInt32LittleEndian(bytes, 0);
 0161                return sizeof(uint);
 162            }
 163
 0164            var type = value.GetType();
 0165            if (type.IsEnum)
 0166            {
 0167                type = Enum.GetUnderlyingType(type);
 0168            }
 169
 0170            if (type == typeof(bool))
 0171            {
 0172                bytes[0] = (byte)((bool)value ? 1 : 0);
 0173                return sizeof(bool);
 174            }
 0175            else if (type == typeof(int))
 0176            {
 0177                BinaryPrimitives.WriteInt32LittleEndian(bytes, (int)value);
 0178                return sizeof(int);
 179            }
 0180            else if (type == typeof(byte))
 0181            {
 0182                bytes[0] = (byte)value;
 0183                return sizeof(byte);
 184            }
 0185            else if (type == typeof(char))
 0186            {
 0187                BinaryPrimitives.WriteUInt16LittleEndian(bytes, (char)value);
 0188                return sizeof(char);
 189            }
 0190            else if (type == typeof(double))
 0191            {
 192#if NET
 0193                BinaryPrimitives.WriteDoubleLittleEndian(bytes, (double)value);
 194#else
 195                double v = (double)value;
 196                unsafe
 197                {
 198                    BinaryPrimitives.WriteUInt64LittleEndian(bytes, *(ulong*)(&v));
 199                }
 200#endif
 0201                return sizeof(double);
 202            }
 0203            else if (type == typeof(short))
 0204            {
 0205                BinaryPrimitives.WriteInt16LittleEndian(bytes, (short)value);
 0206                return sizeof(short);
 207            }
 0208            else if (type == typeof(long))
 0209            {
 0210                BinaryPrimitives.WriteInt64LittleEndian(bytes, (long)value);
 0211                return sizeof(long);
 212            }
 0213            else if (type == typeof(sbyte))
 0214            {
 0215                bytes[0] = (byte)(sbyte)value;
 0216                return sizeof(sbyte);
 217            }
 0218            else if (type == typeof(float))
 0219            {
 220#if NET
 0221                BinaryPrimitives.WriteSingleLittleEndian(bytes, (float)value);
 222#else
 223                float v = (float)value;
 224                unsafe
 225                {
 226                    BinaryPrimitives.WriteUInt32LittleEndian(bytes, *(uint*)(&v));
 227                }
 228#endif
 0229                return sizeof(float);
 230            }
 0231            else if (type == typeof(ushort))
 0232            {
 0233                BinaryPrimitives.WriteUInt16LittleEndian(bytes, (ushort)value);
 0234                return sizeof(ushort);
 235            }
 0236            else if (type == typeof(uint))
 0237            {
 0238                BinaryPrimitives.WriteUInt32LittleEndian(bytes, (uint)value);
 0239                return sizeof(uint);
 240            }
 0241            else if (type == typeof(ulong))
 0242            {
 0243                BinaryPrimitives.WriteUInt64LittleEndian(bytes, (ulong)value);
 0244                return sizeof(ulong);
 245            }
 246            else
 0247            {
 0248                throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type));
 249            }
 0250        }
 251
 252        internal static void WriteConstant(ref BlobWriter writer, object? value)
 0253        {
 0254            if (value == null)
 0255            {
 256                // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 4-by
 0257                writer.WriteUInt32(0);
 0258                return;
 259            }
 260
 0261            var type = value.GetType();
 0262            if (type.IsEnum)
 0263            {
 0264                type = Enum.GetUnderlyingType(type);
 0265            }
 266
 0267            if (type == typeof(bool))
 0268            {
 0269                writer.WriteBoolean((bool)value);
 0270            }
 0271            else if (type == typeof(int))
 0272            {
 0273                writer.WriteInt32((int)value);
 0274            }
 0275            else if (type == typeof(string))
 0276            {
 0277                writer.WriteUTF16((string)value);
 0278            }
 0279            else if (type == typeof(byte))
 0280            {
 0281                writer.WriteByte((byte)value);
 0282            }
 0283            else if (type == typeof(char))
 0284            {
 0285                writer.WriteUInt16((char)value);
 0286            }
 0287            else if (type == typeof(double))
 0288            {
 0289                writer.WriteDouble((double)value);
 0290            }
 0291            else if (type == typeof(short))
 0292            {
 0293                writer.WriteInt16((short)value);
 0294            }
 0295            else if (type == typeof(long))
 0296            {
 0297                writer.WriteInt64((long)value);
 0298            }
 0299            else if (type == typeof(sbyte))
 0300            {
 0301                writer.WriteSByte((sbyte)value);
 0302            }
 0303            else if (type == typeof(float))
 0304            {
 0305                writer.WriteSingle((float)value);
 0306            }
 0307            else if (type == typeof(ushort))
 0308            {
 0309                writer.WriteUInt16((ushort)value);
 0310            }
 0311            else if (type == typeof(uint))
 0312            {
 0313                writer.WriteUInt32((uint)value);
 0314            }
 0315            else if (type == typeof(ulong))
 0316            {
 0317                writer.WriteUInt64((ulong)value);
 0318            }
 319            else
 0320            {
 0321                throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type));
 322            }
 0323        }
 324
 325        internal static void WriteConstant(BlobBuilder writer, object? value)
 0326        {
 0327            if (value == null)
 0328            {
 329                // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 4-by
 0330                writer.WriteUInt32(0);
 0331                return;
 332            }
 333
 0334            var type = value.GetType();
 0335            if (type.IsEnum)
 0336            {
 0337                type = Enum.GetUnderlyingType(type);
 0338            }
 339
 0340            if (type == typeof(bool))
 0341            {
 0342                writer.WriteBoolean((bool)value);
 0343            }
 0344            else if (type == typeof(int))
 0345            {
 0346                writer.WriteInt32((int)value);
 0347            }
 0348            else if (type == typeof(string))
 0349            {
 0350                writer.WriteUTF16((string)value);
 0351            }
 0352            else if (type == typeof(byte))
 0353            {
 0354                writer.WriteByte((byte)value);
 0355            }
 0356            else if (type == typeof(char))
 0357            {
 0358                writer.WriteUInt16((char)value);
 0359            }
 0360            else if (type == typeof(double))
 0361            {
 0362                writer.WriteDouble((double)value);
 0363            }
 0364            else if (type == typeof(short))
 0365            {
 0366                writer.WriteInt16((short)value);
 0367            }
 0368            else if (type == typeof(long))
 0369            {
 0370                writer.WriteInt64((long)value);
 0371            }
 0372            else if (type == typeof(sbyte))
 0373            {
 0374                writer.WriteSByte((sbyte)value);
 0375            }
 0376            else if (type == typeof(float))
 0377            {
 0378                writer.WriteSingle((float)value);
 0379            }
 0380            else if (type == typeof(ushort))
 0381            {
 0382                writer.WriteUInt16((ushort)value);
 0383            }
 0384            else if (type == typeof(uint))
 0385            {
 0386                writer.WriteUInt32((uint)value);
 0387            }
 0388            else if (type == typeof(ulong))
 0389            {
 0390                writer.WriteUInt64((ulong)value);
 0391            }
 392            else
 0393            {
 0394                throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type));
 395            }
 0396        }
 397    }
 398}
 399