using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.Json; using JT808.Protocol.Enums; using JT808.Protocol.Extensions; using JT808.Protocol.Formatters; using JT808.Protocol.Interfaces; using JT808.Protocol.Internal; using JT808.Protocol.MessagePack; [assembly: InternalsVisibleTo("JT808.Protocol.DependencyInjection")] namespace JT808.Protocol { /// /// JT808序列化器 /// public class JT808Serializer { internal readonly IMerger merger; private readonly static JT808Package jT808Package = new JT808Package(); private readonly static Type JT808_Header_Package_Type = typeof(JT808HeaderPackage); private readonly static Type JT808_Package_Type = typeof(JT808Package); /// /// 默认实例 /// default instance /// public readonly static JT808Serializer Instance; static JT808Serializer() { Instance = new JT808Serializer(); } /// /// ctor /// /// public JT808Serializer(IJT808Config jT808Config) { if (jT808Config.EnableAutoMerge) merger = new DefaultMerger(); this.jT808Config = jT808Config; } /// /// ctor /// public JT808Serializer() : this(new DefaultGlobalConfig()) { } /// /// 标识 /// public string SerializerId => jT808Config.ConfigId; private readonly IJT808Config jT808Config; /// /// 序列化数据包 /// /// 数据包 /// 协议版本 /// 最低所需缓冲区大小 /// 元数据 public byte[] Serialize(JT808Package package, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); package.Serialize(ref jT808MessagePackWriter, package, jT808Config); return jT808MessagePackWriter.FlushAndGetEncodingArray(); } finally { JT808ArrayPool.Return(buffer); } } /// /// 反序列化 /// /// 元数据 /// 协议版本 /// 最低所需缓冲区大小 /// 数据包 public JT808Package Deserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); return jT808Package.Deserialize(ref jT808MessagePackReader, jT808Config); } finally { JT808ArrayPool.Return(buffer); } } /// /// 序列化 /// /// /// 数据包 /// 协议版本 /// 最低所需缓冲区大小 /// 元数据 public byte[] Serialize(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { var formatter = jT808Config.GetMessagePackFormatter(); JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); return jT808MessagePackWriter.FlushAndGetEncodingArray(); } finally { JT808ArrayPool.Return(buffer); } } /// /// 根据泛型反序列化元数据 /// /// /// 元素书 /// 协议版本 /// 最低所需缓冲区大小 /// 数据包 public T Deserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if (CheckPackageType(typeof(T))) jT808MessagePackReader.Decode(buffer); var formatter = jT808Config.GetMessagePackFormatter(); return formatter.Deserialize(ref jT808MessagePackReader, jT808Config); } finally { JT808ArrayPool.Return(buffer); } } /// /// 验证类型是否为或者 /// /// 需要验证的类型 /// private static bool CheckPackageType(Type type) { return type == JT808_Package_Type || type == JT808_Header_Package_Type; } /// /// 反序列化消息头 /// 用于负载或者分布式的时候,在网关只需要解到头部,根据头部的消息Id进行分发处理,可以防止小部分性能损耗。 /// /// 元数据 /// 协议版本 /// 最低所需缓冲区大小 /// public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); return new JT808HeaderPackage(ref jT808MessagePackReader, jT808Config); } finally { JT808ArrayPool.Return(buffer); } } /// /// 根据类型反序列化 /// /// 元数据 /// 类型 /// 协议版本 /// 最低所需缓冲区大小 /// public object Deserialize(ReadOnlySpan bytes, Type type, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { var formatter = jT808Config.GetMessagePackFormatterByType(type); JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if (CheckPackageType(type)) jT808MessagePackReader.Decode(buffer); return formatter.Deserialize(ref jT808MessagePackReader, jT808Config); } finally { JT808ArrayPool.Return(buffer); } } /// /// 分析元数据至json /// /// 元数据 /// 协议版本 /// json选项 /// 最低所需缓冲区大小 /// public string Analyze(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); jT808Package.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); utf8JsonWriter.Flush(); string value = Encoding.UTF8.GetString(memoryStream.ToArray()); return value; } finally { JT808ArrayPool.Return(buffer); } } /// /// 分析元数据至json /// /// /// 元数据 /// 协议版本 /// json序列化选项 /// 最低所需缓冲区大小 /// public string Analyze(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if (CheckPackageType(typeof(T))) jT808MessagePackReader.Decode(buffer); var analyze = jT808Config.GetAnalyze(); using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteStartObject(); analyze.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteEndObject(); utf8JsonWriter.Flush(); string value = Encoding.UTF8.GetString(memoryStream.ToArray()); return value; } finally { JT808ArrayPool.Return(buffer); } } /// /// 用于分包组合 /// /// 对应消息id /// 组合的数据体 /// 对应版本号 /// 序列化选项 /// 默认65535 /// public string Analyze(ushort msgid, ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 65535) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { if (jT808Config.MsgIdFactory.TryGetValue(msgid, out object msgHandle)) { if (msgHandle is IJT808MessagePackFormatter instance) { using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); utf8JsonWriter.WriteStartObject(); instance.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); utf8JsonWriter.WriteEndObject(); utf8JsonWriter.Flush(); string value = Encoding.UTF8.GetString(memoryStream.ToArray()); return value; } return $"未找到对应的0x{msgid:X2}消息数据体类型"; } return $"未找到对应的0x{msgid:X2}消息数据体类型"; } finally { JT808ArrayPool.Return(buffer); } } /// /// 用于分包组合 /// /// 对应消息id /// 组合的数据体 /// 对应版本号 /// 序列化选项 /// 默认65535 /// public byte[] AnalyzeJsonBuffer(ushort msgid, ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 65535) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { if (jT808Config.MsgIdFactory.TryGetValue(msgid, out object msgHandle)) { if (msgHandle is IJT808MessagePackFormatter instance) { using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); utf8JsonWriter.WriteStartObject(); instance.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); utf8JsonWriter.WriteEndObject(); utf8JsonWriter.Flush(); return memoryStream.ToArray(); } return Encoding.UTF8.GetBytes($"未找到对应的0x{msgid:X2}消息数据体类型"); } return Encoding.UTF8.GetBytes($"未找到对应的0x{msgid:X2}消息数据体类型"); } finally { JT808ArrayPool.Return(buffer); } } /// /// 分析元数据至json /// /// 元数据 /// 协议版本 /// json选项 /// 最低所需缓冲区大小 /// public byte[] AnalyzeJsonBuffer(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); jT808Package.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); utf8JsonWriter.Flush(); return memoryStream.ToArray(); } finally { JT808ArrayPool.Return(buffer); } } /// /// 分析元数据至json /// /// /// 元数据 /// 协议版本 /// json选项 /// 最低所需缓冲区大小 /// public byte[] AnalyzeJsonBuffer(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if (CheckPackageType(typeof(T))) jT808MessagePackReader.Decode(buffer); var analyze = jT808Config.GetAnalyze(); using MemoryStream memoryStream = new MemoryStream(); using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options); if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteStartObject(); analyze.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config); if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteEndObject(); utf8JsonWriter.Flush(); return memoryStream.ToArray(); } finally { JT808ArrayPool.Return(buffer); } } /// /// 外部注册 /// /// /// public JT808Serializer Register(params Assembly[] externalAssemblies) { if (externalAssemblies != null && externalAssemblies.Length > 0) { foreach (var asm in externalAssemblies) { jT808Config.Register(asm); } } return this; } } }