|
1 | 1 |
|
2 | 2 | using System; |
3 | 3 | using System.Buffers; |
| 4 | +using System.Buffers.Binary; |
4 | 5 |
|
5 | 6 | namespace Serde; |
6 | 7 |
|
@@ -83,9 +84,51 @@ public interface ITypeDeserializer : IDisposable |
83 | 84 | /// </summary> |
84 | 85 | (int, string? errorName) TryReadIndexWithName(ISerdeInfo info); |
85 | 86 |
|
| 87 | + /// <summary> |
| 88 | + /// Read a value of type T using the provided deserializer. |
| 89 | + /// </summary> |
86 | 90 | T ReadValue<T>(ISerdeInfo info, int index, IDeserialize<T> deserialize) |
87 | 91 | where T : class?; |
88 | 92 |
|
| 93 | + /// <summary> |
| 94 | + /// Read a value that can be represented as a 32-bit integer. |
| 95 | + /// </summary> |
| 96 | + /// <remarks> |
| 97 | + /// Must be implemented by deserializers to avoid boxing. |
| 98 | + /// |
| 99 | + /// Useful for deserializing structs/enums without boxing. Unlike <see cref="ReadValue{T}"/> , |
| 100 | + /// this method does not require T to be a reference type. And unlike <see cref="ReadU32" /> |
| 101 | + /// there is no requirement that the serialized representation is exactly a 32-bit integer. |
| 102 | + /// </remarks> |
| 103 | + UInt32 ReadValue32(ISerdeInfo info, int index, IDeserialize<UInt32> deserialize) |
| 104 | + => this.ReadBoxedValue(info, index, deserialize); |
| 105 | + |
| 106 | + /// <summary> |
| 107 | + /// Read a value that can be represented as a 64-bit integer. |
| 108 | + /// </summary> |
| 109 | + /// <remarks> |
| 110 | + /// Must be implemented by deserializers to avoid boxing. |
| 111 | + /// |
| 112 | + /// Useful for deserializing structs/enums without boxing. Unlike <see cref="ReadValue{T}"/> , |
| 113 | + /// this method does not require T to be a reference type. And unlike <see cref="ReadU32" /> |
| 114 | + /// there is no requirement that the serialized representation is exactly a 32-bit integer. |
| 115 | + /// </remarks> |
| 116 | + UInt64 ReadValue64(ISerdeInfo info, int index, IDeserialize<UInt64> deserialize) |
| 117 | + => this.ReadBoxedValue(info, index, deserialize); |
| 118 | + |
| 119 | + /// <summary> |
| 120 | + /// Read a value that can be represented as a 128-bit integer. |
| 121 | + /// </summary> |
| 122 | + /// <remarks> |
| 123 | + /// Must be implemented by deserializers to avoid boxing. |
| 124 | + /// |
| 125 | + /// Useful for deserializing structs/enums without boxing. Unlike <see cref="ReadValue{T}"/> , |
| 126 | + /// this method does not require T to be a reference type. And unlike <see cref="ReadU32" /> |
| 127 | + /// there is no requirement that the serialized representation is exactly a 32-bit integer. |
| 128 | + /// </remarks> |
| 129 | + UInt128 ReadValue128(ISerdeInfo info, int index, IDeserialize<UInt128> deserialize) |
| 130 | + => this.ReadBoxedValue(info, index, deserialize); |
| 131 | + |
89 | 132 | void SkipValue(ISerdeInfo info, int index); |
90 | 133 | bool ReadBool(ISerdeInfo info, int index); |
91 | 134 | char ReadChar(ISerdeInfo info, int index); |
@@ -131,9 +174,31 @@ public static T ReadValue<T, TProvider>(this ITypeDeserializer deserializeType, |
131 | 174 | return deserializeType.ReadValue(info, index, TProvider.Instance); |
132 | 175 | } |
133 | 176 |
|
| 177 | + public static T ReadBoxedValue<T>(this ITypeDeserializer deserializeType, ISerdeInfo info, int index, IDeserialize<T> d) |
| 178 | + where T : struct |
| 179 | + { |
| 180 | + return (T)deserializeType.ReadValue(info, index, new BoxProxy.De<T>(d))!; |
| 181 | + } |
| 182 | + |
134 | 183 | public static T ReadBoxedValue<T, TProvider>(this ITypeDeserializer deserializeType, ISerdeInfo info, int index) |
135 | 184 | where TProvider : IDeserializeProvider<T> |
136 | 185 | { |
137 | 186 | return (T)deserializeType.ReadValue(info, index, BoxProxy.De<T, TProvider>.Instance)!; |
138 | 187 | } |
| 188 | + |
| 189 | + public static Guid ReadGuid<TProvider>(this ITypeDeserializer deserializeType, ISerdeInfo info, int index) |
| 190 | + where TProvider : IDeserializeProvider<UInt128> |
| 191 | + { |
| 192 | + var u128 = deserializeType.ReadValue128(info, index, TProvider.Instance); |
| 193 | + Span<byte> bytes = stackalloc byte[16]; |
| 194 | + if (BitConverter.IsLittleEndian) |
| 195 | + { |
| 196 | + BinaryPrimitives.WriteUInt128LittleEndian(bytes, u128); |
| 197 | + } |
| 198 | + else |
| 199 | + { |
| 200 | + BinaryPrimitives.WriteUInt128BigEndian(bytes, u128); |
| 201 | + } |
| 202 | + return new Guid(bytes, !BitConverter.IsLittleEndian); |
| 203 | + } |
139 | 204 | } |
0 commit comments