示例#1
0
        private static Span <byte> SerializeArray(BitEndianess endianess, object fieldValueAsObject, FieldInfo field, string typeName, Span <byte> itr)
        {
            Array list        = (Array)fieldValueAsObject;
            Type  fieldType   = field.FieldType;
            Type  elementType = fieldType.GetElementType() !;

            // Get the serialization settings for the array.
            BitArrayAttribute?arrayAttribute = field.GetCustomAttribute <BitArrayAttribute>();

            if (arrayAttribute == null)
            {
                throw new Exception($"Field ${field.Name} from type ${typeName} must be annotated with BitArrayAttribute.");
            }

            int backfillCount = 0;

            switch (arrayAttribute.SizeType)
            {
            case BitArraySizeType.Const:
                int collectionCount = list?.Length ?? 0;

                // Ensure provided array isn't too large.
                if (collectionCount > arrayAttribute.ConstSize)
                {
                    throw new Exception($"List ${field.Name} from type ${typeName} is too large.");
                }

                backfillCount = arrayAttribute.ConstSize - collectionCount;
                break;

            case BitArraySizeType.EndFill:
                break;

            default:
                throw new Exception($"Unknown BitArraySizeType value {arrayAttribute.SizeType}");
            }

            // Serialize the array's items.
            if (list != null)
            {
                foreach (object?item in list)
                {
                    itr = SerializeValue(endianess, item !, elementType !, field.Name, itr);
                }
            }

            // Backfill the serialized array with default values (if neccessary).
            if (backfillCount > 0)
            {
                object defaultValue = Activator.CreateInstance(elementType !) !;
                for (int i = 0; i != backfillCount; ++i)
                {
                    itr = SerializeValue(endianess, defaultValue, elementType !, field.Name, itr);
                }
            }

            return(itr);
        }
示例#2
0
        private static ReadOnlySpan <byte> DeserializeArray(BitEndianess endianess, FieldInfo field, string typeName, ReadOnlySpan <byte> itr, out object value)
        {
            Type fieldType   = field.FieldType;
            Type elementType = fieldType.GetElementType() !;

            // Get the serialization settings for the array.
            BitArrayAttribute?arrayAttribute = field.GetCustomAttribute <BitArrayAttribute>();

            if (arrayAttribute == null)
            {
                throw new Exception($"Field ${field.Name} from type ${typeName} must be annotated with BitArrayAttribute.");
            }

            switch (arrayAttribute.SizeType)
            {
            case BitArraySizeType.Const:
            {
                int collectionSize = arrayAttribute.ConstSize;

                Array list = Array.CreateInstance(elementType, collectionSize);

                // Deserialize the array's items.
                for (int i = 0; i != collectionSize; ++i)
                {
                    object itemValue;
                    itr = DeserializeValue(endianess, elementType, itr, field.Name, out itemValue);
                    list.SetValue(itemValue, i);
                }

                value = list;
                break;
            }

            case BitArraySizeType.EndFill:
            {
                Type  listType = typeof(List <>).MakeGenericType(elementType);
                IList list     = (IList)Activator.CreateInstance(listType) !;

                // Deserialize the array's items.
                // Since this is an end fill array, keep going until there is no more input.
                while (!itr.IsEmpty)
                {
                    object itemValue;
                    itr = DeserializeValue(endianess, elementType !, itr, field.Name, out itemValue);
                    list.Add(itemValue);
                }

                // Call ToArray() on list.
                value = listType.GetMethod(nameof(List <int> .ToArray)) !.Invoke(list, null) !;
                break;
            }

            default:
                throw new Exception($"Unknown BitArraySizeType value {arrayAttribute.SizeType}");
            }

            return(itr);
        }
示例#3
0
        public BasePacketView(BitEndianess e)
        {
            Endianess = e;

            if (Endianess == BitEndianess.LittleBigEndian || Endianess == BitEndianess.BigLittleEndian)
            {
                throw new NotImplementedException("LittleBigEndian and BigLittleEndian NYI");
            }
        }
示例#4
0
        public static byte[] ConvertUInt8(Byte value, BitEndianess bitEndianess = BitEndianess.Msb)
        {
            // Change bit-order if appropriate.
            byte[] buffer = new byte[1];
            if (BitEndianess.Lsb == bitEndianess)
            {
                value = (byte)IPAddress.HostToNetworkOrder(value);
            }

            buffer[0] = value;

            return(buffer);
        }
