| /* |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| namespace DotPulsar.Internal.Compression; |
| |
| using DotPulsar.Internal.Abstractions; |
| using System; |
| using System.Buffers; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Reflection; |
| |
| public static class ZlibCompression |
| { |
| public delegate byte[] CompressBuffer(byte[] source); |
| public delegate byte[] UncompressBuffer(byte[] source); |
| |
| public static bool TryLoading(out ICompressorFactory? compressorFactory, out IDecompressorFactory? decompressorFactory) |
| { |
| try |
| { |
| var assembly = Assembly.Load("DotNetZip"); |
| |
| var definedTypes = assembly.DefinedTypes.ToArray(); |
| |
| var ZlibStream = FindZlibStream(definedTypes); |
| |
| var methods = ZlibStream.GetMethods(BindingFlags.Public | BindingFlags.Static); |
| |
| var compressBuffer = FindCompressBuffer(methods); |
| var uncompressBuffer = FindUncompressBuffer(methods); |
| |
| compressorFactory = new CompressorFactory(PulsarApi.CompressionType.Zlib, () => new Compressor(CreateCompressor(compressBuffer))); |
| decompressorFactory = new DecompressorFactory(PulsarApi.CompressionType.Zlib, () => new Decompressor(CreateDecompressor(uncompressBuffer))); |
| return true; |
| } |
| catch |
| { |
| // Ignore |
| } |
| |
| compressorFactory = null; |
| decompressorFactory = null; |
| |
| return false; |
| } |
| |
| private static TypeInfo FindZlibStream(IEnumerable<TypeInfo> types) |
| { |
| const string fullName = "Ionic.Zlib.ZlibStream"; |
| |
| foreach (var type in types) |
| { |
| if (type.FullName is null || !type.FullName.Equals(fullName)) |
| continue; |
| |
| if (type.IsPublic && type.IsClass) |
| return type; |
| |
| break; |
| } |
| |
| throw new Exception($"{fullName} as a public class was not found"); |
| } |
| |
| private static CompressBuffer FindCompressBuffer(MethodInfo[] methods) |
| { |
| const string name = "CompressBuffer"; |
| |
| foreach (var method in methods) |
| { |
| if (method.Name != name || method.ReturnType != typeof(byte[])) |
| continue; |
| |
| var parameters = method.GetParameters(); |
| if (parameters.Length != 1) |
| continue; |
| |
| if (parameters[0].ParameterType != typeof(byte[])) |
| continue; |
| |
| return (CompressBuffer) method.CreateDelegate(typeof(CompressBuffer)); |
| } |
| |
| throw new Exception($"A method with the name '{name}' matching the delegate was not found"); |
| } |
| |
| private static UncompressBuffer FindUncompressBuffer(MethodInfo[] methods) |
| { |
| const string name = "UncompressBuffer"; |
| |
| foreach (var method in methods) |
| { |
| if (method.Name != name || method.ReturnType != typeof(byte[])) |
| continue; |
| |
| var parameters = method.GetParameters(); |
| if (parameters.Length != 1) |
| continue; |
| |
| if (parameters[0].ParameterType != typeof(byte[])) |
| continue; |
| |
| return (UncompressBuffer) method.CreateDelegate(typeof(UncompressBuffer)); |
| } |
| |
| throw new Exception($"A method with the name '{name}' matching the delegate was not found"); |
| } |
| |
| private static Func<ReadOnlySequence<byte>, int, ReadOnlySequence<byte>> CreateDecompressor(UncompressBuffer decompress) |
| => (source, size) => new ReadOnlySequence<byte>(decompress(source.ToArray())); |
| |
| private static Func<ReadOnlySequence<byte>, ReadOnlySequence<byte>> CreateCompressor(CompressBuffer compress) |
| => (source) => new ReadOnlySequence<byte>(compress(source.ToArray())); |
| } |