BrotliDecompressor.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using BestHTTP.Extensions;
  3. using BestHTTP.PlatformSupport.Memory;
  4. namespace BestHTTP.Decompression
  5. {
  6. public sealed class BrotliDecompressor : IDecompressor
  7. {
  8. #if ((NET_STANDARD_2_1 || UNITY_2021_2_OR_NEWER) && (!(ENABLE_MONO && UNITY_ANDROID) || (!UNITY_WEBGL || UNITY_EDITOR))) && BESTHTTP_ENABLE_BROTLI
  9. private BufferPoolMemoryStream decompressorInputStream;
  10. private BufferPoolMemoryStream decompressorOutputStream;
  11. private System.IO.Compression.BrotliStream decompressorStream;
  12. #endif
  13. private int MinLengthToDecompress = 256;
  14. public static bool IsSupported()
  15. {
  16. // Not enabled under android with the mono runtime
  17. #if ((NET_STANDARD_2_1 || UNITY_2021_2_OR_NEWER) && (!(ENABLE_MONO && UNITY_ANDROID) || (!UNITY_WEBGL || UNITY_EDITOR))) && BESTHTTP_ENABLE_BROTLI
  18. return true;
  19. #else
  20. return false;
  21. #endif
  22. }
  23. public BrotliDecompressor(int minLengthToDecompress)
  24. {
  25. this.MinLengthToDecompress = minLengthToDecompress;
  26. }
  27. public DecompressedData Decompress(byte[] data, int offset, int count, bool forceDecompress = false, bool dataCanBeLarger = false)
  28. {
  29. #if ((NET_STANDARD_2_1 || UNITY_2021_2_OR_NEWER) && (!(ENABLE_MONO && UNITY_ANDROID) || (!UNITY_WEBGL || UNITY_EDITOR))) && BESTHTTP_ENABLE_BROTLI
  30. if (decompressorInputStream == null)
  31. decompressorInputStream = new BufferPoolMemoryStream(count);
  32. if (data != null)
  33. decompressorInputStream.Write(data, offset, count);
  34. if (!forceDecompress && decompressorInputStream.Length < MinLengthToDecompress)
  35. return new DecompressedData(null, 0);
  36. decompressorInputStream.Position = 0;
  37. if (decompressorStream == null)
  38. {
  39. decompressorStream = new System.IO.Compression.BrotliStream(decompressorInputStream,
  40. System.IO.Compression.CompressionMode.Decompress,
  41. true);
  42. }
  43. if (decompressorOutputStream == null)
  44. decompressorOutputStream = new BufferPoolMemoryStream();
  45. decompressorOutputStream.SetLength(0);
  46. byte[] copyBuffer = BufferPool.Get(1024, true);
  47. int readCount;
  48. int sumReadCount = 0;
  49. while ((readCount = decompressorStream.Read(copyBuffer, 0, copyBuffer.Length)) != 0)
  50. {
  51. decompressorOutputStream.Write(copyBuffer, 0, readCount);
  52. sumReadCount += readCount;
  53. }
  54. BufferPool.Release(copyBuffer);
  55. // If no read is done (returned with any data) don't zero out the input stream, as it would delete any not yet used data.
  56. if (sumReadCount > 0)
  57. decompressorStream.SetLength(0);
  58. byte[] result = decompressorOutputStream.ToArray(dataCanBeLarger);
  59. return new DecompressedData(result, dataCanBeLarger ? (int)decompressorOutputStream.Length : result.Length);
  60. #else
  61. return default(DecompressedData);
  62. #endif
  63. }
  64. public void Dispose()
  65. {
  66. #if ((NET_STANDARD_2_1 || UNITY_2021_2_OR_NEWER) && (!(ENABLE_MONO && UNITY_ANDROID) || (!UNITY_WEBGL || UNITY_EDITOR))) && BESTHTTP_ENABLE_BROTLI
  67. this.decompressorStream?.Dispose();
  68. this.decompressorStream = null;
  69. #endif
  70. }
  71. }
  72. }