示例#5
0
        private static IntegerOrEnumTypeInfo GetIntegerOrEnumTypeInfo(INamedTypeSymbol typeSymbol, BitEndianess endianess)
        {
            IntegerOrEnumTypeInfo result;

            string endianessName = endianess == BitEndianess.BigEndian ?
                                   "BigEndian" :
                                   "LittleEndian";

            ITypeSymbol fieldUnderlyingType = typeSymbol;

            result.SerializeTypeCast   = string.Empty;
            result.DeserializeTypeCast = string.Empty;

            if (typeSymbol.TypeKind == TypeKind.Enum)
            {
                fieldUnderlyingType        = typeSymbol.EnumUnderlyingType;
                result.SerializeTypeCast   = $"({SourceGenUtils.GetTypeFullName(fieldUnderlyingType)})";
                result.DeserializeTypeCast = $"({SourceGenUtils.GetTypeFullName(typeSymbol)})";
            }

            switch (fieldUnderlyingType.SpecialType)
            {
            case SpecialType.System_Byte:
            case SpecialType.System_SByte:
                result.SerializeFuncName   = $"global::BitSerialization.Generated.BitPrimitivesSerializer.TryWrite{fieldUnderlyingType.Name}";
                result.DeserializeFuncName = $"global::BitSerialization.Generated.BitPrimitivesSerializer.TryRead{fieldUnderlyingType.Name}";
                break;

            case SpecialType.System_UInt16:
            case SpecialType.System_Int16:
            case SpecialType.System_UInt32:
            case SpecialType.System_Int32:
            case SpecialType.System_UInt64:
            case SpecialType.System_Int64:
                result.SerializeFuncName   = $"global::System.Buffers.Binary.BinaryPrimitives.TryWrite{fieldUnderlyingType.Name}{endianessName}";
                result.DeserializeFuncName = $"global::System.Buffers.Binary.BinaryPrimitives.TryRead{fieldUnderlyingType.Name}{endianessName}";
                break;

            default:
                throw new Exception();
            }

            switch (fieldUnderlyingType.SpecialType)
            {
            case SpecialType.System_Byte:
            case SpecialType.System_SByte:
                result.TypeSize = 1;
                break;

            case SpecialType.System_UInt16:
            case SpecialType.System_Int16:
                result.TypeSize = 2;
                break;

            case SpecialType.System_UInt32:
            case SpecialType.System_Int32:
                result.TypeSize = 4;
                break;

            case SpecialType.System_UInt64:
            case SpecialType.System_Int64:
                result.TypeSize = 8;
                break;

            default:
                throw new Exception();
            }

            return(result);
        }
示例#6
0
 public static byte[] ConvertInt64(Int64 value, ByteEndianess byteEndianess = ByteEndianess.LittleEndian, BitEndianess bitEndianess = BitEndianess.Msb)
 {
     byte[] buffer = new byte[8];
     if (ByteEndianess.BigEndian == byteEndianess)
     {
         buffer[0] = ((Byte)(value >> 56));
         buffer[1] = ((Byte)(value >> 48));
         buffer[2] = ((Byte)(value >> 40));
         buffer[3] = ((Byte)(value >> 32));
         buffer[4] = ((Byte)(value >> 24));
         buffer[5] = ((Byte)(value >> 16));
         buffer[6] = ((Byte)(value >> 8));
         buffer[7] = ((Byte)value);
     }
     else
     {
         buffer[0] = ((Byte)value);
         buffer[1] = ((Byte)(value >> 8));
         buffer[2] = ((Byte)(value >> 16));
         buffer[3] = ((Byte)(value >> 24));
         buffer[4] = ((Byte)(value >> 32));
         buffer[5] = ((Byte)(value >> 40));
         buffer[6] = ((Byte)(value >> 48));
         buffer[7] = ((Byte)(value >> 56));
     }
     return(buffer);
 }
示例#7
0
 public static byte[] ConvertInt32(Int32 value, ByteEndianess byteEndianess = ByteEndianess.LittleEndian, BitEndianess bitEndianess = BitEndianess.Msb)
 {
     byte[] buffer = new byte[4];
     if (ByteEndianess.BigEndian == byteEndianess)
     {
         buffer[0] = ((Byte)(value >> 24));
         buffer[1] = ((Byte)(value >> 16));
         buffer[2] = ((Byte)(value >> 8));
         buffer[3] = ((Byte)value);
     }
     else
     {
         buffer[0] = ((Byte)value);
         buffer[1] = ((Byte)(value >> 8));
         buffer[2] = ((Byte)(value >> 16));
         buffer[3] = ((Byte)(value >> 24));
     }
     return(buffer);
 }
示例#8
0
 public static byte[] ConvertUInt16(UInt16 value, ByteEndianess byteEndianess = ByteEndianess.LittleEndian, BitEndianess bitEndianess = BitEndianess.Msb)
 {
     byte[] buffer = new byte[2];
     if (ByteEndianess.BigEndian == byteEndianess)
     {
         buffer[0] = ((Byte)(value >> 8));
         buffer[1] = ((Byte)value);
     }
     else
     {
         buffer[0] = ((Byte)value);
         buffer[1] = ((Byte)(value >> 8));
     }
     return(buffer);
 }
示例#9
0
 public BinaryParser(Stream stream, ByteEndianess byteEndianess, BitEndianess bitEndianess) : this(stream)
 {
     myByteEndianess = byteEndianess;
     myBitEndianess  = bitEndianess;
 }
