📄 lib/src/Payloads/Arguments.cs
using System;
using System.Globalization;

namespace SharpDlt.Payloads;

/// <summary>A single argument of a verbose mode payload.</summary>
public abstract partial record DltArgument
{
    /// <summary>Gets a human readable representation of the argument value.</summary>
    public abstract override string ToString();
}

/// <summary>An argument of type bool (BOOL).</summary>
/// <param name="Value">The value of the argument.</param>
public sealed record DltBoolArgument(bool Value) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Value ? "True" : "False";
}

/// <summary>An argument of type signed integer (SINT).</summary>
/// <param name="Value">The value of the argument.</param>
/// <param name="Width">The width of the value as it was encoded.</param>
public sealed record DltSignedArgument(long Value, DltIntegerWidth Width) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Value.ToString(CultureInfo.InvariantCulture);
}

/// <summary>An argument of type unsigned integer (UINT).</summary>
/// <param name="Value">The value of the argument.</param>
/// <param name="Width">The width of the value as it was encoded.</param>
public sealed record DltUnsignedArgument(ulong Value, DltIntegerWidth Width) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Value.ToString(CultureInfo.InvariantCulture);
}

/// <summary>An argument of type float (FLOA).</summary>
/// <param name="Value">The value of the argument.</param>
/// <param name="Width">The width of the value as it was encoded.</param>
public sealed record DltFloatArgument(double Value, DltFloatWidth Width) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Value.ToString(CultureInfo.InvariantCulture);
}

/// <summary>An argument of type string (STRG).</summary>
/// <param name="Value">The value of the argument, without its NUL terminator.</param>
/// <param name="Coding">The coding of the string on the wire.</param>
public sealed record DltStringArgument(string Value, DltStringCoding Coding) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Value;
}

/// <summary>An argument of type raw (RAWD).</summary>
/// <param name="Value">The raw bytes of the argument.</param>
public sealed record DltRawArgument(ReadOnlyMemory<byte> Value) : DltArgument
{
    /// <inheritdoc />
    public override string ToString() => Convert.ToHexString(Value.Span).ToLowerInvariant();

    /// <summary>Determines whether the argument carries the same bytes as <paramref name="other"/>.</summary>
    public bool Equals(DltRawArgument? other) => other is not null && Value.Span.SequenceEqual(other.Value.Span);

    /// <inheritdoc />
    public override int GetHashCode()
    {
        var hash = new HashCode();
        hash.AddBytes(Value.Span);
        return hash.ToHashCode();
    }
}