/// <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());
        }
Example #5
0
        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);
        }