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;
}
}
}