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); }
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); }
public BasePacketView(BitEndianess e) { Endianess = e; if (Endianess == BitEndianess.LittleBigEndian || Endianess == BitEndianess.BigLittleEndian) { throw new NotImplementedException("LittleBigEndian and BigLittleEndian NYI"); } }
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); }
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); }
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); }
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); }
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); }
public BinaryParser(Stream stream, ByteEndianess byteEndianess, BitEndianess bitEndianess) : this(stream) { myByteEndianess = byteEndianess; myBitEndianess = bitEndianess; }
public BinaryParser(Byte[] data, ByteEndianess byteEndianess, BitEndianess bitEndianess) : this(data) { myByteEndianess = byteEndianess; myBitEndianess = bitEndianess; }
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)); }
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); }