diff --git a/Brotli.Core/.gitignore b/Brotli.Core/.gitignore
new file mode 100644
index 0000000..33a2c50
--- /dev/null
+++ b/Brotli.Core/.gitignore
@@ -0,0 +1,2 @@
+!runtimes/x64
+!runtimes/x86
\ No newline at end of file
diff --git a/Brotli.Core/Brotli.Core.csproj b/Brotli.Core/Brotli.Core.csproj
new file mode 100644
index 0000000..2eb5ea0
--- /dev/null
+++ b/Brotli.Core/Brotli.Core.csproj
@@ -0,0 +1,46 @@
+
+
+
+ net45;netstandard2.0
+ 2.1.1.0
+ true
+ Brotli.NET
+ Jinjun Xie
+ Jinjun Xie
+ Copyright Jinjun Xie 2016
+
+ https://github.com/XieJJ99/brotli.net
+ Brotli Compress Decompress .NET Standard Stream
+ Add async stream support, update brotli core to v1.0.9
+ Supported on dotnet standard2(Windows/Linux/OSX), provide similar interface to Google offical API.Quality and window control is supported.
+The library use the native runtime and its performance should be better than System.IO.Compress.BrotliStream.
+For more document,please visit https://github.com/XieJJ99/brotli.net.
+ MIT
+ 2.1.1.0
+
+
+
+
+ runtimes
+ true
+
+
+
+
+
+
+
+
+
+
+ build
+ true
+
+
+
+
+
+
diff --git a/Brotli.Core/Enum/BrotliDecoderParameter.cs b/Brotli.Core/Enum/BrotliDecoderParameter.cs
new file mode 100644
index 0000000..a830651
--- /dev/null
+++ b/Brotli.Core/Enum/BrotliDecoderParameter.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Brotli
+{
+ public enum BrotliDecoderParameter:int
+ {
+ DisableRingBufferReallocation=0,
+ LargeWindow=1,
+ }
+}
diff --git a/Brotli.Core/Enum/BrotliDecoderResult.cs b/Brotli.Core/Enum/BrotliDecoderResult.cs
new file mode 100644
index 0000000..80ecd0d
--- /dev/null
+++ b/Brotli.Core/Enum/BrotliDecoderResult.cs
@@ -0,0 +1,22 @@
+namespace Brotli
+{
+ public enum BrotliDecoderResult:int
+ {
+ ///
+ /// Decoding error, e.g. corrupt input or memory allocation problem
+ ///
+ Error = 0,
+ ///
+ /// Decoding successfully completed
+ ///
+ Success = 1,
+ ///
+ /// Partially done; should be called again with more input
+ ///
+ NeedsMoreInput = 2,
+ ///
+ /// Partially done; should be called again with more output
+ ///
+ NeedsMoreOutput = 3
+ };
+}
diff --git a/Brotli.Core/Enum/BrotliEncoderOperation.cs b/Brotli.Core/Enum/BrotliEncoderOperation.cs
new file mode 100644
index 0000000..4cc17c4
--- /dev/null
+++ b/Brotli.Core/Enum/BrotliEncoderOperation.cs
@@ -0,0 +1,26 @@
+namespace Brotli
+{
+ public enum BrotliEncoderOperation : int
+ {
+ Process = 0,
+ ///
+ /// Request output stream to flush. Performed when input stream is depleted
+ /// and there is enough space in output stream.
+ ///
+ Flush = 1,
+ ///
+ /// Request output stream to finish. Performed when input stream is depleted
+ /// and there is enough space in output stream.
+ ///
+ Finish = 2,
+
+ ///
+ /// Emits metadata block to stream. Stream is soft-flushed before metadata
+ /// block is emitted. CAUTION: when operation is started, length of the input
+ /// buffer is interpreted as length of a metadata block; changing operation,
+ /// expanding or truncating input before metadata block is completely emitted
+ /// will cause an error; metadata block must not be greater than 16MiB.
+ ///
+ EmitMetadata = 3
+ };
+}
diff --git a/Brotli.Core/Enum/BrotliEncoderParameter.cs b/Brotli.Core/Enum/BrotliEncoderParameter.cs
new file mode 100644
index 0000000..d1e471e
--- /dev/null
+++ b/Brotli.Core/Enum/BrotliEncoderParameter.cs
@@ -0,0 +1,22 @@
+namespace Brotli
+{
+ public enum BrotliEncoderParameter : int
+ {
+ Mode = 0,
+ ///
+ /// Controls the compression-speed vs compression-density tradeoffs. The higher
+ /// the quality, the slower the compression. Range is 0 to 11.
+ ///
+ Quality = 1,
+ ///
+ /// Base 2 logarithm of the sliding window size. Range is 10 to 24.
+ ///
+ LGWin = 2,
+
+ ///
+ /// Base 2 logarithm of the maximum input block size. Range is 16 to 24.
+ /// If set to 0, the value will be set based on the quality.
+ ///
+ LGBlock = 3
+ };
+}
diff --git a/Brotli.Core/Exception/BrotliDecodeException.cs b/Brotli.Core/Exception/BrotliDecodeException.cs
new file mode 100644
index 0000000..286f170
--- /dev/null
+++ b/Brotli.Core/Exception/BrotliDecodeException.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Brotli
+{
+ public class BrotliDecodeException : BrotliException
+ {
+ public int Code { get; set; }
+ public String ErrorText { get; set; }
+
+
+ public BrotliDecodeException(int code, String errorText) : base() {
+ Code = code;
+ ErrorText = errorText;
+ }
+
+ public BrotliDecodeException(String message, int code, String errorText) : base(message) {
+ Code = code;
+ ErrorText = errorText;
+ }
+ public BrotliDecodeException(String message, Exception innerException, int code, String errorText) : base(message, innerException) {
+ Code = code;
+ ErrorText = errorText;
+ }
+ }
+}
diff --git a/Brotli.Core/Exception/BrotliException.cs b/Brotli.Core/Exception/BrotliException.cs
new file mode 100644
index 0000000..f232772
--- /dev/null
+++ b/Brotli.Core/Exception/BrotliException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Brotli
+{
+ public class BrotliException:Exception
+ {
+ public BrotliException() : base() { }
+ public BrotliException(String message) : base(message) { }
+ public BrotliException(String message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/Brotli.Core/Extensions/BrotliExtensions.cs b/Brotli.Core/Extensions/BrotliExtensions.cs
new file mode 100644
index 0000000..d2a7d05
--- /dev/null
+++ b/Brotli.Core/Extensions/BrotliExtensions.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Brotli
+{
+ public static class BrotliExtensions
+ {
+ ///
+ /// Compress the data with brotli
+ ///
+ /// inputData
+ /// quality,0~11
+ /// compress window(10~24)
+ /// compressed bytes
+ public static byte[] CompressToBrotli(this byte[] rawData, uint quality = 5, uint window = 22)
+ {
+ if (rawData == null) throw new ArgumentNullException(nameof(rawData));
+ using (var msInput = new System.IO.MemoryStream(rawData))
+ {
+ return CompressToBrotli(msInput, quality, window);
+ }
+ }
+
+ ///
+ /// Compress the data with brotli
+ ///
+ /// input stream
+ /// quality,0~11
+ /// compress window(10~24)
+ /// compressed bytes
+ public static byte[] CompressToBrotli(this System.IO.Stream inStream, uint quality = 5, uint window = 22)
+ {
+ using (System.IO.MemoryStream msOutput = new System.IO.MemoryStream())
+ {
+ CompressToBrotli(inStream, msOutput, quality, window);
+ var output = msOutput.ToArray();
+ return output;
+ }
+ }
+
+ ///
+ /// Compress the data with brotli
+ ///
+ /// input stream
+ /// dest output stream
+ /// quality,0~11
+ /// compress window(10~24)
+ public static void CompressToBrotli(this System.IO.Stream inStream, System.IO.Stream destStream, uint quality = 5, uint window = 22)
+ {
+ using (BrotliStream bs = new BrotliStream(destStream, System.IO.Compression.CompressionMode.Compress))
+ {
+ bs.SetQuality(quality);
+ bs.SetWindow(window);
+ inStream.CopyTo(bs);
+ bs.Close();
+ }
+ }
+
+ public static byte[] DecompressFromBrotli(this byte[] rawData)
+ {
+ if (rawData == null) throw new ArgumentNullException(nameof(rawData));
+ using (var msInput = new System.IO.MemoryStream(rawData))
+ {
+ return DecompressFromBrotli(msInput);
+ }
+ }
+
+ public static byte[] DecompressFromBrotli(this System.IO.Stream inStream)
+ {
+ using (System.IO.MemoryStream msOutput = new System.IO.MemoryStream())
+ {
+ DecompressFromBrotli(inStream, msOutput);
+ var output = msOutput.ToArray();
+ return output;
+ }
+ }
+
+ public static void DecompressFromBrotli(this System.IO.Stream inStream,System.IO.Stream destStream)
+ {
+ using (BrotliStream bs = new BrotliStream(inStream, System.IO.Compression.CompressionMode.Decompress))
+ {
+ bs.CopyTo(destStream);
+ destStream.Flush();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Brotli.Core/Implement/AsyncHelper.cs b/Brotli.Core/Implement/AsyncHelper.cs
new file mode 100644
index 0000000..eda8427
--- /dev/null
+++ b/Brotli.Core/Implement/AsyncHelper.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Brotli
+{
+ internal class AsyncHelper
+ {
+ private static readonly TaskFactory _myTaskFactory = new
+ TaskFactory(CancellationToken.None, TaskCreationOptions.None,
+ TaskContinuationOptions.None, TaskScheduler.Default);
+
+ internal static void RunSync(Func func, bool await = false)
+ {
+ CultureInfo cultureUi = CultureInfo.CurrentUICulture;
+ CultureInfo culture = CultureInfo.CurrentCulture;
+ _myTaskFactory.StartNew(delegate
+ {
+ Thread.CurrentThread.CurrentCulture = culture;
+ Thread.CurrentThread.CurrentUICulture = cultureUi;
+ return func();
+ }).Unwrap().ConfigureAwait(await).GetAwaiter().GetResult();
+ }
+
+ // Microsoft.AspNet.Identity.AsyncHelper
+ internal static TResult RunSync(Func> func, bool await = false)
+ {
+ CultureInfo cultureUi = CultureInfo.CurrentUICulture;
+ CultureInfo culture = CultureInfo.CurrentCulture;
+ return _myTaskFactory.StartNew>(delegate
+ {
+ Thread.CurrentThread.CurrentCulture = culture;
+ Thread.CurrentThread.CurrentUICulture = cultureUi;
+ return func();
+ }).Unwrap().ConfigureAwait(await).GetAwaiter().GetResult();
+ }
+
+
+
+
+ internal static TResult RunSync(Func