Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

415 рядки
18 KiB

  1. using System.Reflection;
  2. using System.Runtime.CompilerServices;
  3. using System.Text;
  4. using System.Text.Json;
  5. using JT808.Protocol.Enums;
  6. using JT808.Protocol.Extensions;
  7. using JT808.Protocol.Formatters;
  8. using JT808.Protocol.Interfaces;
  9. using JT808.Protocol.Internal;
  10. using JT808.Protocol.MessagePack;
  11. [assembly: InternalsVisibleTo("JT808.Protocol.DependencyInjection")]
  12. namespace JT808.Protocol
  13. {
  14. /// <summary>
  15. /// JT808序列化器
  16. /// </summary>
  17. public class JT808Serializer
  18. {
  19. internal readonly IMerger merger;
  20. private readonly static JT808Package jT808Package = new JT808Package();
  21. private readonly static Type JT808_Header_Package_Type = typeof(JT808HeaderPackage);
  22. private readonly static Type JT808_Package_Type = typeof(JT808Package);
  23. /// <summary>
  24. /// 默认实例
  25. /// default instance
  26. /// </summary>
  27. public readonly static JT808Serializer Instance;
  28. static JT808Serializer()
  29. {
  30. Instance = new JT808Serializer();
  31. }
  32. /// <summary>
  33. /// ctor
  34. /// </summary>
  35. /// <param name="jT808Config"></param>
  36. public JT808Serializer(IJT808Config jT808Config)
  37. {
  38. if (jT808Config.EnableAutoMerge)
  39. merger = new DefaultMerger();
  40. this.jT808Config = jT808Config;
  41. }
  42. /// <summary>
  43. /// ctor
  44. /// </summary>
  45. public JT808Serializer() : this(new DefaultGlobalConfig()) { }
  46. /// <summary>
  47. /// 标识
  48. /// </summary>
  49. public string SerializerId => jT808Config.ConfigId;
  50. private readonly IJT808Config jT808Config;
  51. /// <summary>
  52. /// 序列化数据包
  53. /// </summary>
  54. /// <param name="package">数据包</param>
  55. /// <param name="version">协议版本</param>
  56. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  57. /// <returns>元数据</returns>
  58. public byte[] Serialize(JT808Package package, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  59. {
  60. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  61. try
  62. {
  63. JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version);
  64. package.Serialize(ref jT808MessagePackWriter, package, jT808Config);
  65. return jT808MessagePackWriter.FlushAndGetEncodingArray();
  66. }
  67. finally
  68. {
  69. JT808ArrayPool.Return(buffer);
  70. }
  71. }
  72. /// <summary>
  73. /// 反序列化
  74. /// </summary>
  75. /// <param name="bytes">元数据</param>
  76. /// <param name="version">协议版本</param>
  77. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  78. /// <returns>数据包</returns>
  79. public JT808Package Deserialize(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  80. {
  81. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  82. try
  83. {
  84. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  85. jT808MessagePackReader.Decode(buffer);
  86. return jT808Package.Deserialize(ref jT808MessagePackReader, jT808Config);
  87. }
  88. finally
  89. {
  90. JT808ArrayPool.Return(buffer);
  91. }
  92. }
  93. /// <summary>
  94. /// 序列化
  95. /// </summary>
  96. /// <typeparam name="T"></typeparam>
  97. /// <param name="obj">数据包</param>
  98. /// <param name="version">协议版本</param>
  99. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  100. /// <returns>元数据</returns>
  101. public byte[] Serialize<T>(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  102. {
  103. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  104. try
  105. {
  106. var formatter = jT808Config.GetMessagePackFormatter<T>();
  107. JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version);
  108. formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config);
  109. return jT808MessagePackWriter.FlushAndGetEncodingArray();
  110. }
  111. finally
  112. {
  113. JT808ArrayPool.Return(buffer);
  114. }
  115. }
  116. /// <summary>
  117. /// 根据泛型反序列化元数据
  118. /// </summary>
  119. /// <typeparam name="T"></typeparam>
  120. /// <param name="bytes">元素书</param>
  121. /// <param name="version">协议版本</param>
  122. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  123. /// <returns>数据包</returns>
  124. public T Deserialize<T>(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  125. {
  126. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  127. try
  128. {
  129. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  130. if (CheckPackageType(typeof(T)))
  131. jT808MessagePackReader.Decode(buffer);
  132. var formatter = jT808Config.GetMessagePackFormatter<T>();
  133. return formatter.Deserialize(ref jT808MessagePackReader, jT808Config);
  134. }
  135. finally
  136. {
  137. JT808ArrayPool.Return(buffer);
  138. }
  139. }
  140. /// <summary>
  141. /// 验证类型是否为<see cref="JT808_Package_Type"/>或者<see cref="JT808_Header_Package_Type"/>
  142. /// </summary>
  143. /// <param name="type">需要验证的类型</param>
  144. /// <returns></returns>
  145. private static bool CheckPackageType(Type type)
  146. {
  147. return type == JT808_Package_Type || type == JT808_Header_Package_Type;
  148. }
  149. /// <summary>
  150. /// 反序列化消息头
  151. /// <para>用于负载或者分布式的时候,在网关只需要解到头部,根据头部的消息Id进行分发处理,可以防止小部分性能损耗。</para>
  152. /// </summary>
  153. /// <param name="bytes">元数据</param>
  154. /// <param name="version">协议版本</param>
  155. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  156. /// <returns></returns>
  157. public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  158. {
  159. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  160. try
  161. {
  162. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  163. jT808MessagePackReader.Decode(buffer);
  164. return new JT808HeaderPackage(ref jT808MessagePackReader, jT808Config);
  165. }
  166. finally
  167. {
  168. JT808ArrayPool.Return(buffer);
  169. }
  170. }
  171. /// <summary>
  172. /// 根据类型反序列化
  173. /// </summary>
  174. /// <param name="bytes">元数据</param>
  175. /// <param name="type">类型</param>
  176. /// <param name="version">协议版本</param>
  177. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  178. /// <returns></returns>
  179. public object Deserialize(ReadOnlySpan<byte> bytes, Type type, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096)
  180. {
  181. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  182. try
  183. {
  184. var formatter = jT808Config.GetMessagePackFormatterByType(type);
  185. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  186. if (CheckPackageType(type))
  187. jT808MessagePackReader.Decode(buffer);
  188. return formatter.Deserialize(ref jT808MessagePackReader, jT808Config);
  189. }
  190. finally
  191. {
  192. JT808ArrayPool.Return(buffer);
  193. }
  194. }
  195. /// <summary>
  196. /// 分析元数据至json
  197. /// </summary>
  198. /// <param name="bytes">元数据</param>
  199. /// <param name="version">协议版本</param>
  200. /// <param name="options">json选项</param>
  201. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  202. /// <returns></returns>
  203. public string Analyze(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096)
  204. {
  205. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  206. try
  207. {
  208. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  209. jT808MessagePackReader.Decode(buffer);
  210. using MemoryStream memoryStream = new MemoryStream();
  211. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  212. jT808Package.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  213. utf8JsonWriter.Flush();
  214. string value = Encoding.UTF8.GetString(memoryStream.ToArray());
  215. return value;
  216. }
  217. finally
  218. {
  219. JT808ArrayPool.Return(buffer);
  220. }
  221. }
  222. /// <summary>
  223. /// 分析元数据至json
  224. /// </summary>
  225. /// <typeparam name="T"></typeparam>
  226. /// <param name="bytes">元数据</param>
  227. /// <param name="version">协议版本</param>
  228. /// <param name="options">json序列化选项</param>
  229. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  230. /// <returns></returns>
  231. public string Analyze<T>(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096)
  232. {
  233. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  234. try
  235. {
  236. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  237. if (CheckPackageType(typeof(T)))
  238. jT808MessagePackReader.Decode(buffer);
  239. var analyze = jT808Config.GetAnalyze<T>();
  240. using MemoryStream memoryStream = new MemoryStream();
  241. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  242. if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteStartObject();
  243. analyze.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  244. if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteEndObject();
  245. utf8JsonWriter.Flush();
  246. string value = Encoding.UTF8.GetString(memoryStream.ToArray());
  247. return value;
  248. }
  249. finally
  250. {
  251. JT808ArrayPool.Return(buffer);
  252. }
  253. }
  254. /// <summary>
  255. /// 用于分包组合
  256. /// </summary>
  257. /// <param name="msgid">对应消息id</param>
  258. /// <param name="bytes">组合的数据体</param>
  259. /// <param name="version">对应版本号</param>
  260. /// <param name="options">序列化选项</param>
  261. /// <param name="minBufferSize">默认65535</param>
  262. /// <returns></returns>
  263. public string Analyze(ushort msgid, ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 65535)
  264. {
  265. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  266. try
  267. {
  268. if (jT808Config.MsgIdFactory.TryGetValue(msgid, out object msgHandle))
  269. {
  270. if (msgHandle is IJT808MessagePackFormatter instance)
  271. {
  272. using MemoryStream memoryStream = new MemoryStream();
  273. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  274. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  275. utf8JsonWriter.WriteStartObject();
  276. instance.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  277. utf8JsonWriter.WriteEndObject();
  278. utf8JsonWriter.Flush();
  279. string value = Encoding.UTF8.GetString(memoryStream.ToArray());
  280. return value;
  281. }
  282. return $"未找到对应的0x{msgid:X2}消息数据体类型";
  283. }
  284. return $"未找到对应的0x{msgid:X2}消息数据体类型";
  285. }
  286. finally
  287. {
  288. JT808ArrayPool.Return(buffer);
  289. }
  290. }
  291. /// <summary>
  292. /// 用于分包组合
  293. /// </summary>
  294. /// <param name="msgid">对应消息id</param>
  295. /// <param name="bytes">组合的数据体</param>
  296. /// <param name="version">对应版本号</param>
  297. /// <param name="options">序列化选项</param>
  298. /// <param name="minBufferSize">默认65535</param>
  299. /// <returns></returns>
  300. public byte[] AnalyzeJsonBuffer(ushort msgid, ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 65535)
  301. {
  302. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  303. try
  304. {
  305. if (jT808Config.MsgIdFactory.TryGetValue(msgid, out object msgHandle))
  306. {
  307. if (msgHandle is IJT808MessagePackFormatter instance)
  308. {
  309. using MemoryStream memoryStream = new MemoryStream();
  310. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  311. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  312. utf8JsonWriter.WriteStartObject();
  313. instance.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  314. utf8JsonWriter.WriteEndObject();
  315. utf8JsonWriter.Flush();
  316. return memoryStream.ToArray();
  317. }
  318. return Encoding.UTF8.GetBytes($"未找到对应的0x{msgid:X2}消息数据体类型");
  319. }
  320. return Encoding.UTF8.GetBytes($"未找到对应的0x{msgid:X2}消息数据体类型");
  321. }
  322. finally
  323. {
  324. JT808ArrayPool.Return(buffer);
  325. }
  326. }
  327. /// <summary>
  328. /// 分析元数据至json
  329. /// </summary>
  330. /// <param name="bytes">元数据</param>
  331. /// <param name="version">协议版本</param>
  332. /// <param name="options">json选项</param>
  333. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  334. /// <returns></returns>
  335. public byte[] AnalyzeJsonBuffer(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096)
  336. {
  337. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  338. try
  339. {
  340. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  341. jT808MessagePackReader.Decode(buffer);
  342. using MemoryStream memoryStream = new MemoryStream();
  343. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  344. jT808Package.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  345. utf8JsonWriter.Flush();
  346. return memoryStream.ToArray();
  347. }
  348. finally
  349. {
  350. JT808ArrayPool.Return(buffer);
  351. }
  352. }
  353. /// <summary>
  354. /// 分析元数据至json
  355. /// </summary>
  356. /// <typeparam name="T"></typeparam>
  357. /// <param name="bytes">元数据</param>
  358. /// <param name="version">协议版本</param>
  359. /// <param name="options">json选项</param>
  360. /// <param name="minBufferSize">最低所需缓冲区大小</param>
  361. /// <returns></returns>
  362. public byte[] AnalyzeJsonBuffer<T>(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, JsonWriterOptions options = default, int minBufferSize = 8096)
  363. {
  364. byte[] buffer = JT808ArrayPool.Rent(minBufferSize);
  365. try
  366. {
  367. JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version);
  368. if (CheckPackageType(typeof(T)))
  369. jT808MessagePackReader.Decode(buffer);
  370. var analyze = jT808Config.GetAnalyze<T>();
  371. using MemoryStream memoryStream = new MemoryStream();
  372. using Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter(memoryStream, options);
  373. if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteStartObject();
  374. analyze.Analyze(ref jT808MessagePackReader, utf8JsonWriter, jT808Config);
  375. if (!CheckPackageType(typeof(T))) utf8JsonWriter.WriteEndObject();
  376. utf8JsonWriter.Flush();
  377. return memoryStream.ToArray();
  378. }
  379. finally
  380. {
  381. JT808ArrayPool.Return(buffer);
  382. }
  383. }
  384. /// <summary>
  385. /// 外部注册
  386. /// </summary>
  387. /// <param name="externalAssemblies"></param>
  388. /// <returns></returns>
  389. public JT808Serializer Register(params Assembly[] externalAssemblies)
  390. {
  391. if (externalAssemblies != null && externalAssemblies.Length > 0)
  392. {
  393. foreach (var asm in externalAssemblies)
  394. {
  395. jT808Config.Register(asm);
  396. }
  397. }
  398. return this;
  399. }
  400. }
  401. }