using System; using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace ARMeilleure.Translation.PTC { static class PtcFormatter { #region "Deserialize" [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Dictionary DeserializeDictionary(Stream stream, Func valueFunc) where TKey : struct { Dictionary dictionary = new(); int count = DeserializeStructure(stream); for (int i = 0; i < count; i++) { TKey key = DeserializeStructure(stream); TValue value = valueFunc(stream); dictionary.Add(key, value); } return dictionary; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List DeserializeList(Stream stream) where T : struct { List list = new(); int count = DeserializeStructure(stream); for (int i = 0; i < count; i++) { T item = DeserializeStructure(stream); list.Add(item); } return list; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T DeserializeStructure(Stream stream) where T : struct { T structure = default(T); Span spanT = MemoryMarshal.CreateSpan(ref structure, 1); int bytesCount = stream.Read(MemoryMarshal.AsBytes(spanT)); if (bytesCount != Unsafe.SizeOf()) { throw new EndOfStreamException(); } return structure; } #endregion #region "GetSerializeSize" [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetSerializeSizeDictionary(Dictionary dictionary, Func valueFunc) where TKey : struct { int size = 0; size += Unsafe.SizeOf(); foreach ((_, TValue value) in dictionary) { size += Unsafe.SizeOf(); size += valueFunc(value); } return size; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetSerializeSizeList(List list) where T : struct { int size = 0; size += Unsafe.SizeOf(); size += list.Count * Unsafe.SizeOf(); return size; } #endregion #region "Serialize" [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SerializeDictionary(Stream stream, Dictionary dictionary, Action valueAction) where TKey : struct { SerializeStructure(stream, dictionary.Count); foreach ((TKey key, TValue value) in dictionary) { SerializeStructure(stream, key); valueAction(stream, value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SerializeList(Stream stream, List list) where T : struct { SerializeStructure(stream, list.Count); foreach (T item in list) { SerializeStructure(stream, item); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SerializeStructure(Stream stream, T structure) where T : struct { Span spanT = MemoryMarshal.CreateSpan(ref structure, 1); stream.Write(MemoryMarshal.AsBytes(spanT)); } #endregion #region "Extension methods" [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReadFrom(this List list, Stream stream) where T : struct { int count = DeserializeStructure(stream); for (int i = 0; i < count; i++) { int itemLength = DeserializeStructure(stream); T[] item = new T[itemLength]; int bytesCount = stream.Read(MemoryMarshal.AsBytes(item.AsSpan())); if (bytesCount != itemLength) { throw new EndOfStreamException(); } list.Add(item); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Length(this List list) where T : struct { long size = 0L; size += Unsafe.SizeOf(); foreach (T[] item in list) { size += Unsafe.SizeOf(); size += item.Length; } return size; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteTo(this List list, Stream stream) where T : struct { SerializeStructure(stream, list.Count); foreach (T[] item in list) { SerializeStructure(stream, item.Length); stream.Write(MemoryMarshal.AsBytes(item.AsSpan())); } } #endregion } }