using System.IO.Compression; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Newtonsoft.Json; /// /// Компрессор для больших списков чисел с плавающей точкой /// public class CompressedFloatListConverter : ValueConverter, string> { public CompressedFloatListConverter() : base( v => Compress(v), v => Decompress(v) ) { } private static string Compress(List list) { if (list is null || list.Count == 0) return ""; byte[] floatBytes = new byte[list.Count * sizeof(float)]; Buffer.BlockCopy(list.ToArray(), 0, floatBytes, 0, floatBytes.Length); using var outputStream = new MemoryStream(); using (var compressionStream = new BrotliStream(outputStream, CompressionLevel.Optimal)) compressionStream.Write(floatBytes, 0, floatBytes.Length); return Convert.ToBase64String(outputStream.ToArray()); } private static List Decompress(string base64String) { if (string.IsNullOrEmpty(base64String)) return new List(); byte[] compressedBytes; float[]? floatArray; try { compressedBytes = Convert.FromBase64String(base64String); } catch (FormatException) { floatArray = JsonConvert.DeserializeObject(base64String); if (floatArray is null) throw; return new List(floatArray); } using var inputStream = new MemoryStream(compressedBytes); using var decompressionStream = new BrotliStream(inputStream, CompressionMode.Decompress); using var outputStream = new MemoryStream(); decompressionStream.CopyTo(outputStream); byte[] decompressedBytes = outputStream.ToArray(); floatArray = new float[decompressedBytes.Length / sizeof(float)]; Buffer.BlockCopy(decompressedBytes, 0, floatArray, 0, decompressedBytes.Length); return new List(floatArray); } }