mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-06-13 14:38:43 +00:00
removed unsafe
This commit is contained in:
@@ -51,6 +51,7 @@ public static class Codec
|
||||
DataDeserializer.BooleanFalseParserAsync,
|
||||
DataDeserializer.BooleanTrueParserAsync,
|
||||
DataDeserializer.NotModifiedParserAsync,
|
||||
DataDeserializer.InfinityParserAsync,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.UInt8ParserAsync,
|
||||
@@ -115,6 +116,7 @@ public static class Codec
|
||||
DataDeserializer.BooleanFalseParser,
|
||||
DataDeserializer.BooleanTrueParser,
|
||||
DataDeserializer.NotModifiedParser,
|
||||
DataDeserializer.InfinityParser,
|
||||
},
|
||||
new SyncParser[]{
|
||||
DataDeserializer.UInt8Parser,
|
||||
@@ -376,6 +378,13 @@ public static class Codec
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Synchronously parses a single value from its IIP wire representation.
|
||||
/// </summary>
|
||||
/// <param name="data">Buffer containing the encoded value.</param>
|
||||
/// <param name="offset">Zero-based offset of the value within <paramref name="data"/>.</param>
|
||||
/// <param name="warehouse">Warehouse used to resolve typed structures (records, enums, ...).</param>
|
||||
/// <returns>A tuple of (number of bytes consumed, decoded value).</returns>
|
||||
public static (uint, object) ParseSync(byte[] data, uint offset, Warehouse warehouse)
|
||||
{
|
||||
var tdu = ParsedTdu.ParseSync(data, offset, (uint)data.Length, warehouse);
|
||||
@@ -612,7 +621,14 @@ public static class Codec
|
||||
/// <param name="connection">EpConnection is required to check locality.</param>
|
||||
/// <param name="prependType">If True, prepend the DataType at the beginning of the output.</param>
|
||||
/// <returns>Array of bytes in the network byte order.</returns>
|
||||
public static byte[] Compose(object valueOrSource, Warehouse warehouse, EpConnection connection)//, bool prependType = true)
|
||||
/// <summary>
|
||||
/// Encodes a value to its self-describing IIP wire representation (a type-prefixed TDU).
|
||||
/// </summary>
|
||||
/// <param name="valueOrSource">The value to encode (may be null, which encodes as the Null TDU).</param>
|
||||
/// <param name="warehouse">Warehouse used to resolve type definitions for typed structures.</param>
|
||||
/// <param name="connection">Connection context, required when the value references remote resources; may be null for plain data.</param>
|
||||
/// <returns>The encoded bytes, including the leading type identifier.</returns>
|
||||
public static byte[] Compose(object valueOrSource, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var tdu = ComposeInternal(valueOrSource, warehouse, connection);
|
||||
return tdu.Composed;
|
||||
|
||||
@@ -108,11 +108,10 @@ public static class DC // Data Converter
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw ex;
|
||||
return null;
|
||||
// Preserve the original stack trace with a bare rethrow.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,19 @@ public static class DataDeserializer
|
||||
return NotModified.Default;
|
||||
}
|
||||
|
||||
// The Infinity token carries no payload: the serializer collapses every NaN and
|
||||
// +/- Infinity onto it (see DataSerializer.Float32/Float64Composer). Decoding it to
|
||||
// a single canonical double keeps the (lossy) round trip from throwing.
|
||||
public static object InfinityParserAsync(ParsedTdu tdu, EpConnection connection, uint[] requestSequence)
|
||||
{
|
||||
return double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static object InfinityParser(ParsedTdu tdu, Warehouse warehouse)
|
||||
{
|
||||
return double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static object UInt8ParserAsync(ParsedTdu tdu, EpConnection connection, uint[] requestSequence)
|
||||
{
|
||||
return tdu.Data[tdu.PayloadOffset];
|
||||
@@ -1345,7 +1358,6 @@ public static class DataDeserializer
|
||||
var subTypes = subTrus.Select(x => x.RuntimeType).ToArray();
|
||||
|
||||
ParsedTdu current;
|
||||
ParsedTdu? previous = null;
|
||||
|
||||
var offset = tdu.PayloadOffset;
|
||||
var length = tdu.PayloadLength;
|
||||
@@ -1477,7 +1489,6 @@ public static class DataDeserializer
|
||||
var types = subTrus.Select(x => x.RuntimeType).ToArray();
|
||||
|
||||
ParsedTdu current;
|
||||
ParsedTdu? previous = null;
|
||||
|
||||
var offset = tdu.PayloadOffset;
|
||||
var length = tdu.PayloadLength;
|
||||
|
||||
@@ -17,7 +17,7 @@ public static class DataSerializer
|
||||
{
|
||||
public delegate byte[] Serializer(object value);
|
||||
|
||||
public static unsafe Tdu Int32Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu Int32Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (int)value;
|
||||
|
||||
@@ -29,22 +29,19 @@ public static class DataSerializer
|
||||
{
|
||||
// Fits in 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((short*)ptr) = (short)v;
|
||||
|
||||
BinaryPrimitives.WriteInt16LittleEndian(rt, (short)v);
|
||||
return new Tdu(TduIdentifier.Int16, rt, 2, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use full 4 bytes
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((int*)ptr) = v;
|
||||
BinaryPrimitives.WriteInt32LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.Int32, rt, 4, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Tdu UInt32Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu UInt32Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (uint)value;
|
||||
|
||||
@@ -57,23 +54,19 @@ public static class DataSerializer
|
||||
{
|
||||
// Fits in 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ushort*)ptr) = (ushort)v;
|
||||
|
||||
BinaryPrimitives.WriteUInt16LittleEndian(rt, (ushort)v);
|
||||
return new Tdu(TduIdentifier.UInt16, rt, 2, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use full 4 bytes
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.UInt32, rt, 4, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Tdu Int16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu Int16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (short)value;
|
||||
|
||||
@@ -86,14 +79,12 @@ public static class DataSerializer
|
||||
{
|
||||
// Use full 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((short*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteInt16LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.Int16, rt, 2, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Tdu UInt16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu UInt16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (ushort)value;
|
||||
|
||||
@@ -106,9 +97,7 @@ public static class DataSerializer
|
||||
{
|
||||
// Use full 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ushort*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteUInt16LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.UInt16, rt, 2, null, null);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +200,7 @@ public static class DataSerializer
|
||||
return new Tdu(TduIdentifier.Float64, rt, 8, null, null);
|
||||
}
|
||||
}
|
||||
public static unsafe Tdu Int64Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu Int64Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (long)value;
|
||||
|
||||
@@ -224,32 +213,26 @@ public static class DataSerializer
|
||||
{
|
||||
// Fits in 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((short*)ptr) = (short)v;
|
||||
|
||||
BinaryPrimitives.WriteInt16LittleEndian(rt, (short)v);
|
||||
return new Tdu(TduIdentifier.Int16, rt, 2, null, null);
|
||||
}
|
||||
else if (v >= int.MinValue && v <= int.MaxValue)
|
||||
{
|
||||
// Fits in 4 bytes
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((int*)ptr) = (int)v;
|
||||
|
||||
BinaryPrimitives.WriteInt32LittleEndian(rt, (int)v);
|
||||
return new Tdu(TduIdentifier.Int32, rt, 4, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use full 8 bytes
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteInt64LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.Int64, rt, 8, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Tdu UInt64Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu UInt64Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (ulong)value;
|
||||
|
||||
@@ -262,39 +245,31 @@ public static class DataSerializer
|
||||
{
|
||||
// Fits in 2 bytes
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ushort*)ptr) = (ushort)v;
|
||||
|
||||
BinaryPrimitives.WriteUInt16LittleEndian(rt, (ushort)v);
|
||||
return new Tdu(TduIdentifier.UInt16, rt, 2, null, null);
|
||||
}
|
||||
else if (v <= uint.MaxValue)
|
||||
{
|
||||
// Fits in 4 bytes
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = (uint)v;
|
||||
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(rt, (uint)v);
|
||||
return new Tdu(TduIdentifier.UInt32, rt, 4, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use full 8 bytes
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ulong*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.UInt64, rt, 8, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static unsafe Tdu DateTimeComposer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu DateTimeComposer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = ((DateTime)value).ToUniversalTime().Ticks;
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteInt64LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.DateTime, rt, 8, null, null);
|
||||
}
|
||||
|
||||
@@ -362,7 +337,7 @@ public static class DataSerializer
|
||||
double d = (double)v;
|
||||
if ((decimal)d == v)
|
||||
{
|
||||
var rt = new byte[4];
|
||||
var rt = new byte[8];
|
||||
|
||||
fixed (byte* ptr = rt)
|
||||
*((double*)ptr) = d;
|
||||
@@ -436,15 +411,12 @@ public static class DataSerializer
|
||||
new byte[] { (byte)(char)value }, 1, null, null);
|
||||
}
|
||||
|
||||
public static unsafe Tdu Char16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
public static Tdu Char16Composer(object value, Warehouse warehouse, EpConnection connection)
|
||||
{
|
||||
var v = (char)value;
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((char*)ptr) = v;
|
||||
|
||||
BinaryPrimitives.WriteUInt16LittleEndian(rt, v);
|
||||
return new Tdu(TduIdentifier.Char16, rt, 2, null, null);
|
||||
|
||||
}
|
||||
|
||||
public static Tdu BoolComposer(object value, Warehouse warehouse, EpConnection connection)
|
||||
@@ -733,7 +705,9 @@ public static class DataSerializer
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var rt = new List<byte>();
|
||||
// Pre-size the buffer from the element count (when known) to avoid repeated
|
||||
// List<byte> reallocations as items are appended. 4 bytes/element is a rough hint.
|
||||
var rt = new List<byte>(value is ICollection collection ? collection.Count * 4 : 16);
|
||||
|
||||
Tdu? previous = null;
|
||||
|
||||
@@ -934,7 +908,7 @@ public static class DataSerializer
|
||||
var trus = fields.Select(x => Tru.FromType(x.FieldType, warehouse)).ToArray();
|
||||
|
||||
|
||||
var rt = new List<byte>();
|
||||
var rt = new List<byte>(fields.Length * 4);
|
||||
|
||||
for (var i = 0; i < fields.Length; i++)
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@ public struct Tdu
|
||||
}
|
||||
|
||||
public Tdu(TduIdentifier identifier,
|
||||
byte[] data, ulong length, Tru metadata, EpConnection connection)
|
||||
byte[]? data, ulong length, Tru? metadata, EpConnection? connection)
|
||||
{
|
||||
Identifier = identifier;
|
||||
//Index = (byte)identifier & 0x7;
|
||||
|
||||
@@ -138,6 +138,14 @@ namespace Esiur.Data
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
// Equality is defined by Match, which always requires a matching Identifier
|
||||
// (composites additionally compare sub-types). Hashing on Identifier therefore
|
||||
// keeps equal Trus in the same bucket and honours the Equals/GetHashCode contract.
|
||||
return (int)Identifier;
|
||||
}
|
||||
|
||||
public abstract void SetNotNull(List<byte> flags);
|
||||
|
||||
public abstract void SetNotNull(byte flag);
|
||||
@@ -299,7 +307,32 @@ namespace Esiur.Data
|
||||
//private static Dictionary<Type, Tru> cache = new Dictionary<Type, Tru>();
|
||||
//private static object cacheLook = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Builds the type-representation unit (Tru) describing how a CLR type maps onto the
|
||||
/// wire, recursing into element/key/value/field types for collections, maps and tuples.
|
||||
/// Results are memoized per warehouse since this is reflection-heavy and hot during
|
||||
/// serialization; returned Tru instances are immutable and safe to share.
|
||||
/// </summary>
|
||||
public static Tru? FromType(Type type, Warehouse warehouse)
|
||||
{
|
||||
// null maps to Void and cannot be a dictionary key, so compute it directly.
|
||||
if (type == null)
|
||||
return FromTypeCore(null, warehouse);
|
||||
|
||||
if (warehouse.TypeRepresentationCache.TryGetValue(type, out var cached))
|
||||
return cached;
|
||||
|
||||
var tru = FromTypeCore(type, warehouse);
|
||||
|
||||
// Cache only fully-built results. Unrecognized types return null (or throw),
|
||||
// which we leave uncached so a later type registration can still resolve them.
|
||||
if (tru != null)
|
||||
warehouse.TypeRepresentationCache[type] = tru;
|
||||
|
||||
return tru;
|
||||
}
|
||||
|
||||
static Tru? FromTypeCore(Type? type, Warehouse warehouse)
|
||||
{
|
||||
if (type == null)
|
||||
return new TruPrimitive(TruIdentifier.Void, true, typeof(void));
|
||||
@@ -714,7 +747,7 @@ namespace Esiur.Data
|
||||
offset += pr.Size;
|
||||
}
|
||||
|
||||
Type runtimeType = null;
|
||||
Type? runtimeType = null;
|
||||
|
||||
if (identifier == TruIdentifier.TypedList)
|
||||
{
|
||||
@@ -852,7 +885,7 @@ namespace Esiur.Data
|
||||
offset += pr.Size;
|
||||
}
|
||||
|
||||
Type runtimeType = null;
|
||||
Type? runtimeType = null;
|
||||
|
||||
if (identifier == TruIdentifier.TypedList)
|
||||
{
|
||||
|
||||
@@ -11,11 +11,9 @@ namespace Esiur.Data
|
||||
{
|
||||
public Tru[] SubTypes;
|
||||
|
||||
Type _runtimeType;
|
||||
|
||||
public override Type RuntimeType { get; protected set; }
|
||||
|
||||
public TruComposite(TruIdentifier identifier, bool nullable, Tru[] subTypes, Type type)
|
||||
public TruComposite(TruIdentifier identifier, bool nullable, Tru[] subTypes, Type? type)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Nullable = nullable;
|
||||
|
||||
@@ -88,7 +88,7 @@ public class ArgumentDef
|
||||
}
|
||||
else
|
||||
{
|
||||
var exp = Codec.Compose(Annotations, null, null);
|
||||
var exp = Codec.Compose(Annotations, connection.Instance.Warehouse, connection);
|
||||
|
||||
return new BinaryList()
|
||||
.AddUInt8((byte)(0x2 | (Optional ? 1 : 0)))
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ConstantDef : MemberDef
|
||||
|
||||
if (Annotations != null)
|
||||
{
|
||||
var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
|
||||
var exp = Codec.Compose(Annotations, connection.Instance.Warehouse, connection);// DC.ToBytes(Annotation);
|
||||
hdr |= 0x70;
|
||||
return new BinaryList()
|
||||
.AddUInt8(hdr)
|
||||
|
||||
@@ -82,7 +82,7 @@ public class EventDef : MemberDef
|
||||
|
||||
if (Annotations != null)
|
||||
{
|
||||
var exp = Codec.Compose(Annotations, null, null); //( DC.ToBytes(Annotation);
|
||||
var exp = Codec.Compose(Annotations, connection.Instance.Warehouse, connection); //( DC.ToBytes(Annotation);
|
||||
hdr |= 0x50;
|
||||
return new BinaryList()
|
||||
.AddUInt8(hdr)
|
||||
|
||||
@@ -110,7 +110,7 @@ public class FunctionDef : MemberDef
|
||||
|
||||
if (Annotations != null)
|
||||
{
|
||||
var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
|
||||
var exp = Codec.Compose(Annotations, connection.Instance.Warehouse , connection);// DC.ToBytes(Annotation);
|
||||
bl.AddUInt8Array(exp);
|
||||
bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0)));
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ public class LocalTypeDef:TypeDef
|
||||
//foreach (var ann in Annotations)
|
||||
// Annotations.Add(ann.Key, ann.Value);
|
||||
|
||||
var classAnnotationBytes = Codec.Compose(Annotations, null, null);
|
||||
var classAnnotationBytes = Codec.Compose(Annotations, connection.Instance.Warehouse, connection);
|
||||
|
||||
b.AddUInt8Array(classAnnotationBytes);
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ public class PropertyDef : MemberDef
|
||||
//}
|
||||
if (Annotations != null)
|
||||
{
|
||||
var rexp = Codec.Compose(Annotations, null, null);
|
||||
var rexp = Codec.Compose(Annotations, connection.Instance.Warehouse, connection);
|
||||
return new BinaryList()
|
||||
.AddUInt8((byte)(0x28 | pv))
|
||||
.AddUInt8((byte)name.Length)
|
||||
|
||||
Reference in New Issue
Block a user