BinSer.cs (7921B)
1 using Serde.Ser; 2 using Std; 3 using Std.Maybe; 4 using Std.Num; 5 using Std.Result; 6 using Std.Vec; 7 using System; 8 using System.Runtime.InteropServices; 9 #region Namespaces 10 namespace Serde.Bin.Ser { 11 #region Types 12 public interface IBinSerializable: ISerializable { 13 14 #region Type-level Constructors 15 #endregion 16 17 #region Instance Constructors 18 #endregion 19 20 #region Type-level Fields 21 #endregion 22 23 #region Instance Fields 24 #endregion 25 26 #region Type-level Properties 27 #endregion 28 29 #region Instance Properties 30 #endregion 31 32 #region Type-level Functions 33 #endregion 34 35 #region Instance Functions 36 public abstract Unit Ser(ref Serializer ser); 37 #endregion 38 39 #region Operators 40 #endregion 41 42 #region Types 43 #endregion 44 } 45 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 0)] 46 public struct Serializer: ISerializer<Unit, Bottom> { 47 48 #region Type-level Constructors 49 #endregion 50 51 #region Instance Constructors 52 public Serializer() => _buffer = new Vec<byte>(); 53 public Serializer(Vec<byte> buffer) => _buffer = buffer; 54 public Serializer(uint bufferSize) => _buffer = Vec<byte>.WithCapacity(bufferSize); 55 #endregion 56 57 #region Type-level Fields 58 #endregion 59 60 #region Instance Fields 61 [FieldOffset(0)] Vec<byte> _buffer; 62 #endregion 63 64 #region Type-level Properties 65 #endregion 66 67 #region Instance Properties 68 public readonly uint Len => _buffer.Len; 69 public readonly Vec<byte> RawBuffer => _buffer; 70 public readonly ReadOnlySpan<byte> SerializedData => _buffer.AsSlice(); 71 #endregion 72 73 #region Type-level Functions 74 public static Serializer New() => new(); 75 public static Serializer NewWithBuffer(Vec<byte> buffer) => new(buffer); 76 public static Serializer NewWithCapacity(uint bufferSize) => new (bufferSize); 77 #endregion 78 79 #region Instance Functions 80 // This exists to avoid copying of data. Instead of one feeding the Serializer bytes to copy internally, 81 // a Span<byte> of its own buffer is handed to downstream code to write into. 82 // This Span<byte> starts at the current position and is of the passed length. 83 // The Serializer assumes every byte is written to and changes its position accordingly. 84 // This means downstream code MUST know exactly how many bytes they want to write as any byte 85 // that is not written to in the Span<byte> will not be detected. 86 public Span<byte> AsMutSlice(uint len) { 87 _ = _buffer.Reserve(len); 88 var origLen = _buffer.Len; 89 // This is safe since we first reserve enough additional space to handle this writing. 90 checked { _ = _buffer.SetLenUnsafe(origLen + len); } 91 return _buffer.AsMutSlice()[(int)origLen..]; 92 } 93 public override readonly bool Equals(object? _) => false; 94 public override readonly int GetHashCode() => 0; 95 public Unit Reset() => _buffer.Clear(); 96 public Unit SerUnsafe<T>(T val) where T: unmanaged { unsafe { return SerSliceUnsafe(new ReadOnlySpan<T>(&val, 1)); } } 97 public Unit Ser(ReadOnlySpan<byte> bytes) => _buffer.ExtendFromSlice(bytes); 98 public Result<Unit, Bottom> Serialize(ReadOnlySpan<byte> bytes) => new(Ser(bytes)); 99 public Unit SerBool(bool val) => _buffer.Push(val ? byte.MaxValue : byte.MinValue); 100 public Result<Unit, Bottom> SerializeBool(bool val) => new(SerBool(val)); 101 public Unit SerByte(byte val) => SerUnsafe(val); 102 public Result<Unit, Bottom> SerializeByte(byte val) => new(SerByte(val)); 103 public Unit SerChar(char val) => SerUnsafe(val); 104 public Result<Unit, Bottom> SerializeChar(char val) => new(SerChar(val)); 105 public Unit SerChars(ReadOnlySpan<char> val) => SerSliceUnsafe(val); 106 public Result<Unit, Bottom> SerializeChars(ReadOnlySpan<char> val) => new(SerChars(val)); 107 public Unit SerDateTime(DateTime val) => SerUnsafe(val); 108 public Result<Unit, Bottom> SerializeDateTime(DateTime val) => new(SerDateTime(val)); 109 public Unit SerDateTimeOffset(DateTimeOffset val) { 110 111 _ = SerDateTime(new DateTime(val.Ticks, DateTimeKind.Unspecified)); 112 return SerTimeSpan(val.Offset); 113 } 114 public Result<Unit, Bottom> SerializeDateTimeOffset(DateTimeOffset val) => new(SerDateTimeOffset(val)); 115 public Unit SerDecimal(decimal val) { 116 117 Span<int> bits = stackalloc int[4]; 118 _ = decimal.GetBits(val, bits); 119 return SerSliceUnsafe<int>(bits); 120 } 121 public Result<Unit, Bottom> SerializeDecimal(decimal val) => new(SerDecimal(val)); 122 public Unit SerDouble(double val) => SerUnsafe(val); 123 public Result<Unit, Bottom> SerializeDouble(double val) => new(SerDouble(val)); 124 public Unit SerFloat(float val) => SerUnsafe(val); 125 public Result<Unit, Bottom> SerializeFloat(float val) => new(SerFloat(val)); 126 public Unit SerGuid(Guid val) => SerUnsafe(val); 127 public Result<Unit, Bottom> SerializeGuid(Guid val) => new(SerGuid(val)); 128 public Unit SerI128(I128 val) => SerUnsafe(val); 129 public Result<Unit, Bottom> SerializeI128(I128 val) => new(SerI128(val)); 130 public Unit SerInt(int val) => SerUnsafe(val); 131 public Result<Unit, Bottom> SerializeInt(int val) => new(SerInt(val)); 132 public Unit SerLong(long val) => SerUnsafe(val); 133 public Result<Unit, Bottom> SerializeLong(long val) => new(SerLong(val)); 134 public Unit SerMaybe<TSome>(Maybe<TSome> val) where TSome: notnull, IBinSerializable { 135 136 if (val.IsNone) { 137 return SerUnsafe(byte.MinValue); 138 } else { 139 _ = SerUnsafe(byte.MaxValue); 140 return val.Unwrap().Ser(ref this); 141 } 142 } 143 public Result<Unit, Bottom> SerializeMaybe<TSome>(Maybe<TSome> val) where TSome : notnull, ISerializable { 144 145 if (val.IsNone) { 146 return new(SerUnsafe(byte.MinValue)); 147 } else { 148 _ = SerUnsafe(byte.MaxValue); 149 return val.Unwrap().Serialize<Serializer, Unit, Bottom>(ref this); 150 } 151 } 152 public Unit SerSbyte(sbyte val) => SerUnsafe(val); 153 public Result<Unit, Bottom> SerializeSbyte(sbyte val) => new(SerSbyte(val)); 154 public Unit SerShort(short val) => SerUnsafe(val); 155 public Result<Unit, Bottom> SerializeShort(short val) => new(SerShort(val)); 156 public Unit SerSliceUnsafe<T>(ReadOnlySpan<T> val) where T: unmanaged { unsafe { fixed (T* ptr = val) { return _buffer.ExtendFromSlice(new(ptr, val.Length * sizeof(T))); } } } 157 public Unit SerTimeSpan(TimeSpan val) => SerUnsafe(val); 158 public Result<Unit, Bottom> SerializeTimeSpan(TimeSpan val) => new(SerTimeSpan(val)); 159 public Unit SerU128(U128 val) => SerUnsafe(val); 160 public Result<Unit, Bottom> SerializeU128(U128 val) => new(SerU128(val)); 161 public Unit SerUint(uint val) => SerUnsafe(val); 162 public Result<Unit, Bottom> SerializeUint(uint val) => new(SerUint(val)); 163 public Unit SerUlong(ulong val) => SerUnsafe(val); 164 public Result<Unit, Bottom> SerializeUlong(ulong val) => new(SerUlong(val)); 165 public Result<Unit, Bottom> SerializeUnit(Unit _) => new(new Unit()); 166 public Unit SerUshort(ushort val) => SerUnsafe(val); 167 public Result<Unit, Bottom> SerializeUshort(ushort val) => new(SerUshort(val)); 168 public override readonly string ToString() => string.Empty; 169 #endregion 170 171 #region Operators 172 #endregion 173 174 #region Types 175 #endregion 176 } 177 #endregion 178 179 #region Namespaces 180 #endregion 181 } 182 #endregion