示例#10
0
 public BinaryParser(Byte[] data, ByteEndianess byteEndianess, BitEndianess bitEndianess)
     : this(data)
 {
     myByteEndianess = byteEndianess;
     myBitEndianess  = bitEndianess;
 }
示例#11
0
        private static ReadOnlySpan <byte> DeserializeValue(BitEndianess endianess, Type valueType, ReadOnlySpan <byte> itr, string fieldName, out object value)
        {
            if (valueType.IsStruct() || valueType.IsClass)
            {
                return(Deserialize(itr, valueType, out value));
            }

            // If the value is an enum, then get the enum's underlying integer type.
            Type underlyingValueType = valueType;

            if (valueType.IsEnum)
            {
                underlyingValueType = valueType.GetEnumUnderlyingType();
            }

            bool success;
            int  fieldSize;

            if (underlyingValueType == typeof(byte))
            {
                fieldSize = sizeof(byte);

                byte fieldValue;
                success = TryReadUInt8(itr, out fieldValue);
                value   = fieldValue;
            }
            else if (underlyingValueType == typeof(sbyte))
            {
                fieldSize = sizeof(sbyte);

                sbyte fieldValue;
                success = TryReadInt8(itr, out fieldValue);
                value   = fieldValue;
            }
            else if (underlyingValueType == typeof(short))
            {
                fieldSize = sizeof(short);

                short fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadInt16BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadInt16LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else if (underlyingValueType == typeof(ushort))
            {
                fieldSize = sizeof(ushort);

                ushort fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadUInt16BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadUInt16LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else if (underlyingValueType == typeof(int))
            {
                fieldSize = sizeof(int);

                int fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadInt32BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadInt32LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else if (underlyingValueType == typeof(uint))
            {
                fieldSize = sizeof(uint);

                uint fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadUInt32BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadUInt32LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else if (underlyingValueType == typeof(long))
            {
                fieldSize = sizeof(long);

                long fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadInt64BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadInt64LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else if (underlyingValueType == typeof(ulong))
            {
                fieldSize = sizeof(ulong);

                ulong fieldValue;
                success = endianess == BitEndianess.BigEndian ?
                          BinaryPrimitives.TryReadUInt64BigEndian(itr, out fieldValue) :
                          BinaryPrimitives.TryReadUInt64LittleEndian(itr, out fieldValue);

                value = fieldValue;
            }
            else
            {
                throw new Exception($"Can't deserialize type of {valueType.Name} from field {fieldName}.");
            }

            if (!success)
            {
                throw new Exception($"Not enough bytes to deserialize field {fieldName} of type {valueType.Name}.");
            }

            if (valueType.IsEnum)
            {
                // Convert integer value to enum value.
                value = Enum.ToObject(valueType, value);
            }

            return(itr.Slice(fieldSize));
        }
示例#12
0
        private static Span <byte> SerializeValue(BitEndianess endianess, object value, Type valueType, string fieldName, Span <byte> itr)
        {
            if (valueType.IsStruct() || valueType.IsClass)
            {
                return(Serialize(itr, value));
            }

            // Convert enum values to their underlying integer type.
            if (valueType.IsEnum)
            {
                valueType = valueType.GetEnumUnderlyingType();
                value     = Convert.ChangeType(value, valueType);
            }

            bool success;
            int  fieldSize;

            switch (value)
            {
            case byte fieldValue:
                fieldSize = sizeof(byte);
                success   = TryWriteUInt8(itr, fieldValue);
                break;

            case sbyte fieldValue:
                fieldSize = sizeof(sbyte);
                success   = TryWriteInt8(itr, fieldValue);
                break;

            case short fieldValue:
                fieldSize = sizeof(short);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteInt16BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteInt16LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            case ushort fieldValue:
                fieldSize = sizeof(ushort);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteUInt16BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteUInt16LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            case int fieldValue:
                fieldSize = sizeof(int);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteInt32BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteInt32LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            case uint fieldValue:
                fieldSize = sizeof(uint);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteUInt32BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteUInt32LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            case long fieldValue:
                fieldSize = sizeof(long);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteInt64BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteInt64LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            case ulong fieldValue:
                fieldSize = sizeof(ulong);

                switch (endianess)
                {
                case BitEndianess.BigEndian:
                    success = BinaryPrimitives.TryWriteUInt64BigEndian(itr, fieldValue);
                    break;

                default:
                case BitEndianess.LittleEndian:
                    success = BinaryPrimitives.TryWriteUInt64LittleEndian(itr, fieldValue);
                    break;
                }
                break;

            default:
                throw new Exception($"Can't serialize type of {valueType.Name} from field {fieldName}.");
            }

            if (!success)
            {
                throw new Exception($"Not enough space to serialize type {valueType.Name} from field {fieldName}.");
            }

            return(itr.Slice(fieldSize));
        }
 public static Dictionary <Type, TypeData> GetTypeData(BitEndianess endianess)
 {
     return(endianess == BitEndianess.BigEndian ?
            BigEndianTypes :
            LittleEndianTypes);
 }