/// <summary> /// Protects a byte array. /// </summary> /// <param name="data">The data to protect.</param> /// <param name="protectionType">The type of error protection used.</param> /// <param name="protectedBlockSize">The size of the raw data block.</param> /// <returns>A byte array holding the protected data.</returns> public static byte[] ProtectDataToArray(byte[] data, ErrorProtectionType protectionType, int protectedBlockSize) { List <byte> bytes = new(); foreach (ErrorProtectedBlock b in ProtectData(data, protectionType, protectedBlockSize)) { bytes.AddRange(Serialize(b)); } return(bytes.ToArray()); }
/// <summary> /// Default constructor. /// </summary> /// <param name="type">The type of error correction to use.</param> /// <param name="data">The data to protect.</param> public ErrorProtectedBlock(ErrorProtectionType type, byte[] data) { if (data.Length > 32768) { throw new ArgumentException("Data must no longer than 32768 bytes (32K)."); } if (errorProtection.Length > 256) { throw new ArgumentException("Error protection must no longer than 256 bytes."); } this.errorProtectionType = type; this.data = data; this.errorProtection = GetErrorProtection(data, type); }
/// <summary> /// Deserializes a ErrorProtectedBlock from a byte array. /// </summary> /// <param name="bytes">The byte array to deserialize from.</param> /// <returns></returns> public static ErrorProtectedBlock Deserialize(byte[] bytes) { ErrorProtectedBlock ret = new() { errorProtectionType = (ErrorProtectionType)bytes[0], data = new byte[BitConverter.ToUInt16(bytes, 1)] }; Array.Copy(bytes, 3, ret.data, 0, ret.data.Length); byte len = GetErrorProtectionLength(ret.errorProtectionType); Array.Copy(bytes, 3 + ret.data.Length, ret.errorProtection, 0, len); return(ret); }
//TODO: Add stream deserialization. /// <summary> /// Protects a byte array. /// </summary> /// <param name="data">The data to protect.</param> /// <param name="protectionType">The type of error protection used.</param> /// <param name="protectedBlockSize">The size of the raw data block.</param> /// <returns>An array of ErrorProtectedBlocks holding the protected data.</returns> public static ErrorProtectedBlock[] ProtectData(byte[] data, ErrorProtectionType protectionType, int protectedBlockSize) { List <ErrorProtectedBlock> blocks = new(); int head = 0; while (head > data.Length) { byte[] dataBlock = new byte[Math.Min(protectedBlockSize, data.Length - head)]; Buffer.BlockCopy(data, head, dataBlock, 0, dataBlock.Length); head += dataBlock.Length; blocks.Add(new ErrorProtectedBlock(protectionType, dataBlock)); } return(blocks.ToArray()); }
private static byte[] GetErrorProtection(byte[] data, ErrorProtectionType protectionType) { switch (protectionType) { case ErrorProtectionType.CheckSum8: return(new byte[] { CheckSum.CheckSum8(data) }); case ErrorProtectionType.Fletcher16: return(BitConverter.GetBytes(Fletcher.Fletcher16(data))); case ErrorProtectionType.Fletcher32: return(BitConverter.GetBytes(Fletcher.Fletcher32(data))); case ErrorProtectionType.None: return(Array.Empty <byte>()); default: throw new NotImplementedException(); } }
private static byte GetErrorProtectionLength(ErrorProtectionType type) { byte len = 0xff; switch (type) { case ErrorProtectionType.None: len = 0; break; case ErrorProtectionType.CheckSum8: len = 1; break; case ErrorProtectionType.CheckSum16: len = 2; break; case ErrorProtectionType.CheckSum32: len = 4; break; case ErrorProtectionType.CheckSum64: len = 8; break; case ErrorProtectionType.Fletcher16: len = 2; break; case ErrorProtectionType.Fletcher32: len = 4; break; } if (len == 0xff) { throw new Exception("Invalid error protection type."); } return(len); }