File: System\Reflection\Metadata\Signatures\SignatureHeader.cs
Web Access
Project: src\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics.CodeAnalysis;
using System.Text;
 
namespace System.Reflection.Metadata
{
    /// <summary>
    /// Represents the signature characteristics specified by the leading byte of signature blobs.
    /// </summary>
    /// <remarks>
    /// This header byte is present in all method definition, method reference, standalone method, field,
    /// property, and local variable signatures, but not in type specification signatures.
    /// </remarks>
    public struct SignatureHeader : IEquatable<SignatureHeader>
    {
        private readonly byte _rawValue;
        public const byte CallingConventionOrKindMask = 0x0F;
        private const byte maxCallingConvention = (byte)SignatureCallingConvention.VarArgs;
 
        public SignatureHeader(byte rawValue)
        {
            _rawValue = rawValue;
        }
 
        public SignatureHeader(SignatureKind kind, SignatureCallingConvention convention, SignatureAttributes attributes)
             : this((byte)((int)kind | (int)convention | (int)attributes))
        {
        }
 
        public byte RawValue
        {
            get { return _rawValue; }
        }
 
        public SignatureCallingConvention CallingConvention
        {
            get
            {
                int callingConventionOrKind = _rawValue & CallingConventionOrKindMask;
 
                if (callingConventionOrKind > maxCallingConvention
                    && callingConventionOrKind != (int)SignatureCallingConvention.Unmanaged)
                {
                    return SignatureCallingConvention.Default;
                }
 
                return (SignatureCallingConvention)callingConventionOrKind;
            }
        }
 
        public SignatureKind Kind
        {
            get
            {
                int callingConventionOrKind = _rawValue & CallingConventionOrKindMask;
 
                if (callingConventionOrKind <= maxCallingConvention
                    || callingConventionOrKind == (int)SignatureCallingConvention.Unmanaged)
                {
                    return SignatureKind.Method;
                }
 
                return (SignatureKind)callingConventionOrKind;
            }
        }
 
        public SignatureAttributes Attributes
        {
            get { return (SignatureAttributes)(_rawValue & ~CallingConventionOrKindMask); }
        }
 
        public bool HasExplicitThis
        {
            get { return (_rawValue & (byte)SignatureAttributes.ExplicitThis) != 0; }
        }
 
        public bool IsInstance
        {
            get { return (_rawValue & (byte)SignatureAttributes.Instance) != 0; }
        }
 
        public bool IsGeneric
        {
            get { return (_rawValue & (byte)SignatureAttributes.Generic) != 0; }
        }
 
        public override bool Equals([NotNullWhen(true)] object? obj)
        {
            return obj is SignatureHeader signatureHeader && Equals(signatureHeader);
        }
 
        public bool Equals(SignatureHeader other)
        {
            return _rawValue == other._rawValue;
        }
 
        public override int GetHashCode()
        {
            return _rawValue;
        }
 
        public static bool operator ==(SignatureHeader left, SignatureHeader right)
        {
            return left._rawValue == right._rawValue;
        }
 
        public static bool operator !=(SignatureHeader left, SignatureHeader right)
        {
            return left._rawValue != right._rawValue;
        }
 
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append(Kind.ToString());
 
            if (Kind == SignatureKind.Method)
            {
                sb.Append(',');
                sb.Append(CallingConvention.ToString());
            }
 
            if (Attributes != SignatureAttributes.None)
            {
                sb.Append(',');
                sb.Append(Attributes.ToString());
            }
 
            return sb.ToString();
        }
    }
}