void SerializePrimitive(BitStreamWriter writer, object value, PrimitiveContract contract, DsdlType derivedDsdlType, bool tailArrayOptimization) { if (contract.TypeCode == PrimitiveTypeCode.String && derivedDsdlType is ArrayDsdlType adt && adt.IsStringLike) { byte[] stringBytes; if (value == null) { stringBytes = _emptyByteArray; } else { if (!(value is string stringValue)) { throw new ArgumentException("Cannot cast value to string.", nameof(value)); } stringBytes = _encoding.GetBytes(stringValue); } SerializeList(writer, stringBytes, contract, null, adt, tailArrayOptimization); return; } if (!(derivedDsdlType is PrimitiveDsdlType t)) { throw new InvalidOperationException($"Primitive DSDL type expected for type '{contract.UnderlyingType.FullName}'."); } switch (t) { case BooleanDsdlType _: var boolValue = (bool)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(bool)); BitSerializer.Write(writer, boolValue, t.MaxBitlen); break; case IntDsdlType idt: var longValue = (long)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(long)); longValue = ApplyIntegerCastMode(longValue, idt); BitSerializer.Write(writer, longValue, t.MaxBitlen); break; case UIntDsdlType uidt: var ulongValue = (ulong)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(ulong)); ulongValue = ApplyIntegerCastMode(ulongValue, uidt); BitSerializer.Write(writer, ulongValue, t.MaxBitlen); break; case FloatDsdlType fdt: var doubleValue = (double)ConvertUtils.ConvertOrCast(value, CultureInfo.CurrentCulture, typeof(double)); WriteFloatPrimitive(writer, doubleValue, fdt); break; default: throw new ArgumentOutOfRangeException(nameof(t)); } }
static void WriteFloatPrimitive(BitStreamWriter writer, double value, FloatDsdlType type) { var range = TypeLimits.GetFloatRange(type.MaxBitlen); switch (type.CastMode) { case CastMode.Saturated: if (value > range.Maximum) { value = range.Maximum; } if (value < range.Minimum) { value = range.Minimum; } break; case CastMode.Truncated: if (!double.IsNaN(value) && value > range.Maximum) { value = double.PositiveInfinity; } if (!double.IsNaN(value) && value < range.Maximum) { value = double.NegativeInfinity; } break; default: throw new ArgumentOutOfRangeException(); } switch (type.MaxBitlen) { case 16: var val = BitSerializer.Float32ToUInt16((float)value); BitSerializer.Write(writer, val, 16); break; case 32: BitSerializer.Write(writer, (float)value, 32); break; case 64: BitSerializer.Write(writer, value, 64); break; default: throw new InvalidOperationException($"Unexpected float bit lenght: {type.MaxBitlen}."); } }
void WriteUnionFieldIndex(BitStreamWriter writer, int index, CompositeDsdlTypeBase t) { var bitLen = BitSerializer.IntBitLength(t.Fields.Count); BitSerializer.Write(writer, index, bitLen); }
void WriteDynamicArraySize(BitStreamWriter writer, int count, ArrayDsdlType arrayDsdlType) { var bitLen = BitSerializer.IntBitLength(arrayDsdlType.MaxSize + 1); BitSerializer.Write(writer, count, bitLen); }