File: System\Security\Cryptography\Cose\CoseHeaderLabel.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography.Cose\src\System.Security.Cryptography.Cose.csproj (System.Security.Cryptography.Cose)
// 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;
using System.Diagnostics.CodeAnalysis;
 
namespace System.Security.Cryptography.Cose
{
    /// <summary>
    /// Represents a COSE header label.
    /// </summary>
    [DebuggerDisplay("{DebuggerDisplay,nq}")]
    public readonly struct CoseHeaderLabel : IEquatable<CoseHeaderLabel>
    {
        internal string LabelName => LabelAsString != null ? $"\"{LabelAsString}\"" : LabelAsInt32.ToString();
        private string DebuggerDisplay => $"Label = {LabelName}, Type = {(LabelAsString != null ? typeof(string) : typeof(int))}";
 
        // https://www.iana.org/assignments/cose/cose.xhtml#header-parameters
        /// <summary>
        /// Gets a header label that represents the known header parameter "alg".
        /// </summary>
        /// <value>A header label that represents the known header parameter "alg".</value>
        public static CoseHeaderLabel Algorithm => new CoseHeaderLabel(KnownHeaders.Alg);
        /// <summary>
        /// Gets a header label that represents the known header parameter "crit".
        /// </summary>
        /// <value>A header label that represents the known header parameter "crit".</value>
        public static CoseHeaderLabel CriticalHeaders => new CoseHeaderLabel(KnownHeaders.Crit);
        /// <summary>
        /// Gets a header label that represents the known header parameter "content type".
        /// </summary>
        /// <value>A header label> that represents the known header parameter "content type".</value>
        public static CoseHeaderLabel ContentType => new CoseHeaderLabel(KnownHeaders.ContentType);
        /// <summary>
        /// Gets a header label that represents the known header parameter "kid".
        /// </summary>
        /// <value>A header label that represents the known header parameter "kid".</value>
        public static CoseHeaderLabel KeyIdentifier => new CoseHeaderLabel(KnownHeaders.Kid);
 
        internal int LabelAsInt32 { get; }
        internal string? LabelAsString { get; }
        internal int EncodedSize { get; }
 
        /// <summary>
        /// Initializes a new instance of the <see cref="CoseHeaderLabel"/> struct.
        /// </summary>
        /// <param name="label">The header label as an integer.</param>
        public CoseHeaderLabel(int label)
        {
            this = default;
            LabelAsInt32 = label;
            EncodedSize = CoseHelpers.GetIntegerEncodedSize(label);
        }
 
        /// <summary>
        /// Initializes a new instance of the <see cref="CoseHeaderLabel"/> struct.
        /// </summary>
        /// <param name="label">The header label as a text string.</param>
        /// <exception cref="ArgumentNullException"><paramref name="label"/> is <see langword="null"/>.</exception>
        public CoseHeaderLabel(string label)
        {
            if (label is null)
            {
                throw new ArgumentNullException(nameof(label));
            }
 
            this = default;
            LabelAsString = label;
            EncodedSize = CoseHelpers.GetTextStringEncodedSize(label);
        }
 
        /// <summary>
        /// Returns a value indicating whether this instance is equal to the specified instance.
        /// </summary>
        /// <param name="other">The object to compare to this instance.</param>
        /// <returns><see langword="true"/> if the value parameter equals the value of this instance; otherwise, <see langword="false"/>.</returns>
        public bool Equals(CoseHeaderLabel other)
        {
            return LabelAsString == other.LabelAsString && LabelAsInt32 == other.LabelAsInt32;
        }
 
        /// <summary>
        /// Returns a value indicating whether this instance is equal to a specified object.
        /// </summary>
        /// <param name="obj">The object to compare to this instance.</param>
        /// <returns><see langword="true"/> if value is an instance of <see cref="CoseHeaderLabel"/> and equals the value of this instance; otherwise, <see langword="false"/>.</returns>
        public override bool Equals([NotNullWhen(true)] object? obj) => obj is CoseHeaderLabel otherObj && Equals(otherObj);
 
        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>A 32-bit signed integer hash code.</returns>
        public override int GetHashCode()
        {
            // Since this type is used as a key in a dictionary (see CoseHeaderMap)
            // and since the label is potentially adversary-provided, we'll need
            // to randomize the hash code.
 
            if (LabelAsString != null)
            {
                return LabelAsString.GetRandomizedOrdinalHashCode();
            }
 
            return LabelAsInt32.GetRandomizedHashCode();
        }
 
        /// <summary>
        /// Determines whether two specified header label instances are equal.
        /// </summary>
        /// <param name="left">The first object to compare.</param>
        /// <param name="right">The second object to compare.</param>
        /// <returns><see langword="true"/> if left and right represent the same label; otherwise, <see langword="false"/>.</returns>
        public static bool operator ==(CoseHeaderLabel left, CoseHeaderLabel right) => left.Equals(right);
 
        /// <summary>
        /// Determines whether two specified header label instances are not equal.
        /// </summary>
        /// <param name="left">The first object to compare.</param>
        /// <param name="right">The second object to compare.</param>
        /// <returns><see langword="true"/> if left and right do not represent the same label; otherwise, <see langword="false"/>.</returns>
        public static bool operator !=(CoseHeaderLabel left, CoseHeaderLabel right) => !left.Equals(right);
    }
}