namespace RioJoy.Core.Protocol; /// /// A fully-framed RIO packet: a command plus its fixed-length payload (the /// 7-bit data bytes between the command byte and the checksum). The checksum /// itself is not stored — it is validated/derived at the framing boundary. /// public readonly struct RioPacket { /// The command byte. public RioCommand Command { get; } /// /// The payload bytes (high bit always clear; treat as read-only). Length /// matches . /// public byte[] Payload { get; } public RioPacket(RioCommand command, byte[] payload) { if (payload is null) throw new ArgumentNullException(nameof(payload)); int expected = RioCommandTable.PayloadLength(command); if (payload.Length != expected) throw new ArgumentException( $"{command} expects a {expected}-byte payload, got {payload.Length}.", nameof(payload)); Command = command; Payload = payload; } public override string ToString() { var hex = BitConverter.ToString(Payload).Replace("-", string.Empty); return Payload.Length == 0 ? Command.ToString() : $"{Command} [{hex}]"; } }