diff --git a/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs b/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs
new file mode 100644
index 000000000000..5907901f844e
--- /dev/null
+++ b/external/corefx-bugfix/src/Common/src/Microsoft/Win32/SafeHandles/SafeBrotliHandle.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ internal sealed class SafeBrotliEncoderHandle : SafeHandle
+ {
+ public SafeBrotliEncoderHandle() : base(IntPtr.Zero, true) { }
+
+ protected override bool ReleaseHandle()
+ {
+ Interop.Brotli.BrotliEncoderDestroyInstance(handle);
+ return true;
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+ }
+
+ internal sealed class SafeBrotliDecoderHandle : SafeHandle
+ {
+ public SafeBrotliDecoderHandle() : base(IntPtr.Zero, true) { }
+
+ protected override bool ReleaseHandle()
+ {
+ Interop.Brotli.BrotliDecoderDestroyInstance(handle);
+ return true;
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+ }
+}
diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c
index 779749bd83d8..40a42a4b5891 100644
--- a/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c
+++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/dec/decode.c
@@ -74,7 +74,7 @@ BROTLI_BOOL BrotliDecoderSetParameter(
}
}
-DLLEXPORT BrotliDecoderState* BrotliDecoderCreateInstance(
+DLLEXPORT BrotliDecoderState* MonoBrotliDecoderCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
BrotliDecoderState* state = 0;
if (!alloc_func && !free_func) {
@@ -99,7 +99,7 @@ DLLEXPORT BrotliDecoderState* BrotliDecoderCreateInstance(
}
/* Deinitializes and frees BrotliDecoderState instance. */
-DLLEXPORT void BrotliDecoderDestroyInstance(BrotliDecoderState* state) {
+DLLEXPORT void MonoBrotliDecoderDestroyInstance(BrotliDecoderState* state) {
if (!state) {
return;
} else {
@@ -2032,7 +2032,7 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
return ProcessCommandsInternal(1, s);
}
-DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress(
+DLLEXPORT BrotliDecoderResult MonoBrotliDecoderDecompress(
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
uint8_t* decoded_buffer) {
BrotliDecoderState s;
@@ -2045,7 +2045,7 @@ DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress(
if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {
return BROTLI_DECODER_RESULT_ERROR;
}
- result = BrotliDecoderDecompressStream(
+ result = MonoBrotliDecoderDecompressStream(
&s, &available_in, &next_in, &available_out, &next_out, &total_out);
*decoded_size = total_out;
BrotliDecoderStateCleanup(&s);
@@ -2066,7 +2066,7 @@ DLLEXPORT BrotliDecoderResult BrotliDecoderDecompress(
buffer ahead of time
- when result is "success" decoder MUST return all unused data back to input
buffer; this is possible because the invariant is held on enter */
-DLLEXPORT BrotliDecoderResult BrotliDecoderDecompressStream(
+DLLEXPORT BrotliDecoderResult MonoBrotliDecoderDecompressStream(
BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,
size_t* available_out, uint8_t** next_out, size_t* total_out) {
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
@@ -2565,7 +2565,7 @@ const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {
*size = requested_out - available_out;
} else {
/* ... or stream is broken. Normally this should be caught by
- BrotliDecoderDecompressStream, this is just a safeguard. */
+ MonoBrotliDecoderDecompressStream, this is just a safeguard. */
if ((int)status < 0) SaveErrorCode(s, status);
*size = 0;
result = 0;
@@ -2578,7 +2578,7 @@ BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) {
BrotliGetAvailableBits(&s->br) != 0);
}
-DLLEXPORT BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) {
+DLLEXPORT BROTLI_BOOL MonoBrotliDecoderIsFinished(const BrotliDecoderState* s) {
return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) &&
!BrotliDecoderHasMoreOutput(s);
}
diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c
index dac29a0e8a10..38b15a8d8220 100644
--- a/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c
+++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/enc/encode.c
@@ -143,7 +143,7 @@ static size_t RemainingInputBlockSize(BrotliEncoderState* s) {
return block_size - (size_t)delta;
}
-DLLEXPORT BROTLI_BOOL BrotliEncoderSetParameter(
+DLLEXPORT BROTLI_BOOL MonoBrotliEncoderSetParameter(
BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) {
/* Changing parameters on the fly is not implemented yet. */
if (state->is_initialized_) return BROTLI_FALSE;
@@ -794,7 +794,7 @@ static void BrotliEncoderInitState(BrotliEncoderState* s) {
memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
}
-DLLEXPORT BrotliEncoderState* BrotliEncoderCreateInstance(
+DLLEXPORT BrotliEncoderState* MonoBrotliEncoderCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
BrotliEncoderState* state = 0;
if (!alloc_func && !free_func) {
@@ -828,7 +828,7 @@ static void BrotliEncoderCleanupState(BrotliEncoderState* s) {
}
/* Deinitializes and frees BrotliEncoderState instance. */
-DLLEXPORT void BrotliEncoderDestroyInstance(BrotliEncoderState* state) {
+DLLEXPORT void MonoBrotliEncoderDestroyInstance(BrotliEncoderState* state) {
if (!state) {
return;
} else {
@@ -1468,7 +1468,7 @@ static size_t MakeUncompressedStream(
return result;
}
-DLLEXPORT BROTLI_BOOL BrotliEncoderCompress(
+DLLEXPORT BROTLI_BOOL MonoBrotliEncoderCompress(
int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
const uint8_t* input_buffer, size_t* encoded_size,
uint8_t* encoded_buffer) {
@@ -1499,7 +1499,7 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompress(
return BROTLI_TRUE;
}
- s = BrotliEncoderCreateInstance(0, 0, 0);
+ s = MonoBrotliEncoderCreateInstance(0, 0, 0);
if (!s) {
return BROTLI_FALSE;
} else {
@@ -1509,18 +1509,18 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompress(
uint8_t* next_out = encoded_buffer;
size_t total_out = 0;
BROTLI_BOOL result = BROTLI_FALSE;
- BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
- BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);
- BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);
if (lgwin > BROTLI_MAX_WINDOW_BITS) {
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);
}
- result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,
+ result = MonoBrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,
&available_in, &next_in, &available_out, &next_out, &total_out);
if (!BrotliEncoderIsFinished(s)) result = 0;
*encoded_size = total_out;
- BrotliEncoderDestroyInstance(s);
+ MonoBrotliEncoderDestroyInstance(s);
if (!result || (max_out_size && *encoded_size > max_out_size)) {
goto fallback;
}
@@ -1801,7 +1801,7 @@ static void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) {
}
}
-DLLEXPORT BROTLI_BOOL BrotliEncoderCompressStream(
+DLLEXPORT BROTLI_BOOL MonoBrotliEncoderCompressStream(
BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,
const uint8_t** next_in, size_t* available_out,uint8_t** next_out,
size_t* total_out) {
@@ -1892,10 +1892,10 @@ DLLEXPORT BROTLI_BOOL BrotliEncoderCompressStream(
BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) {
return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED &&
- !BrotliEncoderHasMoreOutput(s));
+ !MonoBrotliEncoderHasMoreOutput(s));
}
-DLLEXPORT BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) {
+DLLEXPORT BROTLI_BOOL MonoBrotliEncoderHasMoreOutput(BrotliEncoderState* s) {
return TO_BROTLI_BOOL(s->available_out_ != 0);
}
diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h
index 0f5c8f9d1117..dcd393dcf378 100644
--- a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h
+++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/decode.h
@@ -22,14 +22,14 @@ extern "C" {
/**
* Opaque structure that holds decoder state.
*
- * Allocated and initialized with ::BrotliDecoderCreateInstance.
- * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance.
+ * Allocated and initialized with ::MonoBrotliDecoderCreateInstance.
+ * Cleaned up and deallocated with ::MonoBrotliDecoderDestroyInstance.
*/
typedef struct BrotliDecoderStateStruct BrotliDecoderState;
/**
- * Result type for ::BrotliDecoderDecompress and
- * ::BrotliDecoderDecompressStream functions.
+ * Result type for ::MonoBrotliDecoderDecompress and
+ * ::MonoBrotliDecoderDecompressStream functions.
*/
typedef enum {
/** Decoding error, e.g. corrupted input or memory allocation problem. */
@@ -158,7 +158,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(
* Creates an instance of ::BrotliDecoderState and initializes it.
*
* The instance can be used once for decoding and should then be destroyed with
- * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding
+ * ::MonoBrotliDecoderDestroyInstance, it cannot be reused for a new decoding
* session.
*
* @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
@@ -172,7 +172,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(
* @returns @c 0 if instance can not be allocated or initialized
* @returns pointer to initialized ::BrotliDecoderState otherwise
*/
-BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance(
+BROTLI_DEC_API BrotliDecoderState* MonoBrotliDecoderCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
/**
@@ -180,7 +180,7 @@ BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance(
*
* @param state decoder instance to be cleaned up and deallocated
*/
-BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state);
+BROTLI_DEC_API void MonoBrotliDecoderDestroyInstance(BrotliDecoderState* state);
/**
* Performs one-shot memory-to-memory decompression.
@@ -199,7 +199,7 @@ BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state);
* allocation failed, or @p decoded_buffer is not large enough;
* @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise
*/
-BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress(
+BROTLI_DEC_API BrotliDecoderResult MonoBrotliDecoderDecompress(
size_t encoded_size,
const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
size_t* decoded_size,
@@ -243,7 +243,7 @@ BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress(
* @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more
* input might be consumed and no more output will be produced
*/
-BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream(
+BROTLI_DEC_API BrotliDecoderResult MonoBrotliDecoderDecompressStream(
BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in,
size_t* available_out, uint8_t** next_out, size_t* total_out);
@@ -261,7 +261,7 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput(
* Acquires pointer to internal output buffer.
*
* This method is used to make language bindings easier and more efficient:
- * -# push data to ::BrotliDecoderDecompressStream,
+ * -# push data to ::MonoBrotliDecoderDecompressStream,
* until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported
* -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific
* entity
@@ -308,13 +308,13 @@ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state);
* the input and produced all of the output
* @returns ::BROTLI_FALSE otherwise
*/
-BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished(
+BROTLI_DEC_API BROTLI_BOOL MonoBrotliDecoderIsFinished(
const BrotliDecoderState* state);
/**
* Acquires a detailed error code.
*
- * Should be used only after ::BrotliDecoderDecompressStream returns
+ * Should be used only after ::MonoBrotliDecoderDecompressStream returns
* ::BROTLI_DECODER_RESULT_ERROR.
*
* See also ::BrotliDecoderErrorString
diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h
index b2774cb63162..98ed9edcb54b 100644
--- a/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h
+++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/include/brotli/encode.h
@@ -77,7 +77,7 @@ typedef enum BrotliEncoderOperation {
* Actual flush is performed when input stream is depleted and there is enough
* space in output stream. This means that client should repeat
* ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and
- * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
+ * ::MonoBrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
* via ::BrotliEncoderTakeOutput, then operation should be repeated after
* output buffer is drained.
*
@@ -94,7 +94,7 @@ typedef enum BrotliEncoderOperation {
* Actual finalization is performed when input stream is depleted and there is
* enough space in output stream. This means that client should repeat
* ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and
- * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
+ * ::MonoBrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
* via ::BrotliEncoderTakeOutput, then operation should be repeated after
* output buffer is drained.
*
@@ -130,7 +130,7 @@ typedef enum BrotliEncoderOperation {
BROTLI_OPERATION_EMIT_METADATA = 3
} BrotliEncoderOperation;
-/** Options to be used with ::BrotliEncoderSetParameter. */
+/** Options to be used with ::MonoBrotliEncoderSetParameter. */
typedef enum BrotliEncoderParameter {
/**
* Tune encoder for specific input.
@@ -177,7 +177,7 @@ typedef enum BrotliEncoderParameter {
*/
BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4,
/**
- * Estimated total input size for all ::BrotliEncoderCompressStream calls.
+ * Estimated total input size for all ::MonoBrotliEncoderCompressStream calls.
*
* The default value is 0, which means that the total input size is unknown.
*/
@@ -223,8 +223,8 @@ typedef enum BrotliEncoderParameter {
/**
* Opaque structure that holds encoder state.
*
- * Allocated and initialized with ::BrotliEncoderCreateInstance.
- * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance.
+ * Allocated and initialized with ::MonoBrotliEncoderCreateInstance.
+ * Cleaned up and deallocated with ::MonoBrotliEncoderDestroyInstance.
*/
typedef struct BrotliEncoderStateStruct BrotliEncoderState;
@@ -242,7 +242,7 @@ typedef struct BrotliEncoderStateStruct BrotliEncoderState;
* @warning invalid values might be accepted in case they would not break
* encoding process.
*/
-BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(
+BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderSetParameter(
BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value);
/**
@@ -259,7 +259,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(
* @returns @c 0 if instance can not be allocated or initialized
* @returns pointer to initialized ::BrotliEncoderState otherwise
*/
-BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(
+BROTLI_ENC_API BrotliEncoderState* MonoBrotliEncoderCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
/**
@@ -267,13 +267,13 @@ BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(
*
* @param state decoder instance to be cleaned up and deallocated
*/
-BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state);
+BROTLI_ENC_API void MonoBrotliEncoderDestroyInstance(BrotliEncoderState* state);
/**
* Calculates the output size bound for the given @p input_size.
*
* @warning Result is only valid if quality is at least @c 2 and, in
- * case ::BrotliEncoderCompressStream was used, no flushes
+ * case ::MonoBrotliEncoderCompressStream was used, no flushes
* (::BROTLI_OPERATION_FLUSH) were performed.
*
* @param input_size size of projected input
@@ -309,7 +309,7 @@ BROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size);
* @returns ::BROTLI_FALSE if output buffer is too small
* @returns ::BROTLI_TRUE otherwise
*/
-BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(
+BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderCompress(
int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],
size_t* encoded_size,
@@ -348,17 +348,17 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(
* completing the current output block, so it could be fully decoded by stream
* decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH.
* Under some circumstances (e.g. lack of output stream capacity) this operation
- * would require several calls to ::BrotliEncoderCompressStream. The method must
+ * would require several calls to ::MonoBrotliEncoderCompressStream. The method must
* be called again until both input stream is depleted and encoder has no more
- * output (see ::BrotliEncoderHasMoreOutput) after the method is called.
+ * output (see ::MonoBrotliEncoderHasMoreOutput) after the method is called.
*
* Finishing the stream means encoding of all input passed to encoder and
* adding specific "final" marks, so stream decoder could determine that stream
* is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH.
* Under some circumstances (e.g. lack of output stream capacity) this operation
- * would require several calls to ::BrotliEncoderCompressStream. The method must
+ * would require several calls to ::MonoBrotliEncoderCompressStream. The method must
* be called again until both input stream is depleted and encoder has no more
- * output (see ::BrotliEncoderHasMoreOutput) after the method is called.
+ * output (see ::MonoBrotliEncoderHasMoreOutput) after the method is called.
*
* @warning When flushing and finishing, @p op should not change until operation
* is complete; input stream should not be swapped, reduced or
@@ -377,7 +377,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(
* @returns ::BROTLI_FALSE if there was an error
* @returns ::BROTLI_TRUE otherwise
*/
-BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream(
+BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderCompressStream(
BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in,
const uint8_t** next_in, size_t* available_out, uint8_t** next_out,
size_t* total_out);
@@ -399,15 +399,15 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state);
* @returns ::BROTLI_TRUE, if encoder has some unconsumed output
* @returns ::BROTLI_FALSE otherwise
*/
-BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(
+BROTLI_ENC_API BROTLI_BOOL MonoBrotliEncoderHasMoreOutput(
BrotliEncoderState* state);
/**
* Acquires pointer to internal output buffer.
*
* This method is used to make language bindings easier and more efficient:
- * -# push data to ::BrotliEncoderCompressStream,
- * until ::BrotliEncoderHasMoreOutput returns BROTL_TRUE
+ * -# push data to ::MonoBrotliEncoderCompressStream,
+ * until ::MonoBrotliEncoderHasMoreOutput returns BROTL_TRUE
* -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific
* entity
*
diff --git a/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c b/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c
index 7c678d3d8fa5..99f133010726 100644
--- a/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c
+++ b/external/corefx-bugfix/src/Native/AnyOS/brotli/tools/brotli.c
@@ -909,7 +909,7 @@ static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) {
return BROTLI_FALSE;
}
- result = BrotliDecoderDecompressStream(s, &context->available_in,
+ result = MonoBrotliDecoderDecompressStream(s, &context->available_in,
&context->next_in, &context->available_out, &context->next_out, 0);
}
}
@@ -917,7 +917,7 @@ static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) {
static BROTLI_BOOL DecompressFiles(Context* context) {
while (NextFile(context)) {
BROTLI_BOOL is_ok = BROTLI_TRUE;
- BrotliDecoderState* s = BrotliDecoderCreateInstance(NULL, NULL, NULL);
+ BrotliDecoderState* s = MonoBrotliDecoderCreateInstance(NULL, NULL, NULL);
if (!s) {
fprintf(stderr, "out of memory\n");
return BROTLI_FALSE;
@@ -933,7 +933,7 @@ static BROTLI_BOOL DecompressFiles(Context* context) {
is_ok = BROTLI_FALSE;
}
if (is_ok) is_ok = DecompressFile(context, s);
- BrotliDecoderDestroyInstance(s);
+ MonoBrotliDecoderDestroyInstance(s);
if (!CloseFiles(context, is_ok)) is_ok = BROTLI_FALSE;
if (!is_ok) return BROTLI_FALSE;
}
@@ -949,7 +949,7 @@ static BROTLI_BOOL CompressFile(Context* context, BrotliEncoderState* s) {
is_eof = !HasMoreInput(context);
}
- if (!BrotliEncoderCompressStream(s,
+ if (!MonoBrotliEncoderCompressStream(s,
is_eof ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
&context->available_in, &context->next_in,
&context->available_out, &context->next_out, NULL)) {
@@ -978,20 +978,20 @@ static BROTLI_BOOL CompressFile(Context* context, BrotliEncoderState* s) {
static BROTLI_BOOL CompressFiles(Context* context) {
while (NextFile(context)) {
BROTLI_BOOL is_ok = BROTLI_TRUE;
- BrotliEncoderState* s = BrotliEncoderCreateInstance(NULL, NULL, NULL);
+ BrotliEncoderState* s = MonoBrotliEncoderCreateInstance(NULL, NULL, NULL);
if (!s) {
fprintf(stderr, "out of memory\n");
return BROTLI_FALSE;
}
- BrotliEncoderSetParameter(s,
+ MonoBrotliEncoderSetParameter(s,
BROTLI_PARAM_QUALITY, (uint32_t)context->quality);
if (context->lgwin > 0) {
/* Specified by user. */
/* Do not enable "large-window" extension, if not required. */
if (context->lgwin > BROTLI_MAX_WINDOW_BITS) {
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, 1u);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, 1u);
}
- BrotliEncoderSetParameter(s,
+ MonoBrotliEncoderSetParameter(s,
BROTLI_PARAM_LGWIN, (uint32_t)context->lgwin);
} else {
/* 0, or not specified by user; could be chosen by compressor. */
@@ -1005,12 +1005,12 @@ static BROTLI_BOOL CompressFiles(Context* context) {
if (lgwin == BROTLI_MAX_WINDOW_BITS) break;
}
}
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, lgwin);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, lgwin);
}
if (context->input_file_length > 0) {
uint32_t size_hint = context->input_file_length < (1 << 30) ?
(uint32_t)context->input_file_length : (1u << 30);
- BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, size_hint);
+ MonoBrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, size_hint);
}
is_ok = OpenFiles(context);
if (is_ok && !context->current_output_path &&
@@ -1019,7 +1019,7 @@ static BROTLI_BOOL CompressFiles(Context* context) {
is_ok = BROTLI_FALSE;
}
if (is_ok) is_ok = CompressFile(context, s);
- BrotliEncoderDestroyInstance(s);
+ MonoBrotliEncoderDestroyInstance(s);
if (!CloseFiles(context, is_ok)) is_ok = BROTLI_FALSE;
if (!is_ok) return BROTLI_FALSE;
}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln b/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln
new file mode 100644
index 000000000000..6f2cf7407668
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/System.IO.Compression.Brotli.sln
@@ -0,0 +1,60 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli.Tests", "tests\System.IO.Compression.Brotli.Tests.csproj", "{BC2E1649-291D-412E-9529-EDDA94FA7AD6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5471BFE8-8071-466F-838E-5ADAA779E742} = {5471BFE8-8071-466F-838E-5ADAA779E742}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli.Performance.Tests", "tests\Performance\System.IO.Compression.Brotli.Performance.Tests.csproj", "{1341F8C8-637A-49A1-BE0F-13867A634929}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5471BFE8-8071-466F-838E-5ADAA779E742} = {5471BFE8-8071-466F-838E-5ADAA779E742}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli", "src\System.IO.Compression.Brotli.csproj", "{5471BFE8-8071-466F-838E-5ADAA779E742}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA} = {4ADD9456-A929-4254-B8A2-16FC628ABFDA}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Compression.Brotli", "ref\System.IO.Compression.Brotli.csproj", "{4ADD9456-A929-4254-B8A2-16FC628ABFDA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1A2F9F4A-A032-433E-B914-ADD5992BB178}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E107E9C1-E893-4E87-987E-04EF0DCEAEFD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{2E666815-2EDB-464B-9DF6-380BF4789AD4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU
+ {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
+ {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
+ {BC2E1649-291D-412E-9529-EDDA94FA7AD6}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU
+ {1341F8C8-637A-49A1-BE0F-13867A634929}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU
+ {1341F8C8-637A-49A1-BE0F-13867A634929}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
+ {1341F8C8-637A-49A1-BE0F-13867A634929}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
+ {1341F8C8-637A-49A1-BE0F-13867A634929}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU
+ {5471BFE8-8071-466F-838E-5ADAA779E742}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU
+ {5471BFE8-8071-466F-838E-5ADAA779E742}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
+ {5471BFE8-8071-466F-838E-5ADAA779E742}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
+ {5471BFE8-8071-466F-838E-5ADAA779E742}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {BC2E1649-291D-412E-9529-EDDA94FA7AD6} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
+ {1341F8C8-637A-49A1-BE0F-13867A634929} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
+ {5471BFE8-8071-466F-838E-5ADAA779E742} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA} = {2E666815-2EDB-464B-9DF6-380BF4789AD4}
+ EndGlobalSection
+EndGlobal
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props
new file mode 100644
index 000000000000..4d0d97a320ee
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/dir.props
@@ -0,0 +1,10 @@
+
+
+
+
+ 4.2.1.0
+ ECMA
+ true
+ true
+
+
\ No newline at end of file
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props
new file mode 100644
index 000000000000..2845c11c541d
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/Configurations.props
@@ -0,0 +1,8 @@
+
+
+
+
+ netcoreapp;
+
+
+
\ No newline at end of file
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs
new file mode 100644
index 000000000000..dd1990703efa
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
+namespace System.IO.Compression
+{
+ public partial struct BrotliDecoder : System.IDisposable
+ {
+ public System.Buffers.OperationStatus Decompress(System.ReadOnlySpan source, System.Span destination, out int bytesConsumed, out int bytesWritten) { bytesConsumed = default(int); bytesWritten = default(int); throw null; }
+ public static bool TryDecompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; }
+ public void Dispose() { }
+ }
+ public partial struct BrotliEncoder : System.IDisposable
+ {
+ public BrotliEncoder(int quality, int window) { }
+ public System.Buffers.OperationStatus Compress(System.ReadOnlySpan source, System.Span destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) { bytesConsumed = default(int); bytesWritten = default(int); throw null; }
+ public System.Buffers.OperationStatus Flush(System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; }
+ public void Dispose() { }
+ public static bool TryCompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { bytesWritten = default(int); throw null; }
+ public static bool TryCompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten, int quality, int window) { bytesWritten = default(int); throw null; }
+ public static int GetMaxCompressedLength(int inputSize) { throw null; }
+ }
+ public sealed partial class BrotliStream : System.IO.Stream
+ {
+ public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionLevel compressionLevel) { }
+ public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionLevel compressionLevel, bool leaveOpen) { }
+ public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionMode mode) { }
+ public BrotliStream(System.IO.Stream stream, System.IO.Compression.CompressionMode mode, bool leaveOpen) { }
+ public System.IO.Stream BaseStream { get { throw null; } }
+ public override bool CanRead { get { throw null; } }
+ public override bool CanSeek { get { throw null; } }
+ public override bool CanWrite { get { throw null; } }
+ public override long Length { get { throw null; } }
+ public override long Position { get { throw null; } set { } }
+ protected override void Dispose(bool disposing) { }
+ public override void Flush() { }
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
+ public override int EndRead(IAsyncResult asyncResult) { throw null; }
+ public override int Read(byte[] buffer, int offset, int count) { throw null; }
+ public override System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; }
+ public override void SetLength(long value) { }
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
+ public override void EndWrite(IAsyncResult asyncResult) { }
+ public override void Write(byte[] buffer, int offset, int count) { }
+ public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj
new file mode 100644
index 000000000000..13f4ca5a7038
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/ref/System.IO.Compression.Brotli.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+ {4ADD9456-A929-4254-B8A2-16FC628ABFDA}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props
new file mode 100644
index 000000000000..17d3231f8e68
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Configurations.props
@@ -0,0 +1,9 @@
+
+
+
+
+ netcoreapp-Unix;
+ netcoreapp-Windows_NT;
+
+
+
\ No newline at end of file
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs
new file mode 100644
index 000000000000..fd34431d3bd5
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Decoder.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+using size_t = System.IntPtr;
+
+internal static partial class Interop
+{
+ internal static partial class Brotli
+ {
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderCreateInstance")]
+#endif
+ internal static extern SafeBrotliDecoderHandle BrotliDecoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDecompressStream")]
+#endif
+ internal static extern unsafe int BrotliDecoderDecompressStream(
+ SafeBrotliDecoderHandle state, ref size_t availableIn, byte** nextIn,
+ ref size_t availableOut, byte** nextOut, out size_t totalOut);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDecompress")]
+#endif
+ internal static extern unsafe bool BrotliDecoderDecompress(size_t availableInput, byte* inBytes, ref size_t availableOutput, byte* outBytes);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderDestroyInstance")]
+#endif
+ internal static extern void BrotliDecoderDestroyInstance(IntPtr state);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliDecoderIsFinished")]
+#endif
+ internal static extern bool BrotliDecoderIsFinished(SafeBrotliDecoderHandle state);
+ }
+}
+
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs
new file mode 100644
index 000000000000..5fbfcbbff30a
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Interop/Interop.Brotli.Encoder.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.IO.Compression;
+using Microsoft.Win32.SafeHandles;
+using size_t = System.IntPtr;
+
+internal static partial class Interop
+{
+ internal static partial class Brotli
+ {
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCreateInstance")]
+#endif
+ internal static extern SafeBrotliEncoderHandle BrotliEncoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderSetParameter")]
+#endif
+ internal static extern bool BrotliEncoderSetParameter(SafeBrotliEncoderHandle state, BrotliEncoderParameter parameter, UInt32 value);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCompressStream")]
+#endif
+ internal static extern unsafe bool BrotliEncoderCompressStream(
+ SafeBrotliEncoderHandle state, BrotliEncoderOperation op, ref size_t availableIn,
+ byte** nextIn, ref size_t availableOut, byte** nextOut, out size_t totalOut);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderHasMoreOutput")]
+#endif
+ internal static extern bool BrotliEncoderHasMoreOutput(SafeBrotliEncoderHandle state);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderDestroyInstance")]
+#endif
+ internal static extern void BrotliEncoderDestroyInstance(IntPtr state);
+
+#if UNITY_WIN_PLATFORM || UNITY_AOT
+ [DllImport(Libraries.CompressionNative)]
+#else
+ [DllImport(Libraries.CompressionNative, CharSet = CharSet.Unicode, EntryPoint = "MonoBrotliEncoderCompress")]
+#endif
+ internal static extern unsafe bool BrotliEncoderCompress(int quality, int window, int v, size_t availableInput, byte* inBytes, ref size_t availableOutput, byte* outBytes);
+ }
+}
+
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata
new file mode 100644
index 000000000000..f86667937a6f
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/PinvokeAnalyzerExceptionList.analyzerdata
@@ -0,0 +1,23 @@
+
+clrcompression.dll!BrotliDecoderCreateInstance
+clrcompression.dll!BrotliDecoderDecompress
+clrcompression.dll!BrotliDecoderDecompressStream
+clrcompression.dll!BrotliDecoderDestroyInstance
+clrcompression.dll!BrotliDecoderErrorString
+clrcompression.dll!BrotliDecoderGetErrorCode
+clrcompression.dll!BrotliDecoderHasMoreOutput
+clrcompression.dll!BrotliDecoderIsFinished
+clrcompression.dll!BrotliDecoderIsUsed
+clrcompression.dll!BrotliDecoderSetParameter
+clrcompression.dll!BrotliDecoderTakeOutput
+clrcompression.dll!BrotliDecoderVersion
+clrcompression.dll!BrotliEncoderCompress
+clrcompression.dll!BrotliEncoderCompressStream
+clrcompression.dll!BrotliEncoderCreateInstance
+clrcompression.dll!BrotliEncoderDestroyInstance
+clrcompression.dll!BrotliEncoderHasMoreOutput
+clrcompression.dll!BrotliEncoderIsFinished
+clrcompression.dll!BrotliEncoderMaxCompressedSize
+clrcompression.dll!BrotliEncoderSetParameter
+clrcompression.dll!BrotliEncoderTakeOutput
+clrcompression.dll!BrotliEncoderVersion
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx
new file mode 100644
index 000000000000..0e95b1fa9e3f
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/Resources/Strings.resx
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ Stream does not support reading.
+
+
+ Stream does not support writing.
+
+
+ Enum value was out of legal range.
+
+
+ Can not access a closed Stream.
+
+
+ Positive number required.
+
+
+ Offset plus count is larger than the length of target array.
+
+
+ Only one asynchronous reader or writer is allowed time at one time.
+
+
+
+ Failed to create BrotliEncoder instance
+
+
+ Can not access a closed Encoder.
+
+
+ Provided BrotliEncoder Quality of {0} is not between the minimum value of {1} and the maximum value of {2}
+
+
+ Provided BrotliEncoder Window of {0} is not between the minimum value of {1} and the maximum value of {2}
+
+
+ The BrotliEncoder {0} can not be changed at current encoder state.
+
+
+
+ Failed to create BrotliDecoder instance
+
+
+ Decoder threw unexpected error: {0}
+
+
+ Can not access a closed Decoder.
+
+
+
+ Can not perform Read operations on a BrotliStream constructed with CompressionMode.Compress.
+
+
+ Encoder ran into invalid data.
+
+
+
+ Can not perform Write operations on a BrotliStream constructed with CompressionMode.Decompress.
+
+
+ Decoder ran into invalid data.
+
+
+ BrotliStream.BaseStream returned more bytes than requested in Read.
+
+
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj
new file mode 100644
index 000000000000..2555fb0ca1a2
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ System.IO.Compression.Brotli
+ Library
+ {5471BFE8-8071-466F-838E-5ADAA779E742}
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Common\System\Threading\Tasks\TaskToApm.cs
+
+
+ Common\Microsoft\Win32\SafeHandles\SafeBrotliHandle.cs
+
+
+
+
+
+ Common\Interop\Windows\Interop.Libraries.cs
+
+
+
+
+
+ Common\Interop\Unix\Interop.Libraries.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs
new file mode 100644
index 000000000000..eae7912210c1
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliStream.cs
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace System.IO.Compression
+{
+ public sealed partial class BrotliStream : Stream
+ {
+ private const int DefaultInternalBufferSize = (1 << 16) - 16; //65520;
+ private Stream _stream;
+ private readonly byte[] _buffer;
+ private readonly bool _leaveOpen;
+ private readonly CompressionMode _mode;
+
+ public BrotliStream(Stream stream, CompressionMode mode) : this(stream, mode, leaveOpen: false) { }
+ public BrotliStream(Stream stream, CompressionMode mode, bool leaveOpen)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ if (!stream.CanWrite)
+ throw new ArgumentException(SR.Stream_FalseCanWrite, nameof(stream));
+ break;
+ case CompressionMode.Decompress:
+ if (!stream.CanRead)
+ throw new ArgumentException(SR.Stream_FalseCanRead, nameof(stream));
+ break;
+ default:
+ throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(mode));
+ }
+
+ _mode = mode;
+ _stream = stream;
+ _leaveOpen = leaveOpen;
+ _buffer = new byte[DefaultInternalBufferSize];
+ }
+
+ private void EnsureNotDisposed()
+ {
+ if (_stream == null)
+ throw new ObjectDisposedException("stream", SR.ObjectDisposed_StreamClosed);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ try
+ {
+ if (disposing && _stream != null)
+ {
+ if (_mode == CompressionMode.Compress)
+ {
+ WriteCore(ReadOnlySpan.Empty, isFinalBlock: true);
+ }
+
+ if (!_leaveOpen)
+ {
+ _stream.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ _stream = null;
+ _encoder.Dispose();
+ _decoder.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+
+ private static void ValidateParameters(byte[] array, int offset, int count)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedPosNum);
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedPosNum);
+
+ if (array.Length - offset < count)
+ throw new ArgumentException(SR.InvalidArgumentOffsetCount);
+ }
+
+ public Stream BaseStream => _stream;
+ public override bool CanRead => _mode == CompressionMode.Decompress && _stream != null && _stream.CanRead;
+ public override bool CanWrite => _mode == CompressionMode.Compress && _stream != null && _stream.CanWrite;
+ public override bool CanSeek => false;
+ public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
+ public override long Length => throw new NotSupportedException();
+ public override long Position
+ {
+ get => throw new NotSupportedException();
+ set => throw new NotSupportedException();
+ }
+ public override void SetLength(long value) => throw new NotSupportedException();
+
+ private int _activeAsyncOperation; // 1 == true, 0 == false
+ private bool AsyncOperationIsActive => _activeAsyncOperation != 0;
+
+ private void EnsureNoActiveAsyncOperation()
+ {
+ if (AsyncOperationIsActive)
+ ThrowInvalidBeginCall();
+ }
+
+ private void AsyncOperationStarting()
+ {
+ if (Interlocked.CompareExchange(ref _activeAsyncOperation, 1, 0) != 0)
+ {
+ ThrowInvalidBeginCall();
+ }
+ }
+
+ private void AsyncOperationCompleting()
+ {
+ int oldValue = Interlocked.CompareExchange(ref _activeAsyncOperation, 0, 1);
+ Debug.Assert(oldValue == 1, $"Expected {nameof(_activeAsyncOperation)} to be 1, got {oldValue}");
+ }
+
+ private static void ThrowInvalidBeginCall()
+ {
+ throw new InvalidOperationException(SR.InvalidBeginCall);
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs
new file mode 100644
index 000000000000..7dd6da519ae6
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/BrotliUtils.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.IO.Compression
+{
+ internal static partial class BrotliUtils
+ {
+ public const int WindowBits_Min = 10;
+ public const int WindowBits_Default = 22;
+ public const int WindowBits_Max = 24;
+ public const int Quality_Min = 0;
+ public const int Quality_Default = 11;
+ public const int Quality_Max = 11;
+ public const int MaxInputSize = int.MaxValue - 515; // 515 is the max compressed extra bytes
+
+ internal static int GetQualityFromCompressionLevel(CompressionLevel level)
+ {
+ switch (level)
+ {
+ case CompressionLevel.Optimal:
+ return Quality_Default;
+ case CompressionLevel.NoCompression:
+ return Quality_Min;
+ case CompressionLevel.Fastest:
+ return 1;
+ default:
+ return (int)level;
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs
new file mode 100644
index 000000000000..96a966b55262
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliDecoder.cs
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+using size_t = System.IntPtr;
+
+namespace System.IO.Compression
+{
+ public struct BrotliDecoder : IDisposable
+ {
+ private SafeBrotliDecoderHandle _state;
+ private bool _disposed;
+
+ internal void InitializeDecoder()
+ {
+ _state = Interop.Brotli.BrotliDecoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ if (_state.IsInvalid)
+ throw new IOException(SR.BrotliDecoder_Create);
+ }
+
+ internal void EnsureInitialized()
+ {
+ EnsureNotDisposed();
+ if (_state == null)
+ InitializeDecoder();
+ }
+
+ public void Dispose()
+ {
+ _disposed = true;
+ _state?.Dispose();
+ }
+
+ private void EnsureNotDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(nameof(BrotliDecoder), SR.BrotliDecoder_Disposed);
+ }
+
+ public OperationStatus Decompress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten)
+ {
+ EnsureInitialized();
+ bytesConsumed = 0;
+ bytesWritten = 0;
+ if (Interop.Brotli.BrotliDecoderIsFinished(_state))
+ return OperationStatus.Done;
+ size_t availableOutput = (size_t)destination.Length;
+ size_t availableInput = (size_t)source.Length;
+ unsafe
+ {
+ // We can freely cast between int and size_t for two reasons:
+ // 1. Interop Brotli functions will always return an availableInput/Output value lower or equal to the one passed to the function
+ // 2. Span's have a maximum length of the int boundary.
+ while ((int)availableOutput > 0)
+ {
+ fixed (byte* inBytes = &MemoryMarshal.GetReference(source))
+ fixed (byte* outBytes = &MemoryMarshal.GetReference(destination))
+ {
+ // MCS bug workaround:
+ byte* inBytesPtr = inBytes;
+ byte* outBytesPtr = outBytes;
+
+ int brotliResult = Interop.Brotli.BrotliDecoderDecompressStream(_state, ref availableInput, &inBytesPtr, ref availableOutput, &outBytesPtr, out size_t totalOut);
+ if (brotliResult == 0) // Error
+ {
+ return OperationStatus.InvalidData;
+ }
+ bytesConsumed += source.Length - (int)availableInput;
+ bytesWritten += destination.Length - (int)availableOutput;
+
+ switch (brotliResult)
+ {
+ case 1: // Success
+ return OperationStatus.Done;
+ case 3: // NeedsMoreOutput
+ return OperationStatus.DestinationTooSmall;
+ case 2: // NeedsMoreInput
+ default:
+ source = source.Slice(source.Length - (int)availableInput);
+ destination = destination.Slice(destination.Length - (int)availableOutput);
+ if (brotliResult == 2 && source.Length == 0)
+ return OperationStatus.NeedMoreData;
+ break;
+ }
+ }
+ }
+ return OperationStatus.DestinationTooSmall;
+ }
+ }
+
+ public static bool TryDecompress(ReadOnlySpan source, Span destination, out int bytesWritten)
+ {
+ unsafe
+ {
+ fixed (byte* inBytes = &MemoryMarshal.GetReference(source))
+ fixed (byte* outBytes = &MemoryMarshal.GetReference(destination))
+ {
+ size_t availableOutput = (size_t)destination.Length;
+ bool success = Interop.Brotli.BrotliDecoderDecompress((size_t)source.Length, inBytes, ref availableOutput, outBytes);
+ bytesWritten = (int)availableOutput;
+ return success;
+ }
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs
new file mode 100644
index 000000000000..a4489b57e82b
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/dec/BrotliStream.Decompress.cs
@@ -0,0 +1,175 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO.Compression
+{
+ public sealed partial class BrotliStream : Stream
+ {
+ private BrotliDecoder _decoder;
+ private int _bufferOffset;
+ private int _bufferCount;
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ ValidateParameters(buffer, offset, count);
+ return Read(new Span(buffer, offset, count));
+ }
+
+ public override int Read(Span buffer)
+ {
+ if (_mode != CompressionMode.Decompress)
+ throw new InvalidOperationException(SR.BrotliStream_Compress_UnsupportedOperation);
+ EnsureNotDisposed();
+ int totalWritten = 0;
+
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ // We want to continue calling Decompress until we're either out of space for output or until Decompress indicates it is finished.
+ while (buffer.Length > 0 && lastResult != OperationStatus.Done)
+ {
+ if (lastResult == OperationStatus.NeedMoreData)
+ {
+ // Ensure any left over data is at the beginning of the array so we can fill the remainder.
+ if (_bufferCount > 0 && _bufferOffset != 0)
+ {
+ _buffer.AsSpan(_bufferOffset, _bufferCount).CopyTo(_buffer);
+ }
+ _bufferOffset = 0;
+
+ int numRead = 0;
+ while (_bufferCount < _buffer.Length && ((numRead = _stream.Read(_buffer, _bufferCount, _buffer.Length - _bufferCount)) > 0))
+ {
+ _bufferCount += numRead;
+ if (_bufferCount > _buffer.Length)
+ {
+ // The stream is either malicious or poorly implemented and returned a number of
+ // bytes larger than the buffer supplied to it.
+ throw new InvalidDataException(SR.BrotliStream_Decompress_InvalidStream);
+ }
+ }
+
+ if (_bufferCount <= 0)
+ {
+ break;
+ }
+ }
+
+ lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer, out int bytesConsumed, out int bytesWritten);
+ if (lastResult == OperationStatus.InvalidData)
+ {
+ throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData);
+ }
+
+ if (bytesConsumed > 0)
+ {
+ _bufferOffset += bytesConsumed;
+ _bufferCount -= bytesConsumed;
+ }
+
+ if (bytesWritten > 0)
+ {
+ totalWritten += bytesWritten;
+ buffer = buffer.Slice(bytesWritten);
+ }
+ }
+
+ return totalWritten;
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) =>
+ TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState);
+
+ public override int EndRead(IAsyncResult asyncResult) =>
+ TaskToApm.End(asyncResult);
+
+ public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ ValidateParameters(buffer, offset, count);
+ return ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask();
+ }
+
+ public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (_mode != CompressionMode.Decompress)
+ throw new InvalidOperationException(SR.BrotliStream_Compress_UnsupportedOperation);
+ EnsureNoActiveAsyncOperation();
+ EnsureNotDisposed();
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return new ValueTask(Task.FromCanceled(cancellationToken));
+ }
+ return FinishReadAsyncMemory(buffer, cancellationToken);
+ }
+
+ private async ValueTask FinishReadAsyncMemory(Memory buffer, CancellationToken cancellationToken)
+ {
+ AsyncOperationStarting();
+ try
+ {
+ int totalWritten = 0;
+ Memory source = Memory.Empty;
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ // We want to continue calling Decompress until we're either out of space for output or until Decompress indicates it is finished.
+ while (buffer.Length > 0 && lastResult != OperationStatus.Done)
+ {
+ if (lastResult == OperationStatus.NeedMoreData)
+ {
+ // Ensure any left over data is at the beginning of the array so we can fill the remainder.
+ if (_bufferCount > 0 && _bufferOffset != 0)
+ {
+ _buffer.AsSpan(_bufferOffset, _bufferCount).CopyTo(_buffer);
+ }
+ _bufferOffset = 0;
+
+ int numRead = 0;
+ while (_bufferCount < _buffer.Length && ((numRead = await _stream.ReadAsync(new Memory(_buffer, _bufferCount, _buffer.Length - _bufferCount)).ConfigureAwait(false)) > 0))
+ {
+ _bufferCount += numRead;
+ if (_bufferCount > _buffer.Length)
+ {
+ // The stream is either malicious or poorly implemented and returned a number of
+ // bytes larger than the buffer supplied to it.
+ throw new InvalidDataException(SR.BrotliStream_Decompress_InvalidStream);
+ }
+ }
+
+ if (_bufferCount <= 0)
+ {
+ break;
+ }
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+ lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer.Span, out int bytesConsumed, out int bytesWritten);
+ if (lastResult == OperationStatus.InvalidData)
+ {
+ throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData);
+ }
+
+ if (bytesConsumed > 0)
+ {
+ _bufferOffset += bytesConsumed;
+ _bufferCount -= bytesConsumed;
+ }
+
+ if (bytesWritten > 0)
+ {
+ totalWritten += bytesWritten;
+ buffer = buffer.Slice(bytesWritten);
+ }
+ }
+
+ return totalWritten;
+ }
+ finally
+ {
+ AsyncOperationCompleting();
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs
new file mode 100644
index 000000000000..89f094c85551
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoder.cs
@@ -0,0 +1,186 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+using size_t = System.IntPtr;
+
+namespace System.IO.Compression
+{
+ public partial struct BrotliEncoder : IDisposable
+ {
+ internal SafeBrotliEncoderHandle _state;
+ private bool _disposed;
+
+ public BrotliEncoder(int quality, int window)
+ {
+ _disposed = false;
+ _state = Interop.Brotli.BrotliEncoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ if (_state.IsInvalid)
+ throw new IOException(SR.BrotliEncoder_Create);
+ SetQuality(quality);
+ SetWindow(window);
+ }
+
+ ///
+ /// Performs a lazy initialization of the native encoder using the default Quality and Window values:
+ /// BROTLI_DEFAULT_WINDOW 22
+ /// BROTLI_DEFAULT_QUALITY 11
+ ///
+ internal void InitializeEncoder()
+ {
+ EnsureNotDisposed();
+ _state = Interop.Brotli.BrotliEncoderCreateInstance(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ if (_state.IsInvalid)
+ throw new IOException(SR.BrotliEncoder_Create);
+ }
+
+ internal void EnsureInitialized()
+ {
+ EnsureNotDisposed();
+ if (_state == null)
+ {
+ InitializeEncoder();
+ }
+ }
+
+ public void Dispose()
+ {
+ _disposed = true;
+ _state?.Dispose();
+ }
+
+ private void EnsureNotDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(nameof(BrotliEncoder), SR.BrotliEncoder_Disposed);
+ }
+
+ internal void SetQuality(int quality)
+ {
+ EnsureNotDisposed();
+ if (_state == null || _state.IsInvalid || _state.IsClosed)
+ {
+ InitializeEncoder();
+ }
+ if (quality < BrotliUtils.Quality_Min || quality > BrotliUtils.Quality_Max)
+ {
+ throw new ArgumentOutOfRangeException(nameof(quality), SR.Format(SR.BrotliEncoder_Quality, quality, 0, BrotliUtils.Quality_Max));
+ }
+ if (!Interop.Brotli.BrotliEncoderSetParameter(_state, BrotliEncoderParameter.Quality, (uint)quality))
+ {
+ throw new InvalidOperationException(SR.Format(SR.BrotliEncoder_InvalidSetParameter, "Quality"));
+ }
+ }
+
+ internal void SetWindow(int window)
+ {
+ EnsureNotDisposed();
+ if (_state == null || _state.IsInvalid || _state.IsClosed)
+ {
+ InitializeEncoder();
+ }
+ if (window < BrotliUtils.WindowBits_Min || window > BrotliUtils.WindowBits_Max)
+ {
+ throw new ArgumentOutOfRangeException(nameof(window), SR.Format(SR.BrotliEncoder_Window, window, BrotliUtils.WindowBits_Min, BrotliUtils.WindowBits_Max));
+ }
+ if (!Interop.Brotli.BrotliEncoderSetParameter(_state, BrotliEncoderParameter.LGWin, (uint)window))
+ {
+ throw new InvalidOperationException(SR.Format(SR.BrotliEncoder_InvalidSetParameter, "Window"));
+ }
+ }
+
+ public static int GetMaxCompressedLength(int length)
+ {
+ if (length < 0 || length > BrotliUtils.MaxInputSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(length));
+ }
+ if (length == 0)
+ return 1;
+ int numLargeBlocks = length >> 24;
+ int tail = length & 0xFFFFFF;
+ int tailOverhead = (tail > (1 << 20)) ? 4 : 3;
+ int overhead = 2 + (4 * numLargeBlocks) + tailOverhead + 1;
+ int result = length + overhead;
+ return result;
+ }
+
+ internal OperationStatus Flush(Memory destination, out int bytesWritten) => Flush(destination.Span, out bytesWritten);
+
+ public OperationStatus Flush(Span destination, out int bytesWritten) => Compress(ReadOnlySpan.Empty, destination, out int bytesConsumed, out bytesWritten, BrotliEncoderOperation.Flush);
+
+ internal OperationStatus Compress(ReadOnlyMemory source, Memory destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) => Compress(source.Span, destination.Span, out bytesConsumed, out bytesWritten, isFinalBlock);
+
+ public OperationStatus Compress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) => Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock ? BrotliEncoderOperation.Finish : BrotliEncoderOperation.Process);
+
+ internal OperationStatus Compress(ReadOnlySpan source, Span destination, out int bytesConsumed, out int bytesWritten, BrotliEncoderOperation operation)
+ {
+ EnsureInitialized();
+ bytesWritten = 0;
+ bytesConsumed = 0;
+ size_t availableOutput = (size_t)destination.Length;
+ size_t availableInput = (size_t)source.Length;
+ unsafe
+ {
+ // We can freely cast between int and size_t for two reasons:
+ // 1. Interop Brotli functions will always return an availableInput/Output value lower or equal to the one passed to the function
+ // 2. Span's have a maximum length of the int boundary.
+ while ((int)availableOutput > 0)
+ {
+ fixed (byte* inBytes = &MemoryMarshal.GetReference(source))
+ fixed (byte* outBytes = &MemoryMarshal.GetReference(destination))
+ {
+ // MCS bug workaround:
+ byte* inBytesPtr = inBytes;
+ byte* outBytesPtr = outBytes;
+
+ if (!Interop.Brotli.BrotliEncoderCompressStream(_state, operation, ref availableInput, &inBytesPtr, ref availableOutput, &outBytesPtr, out size_t totalOut))
+ {
+ return OperationStatus.InvalidData;
+ }
+ bytesConsumed += source.Length - (int)availableInput;
+ bytesWritten += destination.Length - (int)availableOutput;
+ // no bytes written, no remaining input to give to the encoder, and no output in need of retrieving means we are Done
+ if ((int)availableOutput == destination.Length && !Interop.Brotli.BrotliEncoderHasMoreOutput(_state) && (int)availableInput == 0)
+ {
+ return OperationStatus.Done;
+ }
+
+ source = source.Slice(source.Length - (int)availableInput);
+ destination = destination.Slice(destination.Length - (int)availableOutput);
+ }
+ }
+
+ return OperationStatus.DestinationTooSmall;
+ }
+ }
+
+ public static bool TryCompress(ReadOnlySpan source, Span destination, out int bytesWritten) => TryCompress(source, destination, out bytesWritten, BrotliUtils.Quality_Default, BrotliUtils.WindowBits_Default);
+
+ public static bool TryCompress(ReadOnlySpan source, Span destination, out int bytesWritten, int quality, int window)
+ {
+ if (quality < 0 || quality > BrotliUtils.Quality_Max)
+ {
+ throw new ArgumentOutOfRangeException(nameof(quality), SR.Format(SR.BrotliEncoder_Quality, quality, 0, BrotliUtils.Quality_Max));
+ }
+ if (window < BrotliUtils.WindowBits_Min || window > BrotliUtils.WindowBits_Max)
+ {
+ throw new ArgumentOutOfRangeException(nameof(window), SR.Format(SR.BrotliEncoder_Window, window, BrotliUtils.WindowBits_Min, BrotliUtils.WindowBits_Max));
+ }
+ unsafe
+ {
+ fixed (byte* inBytes = &MemoryMarshal.GetReference(source))
+ fixed (byte* outBytes = &MemoryMarshal.GetReference(destination))
+ {
+ size_t availableOutput = (size_t)destination.Length;
+ bool success = Interop.Brotli.BrotliEncoderCompress(quality, window, /*BrotliEncoderMode*/ 0, (size_t)source.Length, inBytes, ref availableOutput, outBytes);
+ bytesWritten = (int)availableOutput;
+ return success;
+ }
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs
new file mode 100644
index 000000000000..ade5d63c9bf1
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderOperation.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.IO.Compression
+{
+ ///
+ /// Process - Process input. Encoder may postpone producing output, until it has processed enough input.
+ /// Flush - Produce output for all processed input. Actual flush is performed when input stream is depleted and there is enough space in output stream.
+ /// Finish - Finalize the stream. Adding more input data to finalized stream is impossible.
+ /// EmitMetadata - Emit metadata block to stream. Stream is soft-flushed before metadata block is emitted. Metadata bloc MUST be no longer than 16MiB.
+ ///
+ internal enum BrotliEncoderOperation
+ {
+ Process,
+ Flush,
+ Finish,
+ EmitMetadata
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs
new file mode 100644
index 000000000000..8d3cf110b4fb
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliEncoderParameter.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.IO.Compression
+{
+ ///
+ /// Mode - BrotliEncoderMode enumerates all available values.
+ /// Quality - The main compression speed-density lever. The higher the quality, the slower the compression. Range is from ::BROTLI_MIN_QUALITY to::BROTLI_MAX_QUALITY.
+ /// LGWin - Recommended sliding LZ77 window size. Encoder may reduce this value, e.g. if input is much smaller than window size. Range is from BROTLI_MIN_WINDOW_BITS to BROTLI_MAX_WINDOW_BITS.
+ /// LGBlock - Recommended input block size. Encoder may reduce this value, e.g. if input is much smaller than window size. Range is from BROTLI_MIN_INPUT_BLOCK_BITS to BROTLI_MAX_INPUT_BLOCK_BITS. Bigger input block size allows better compression, but consumes more memory.
+ /// LCModeling- Flag that affects usage of "literal context modeling" format feature. This flag is a "decoding-speed vs compression ratio" trade-off.
+ /// SizeHint - Estimated total input size for all BrotliEncoderCompressStream calls. The default value is 0, which means that the total input size is unknown.
+ ///
+ internal enum BrotliEncoderParameter
+ {
+ Mode,
+ Quality,
+ LGWin,
+ LGBlock,
+ LCModeling,
+ SizeHint
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs
new file mode 100644
index 000000000000..0770c46989e2
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs
@@ -0,0 +1,165 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO.Compression
+{
+ public sealed partial class BrotliStream : Stream
+ {
+ private BrotliEncoder _encoder;
+
+ public BrotliStream(Stream stream, CompressionLevel compressionLevel) : this(stream, compressionLevel, leaveOpen: false) { }
+ public BrotliStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen) : this(stream, CompressionMode.Compress, leaveOpen)
+ {
+ _encoder.SetQuality(BrotliUtils.GetQualityFromCompressionLevel(compressionLevel));
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ ValidateParameters(buffer, offset, count);
+ WriteCore(new ReadOnlySpan(buffer, offset, count));
+ }
+
+ public override void Write(ReadOnlySpan buffer)
+ {
+ WriteCore(buffer);
+ }
+
+ internal void WriteCore(ReadOnlySpan buffer, bool isFinalBlock = false)
+ {
+ if (_mode != CompressionMode.Compress)
+ throw new InvalidOperationException(SR.BrotliStream_Decompress_UnsupportedOperation);
+ EnsureNotDisposed();
+
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ Span output = new Span(_buffer);
+ while (lastResult == OperationStatus.DestinationTooSmall)
+ {
+ int bytesConsumed = 0;
+ int bytesWritten = 0;
+ lastResult = _encoder.Compress(buffer, output, out bytesConsumed, out bytesWritten, isFinalBlock);
+ if (lastResult == OperationStatus.InvalidData)
+ throw new InvalidOperationException(SR.BrotliStream_Compress_InvalidData);
+ if (bytesWritten > 0)
+ _stream.Write(output.Slice(0, bytesWritten));
+ if (bytesConsumed > 0)
+ buffer = buffer.Slice(bytesConsumed);
+ }
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) =>
+ TaskToApm.Begin(WriteAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState);
+
+ public override void EndWrite(IAsyncResult asyncResult) =>
+ TaskToApm.End(asyncResult);
+
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ ValidateParameters(buffer, offset, count);
+ return WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask();
+ }
+
+ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (_mode != CompressionMode.Compress)
+ throw new InvalidOperationException(SR.BrotliStream_Decompress_UnsupportedOperation);
+ EnsureNoActiveAsyncOperation();
+ EnsureNotDisposed();
+
+ return new ValueTask(cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ WriteAsyncMemoryCore(buffer, cancellationToken));
+ }
+
+ private async Task WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken)
+ {
+ AsyncOperationStarting();
+ try
+ {
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ while (lastResult == OperationStatus.DestinationTooSmall)
+ {
+ Memory output = new Memory(_buffer);
+ int bytesConsumed = 0;
+ int bytesWritten = 0;
+ lastResult = _encoder.Compress(buffer, output, out bytesConsumed, out bytesWritten, isFinalBlock: false);
+ if (lastResult == OperationStatus.InvalidData)
+ throw new InvalidOperationException(SR.BrotliStream_Compress_InvalidData);
+ if (bytesConsumed > 0)
+ buffer = buffer.Slice(bytesConsumed);
+ if (bytesWritten > 0)
+ await _stream.WriteAsync(new ReadOnlyMemory(_buffer, 0, bytesWritten), cancellationToken).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ AsyncOperationCompleting();
+ }
+ }
+
+ public override void Flush()
+ {
+ EnsureNotDisposed();
+ if (_mode == CompressionMode.Compress)
+ {
+ if (_encoder._state == null || _encoder._state.IsClosed)
+ return;
+
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ Span output = new Span(_buffer);
+ while (lastResult == OperationStatus.DestinationTooSmall)
+ {
+ int bytesWritten = 0;
+ lastResult = _encoder.Flush(output, out bytesWritten);
+ if (lastResult == OperationStatus.InvalidData)
+ throw new InvalidDataException(SR.BrotliStream_Compress_InvalidData);
+ if (bytesWritten > 0)
+ {
+ _stream.Write(output.Slice(0, bytesWritten));
+ }
+ }
+ }
+ }
+
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ EnsureNoActiveAsyncOperation();
+ EnsureNotDisposed();
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ return _mode != CompressionMode.Compress ? Task.CompletedTask : FlushAsyncCore(cancellationToken);
+ }
+
+ private async Task FlushAsyncCore(CancellationToken cancellationToken)
+ {
+ AsyncOperationStarting();
+ try
+ {
+ if (_encoder._state == null || _encoder._state.IsClosed)
+ return;
+
+ OperationStatus lastResult = OperationStatus.DestinationTooSmall;
+ while (lastResult == OperationStatus.DestinationTooSmall)
+ {
+ Memory output = new Memory(_buffer);
+ int bytesWritten = 0;
+ lastResult = _encoder.Flush(output, out bytesWritten);
+ if (lastResult == OperationStatus.InvalidData)
+ throw new InvalidDataException(SR.BrotliStream_Compress_InvalidData);
+ if (bytesWritten > 0)
+ await _stream.WriteAsync(output.Slice(0, bytesWritten), cancellationToken).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ AsyncOperationCompleting();
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs
new file mode 100644
index 000000000000..171d35464e34
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliEncoderTests.cs
@@ -0,0 +1,387 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.IO.Compression.Tests
+{
+ public class BrotliEncoderTests : CompressionTestBase
+ {
+ protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br");
+
+ [Fact]
+ public void InvalidQuality()
+ {
+ Assert.Throws("quality", () => new BrotliEncoder(-1, 11));
+ Assert.Throws("quality", () => new BrotliEncoder(12, 11));
+ Assert.Throws("quality", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, -1, 13));
+ Assert.Throws("quality", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 12, 13));
+ }
+
+ [Fact]
+ public void InvalidWindow()
+ {
+ Assert.Throws("window", () => new BrotliEncoder(10, -1));
+ Assert.Throws("window", () => new BrotliEncoder(10, 9));
+ Assert.Throws("window", () => new BrotliEncoder(10, 25));
+ Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, -1));
+ Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, 9));
+ Assert.Throws("window", () => BrotliEncoder.TryCompress(new ReadOnlySpan(), new Span(), out int bytesWritten, 6, 25));
+ }
+
+ [Fact]
+ public void GetMaxCompressedSize_Basic()
+ {
+ Assert.Throws("length", () => BrotliEncoder.GetMaxCompressedLength(-1));
+ Assert.Throws("length", () => BrotliEncoder.GetMaxCompressedLength(2147483133));
+ Assert.InRange(BrotliEncoder.GetMaxCompressedLength(2147483132), 0, Int32.MaxValue);
+ Assert.Equal(1, BrotliEncoder.GetMaxCompressedLength(0));
+ }
+
+ [Fact]
+ public void GetMaxCompressedSize()
+ {
+ string uncompressedFile = UncompressedTestFile();
+ string compressedFile = CompressedTestFile(uncompressedFile);
+ int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength((int)new FileInfo(uncompressedFile).Length);
+ int actualCompressedSize = (int)new FileInfo(compressedFile).Length;
+ Assert.True(maxCompressedSize >= actualCompressedSize, $"MaxCompressedSize: {maxCompressedSize}, ActualCompressedSize: {actualCompressedSize}");
+ }
+
+ ///
+ /// Test to ensure that when given an empty Destination span, the decoder will consume no input and write no output.
+ ///
+ [Fact]
+ public void Decompress_WithEmptyDestination()
+ {
+ string testFile = UncompressedTestFile();
+ byte[] sourceBytes = File.ReadAllBytes(CompressedTestFile(testFile));
+ byte[] destinationBytes = new byte[0];
+ ReadOnlySpan source = new ReadOnlySpan(sourceBytes);
+ Span destination = new Span(destinationBytes);
+
+ Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a destination array");
+ Assert.Equal(0, bytesWritten);
+
+ BrotliDecoder decoder = default;
+ var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten);
+ Assert.Equal(0, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.DestinationTooSmall, result);
+ }
+
+ ///
+ /// Test to ensure that when given an empty source span, the decoder will consume no input and write no output
+ ///
+ [Fact]
+ public void Decompress_WithEmptySource()
+ {
+ string testFile = UncompressedTestFile();
+ byte[] sourceBytes = new byte[0];
+ byte[] destinationBytes = new byte[100000];
+ ReadOnlySpan source = new ReadOnlySpan(sourceBytes);
+ Span destination = new Span(destinationBytes);
+
+ Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a source array");
+ Assert.Equal(0, bytesWritten);
+
+ BrotliDecoder decoder = default;
+ var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten);
+ Assert.Equal(0, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.NeedMoreData, result);
+ }
+
+ ///
+ /// Test to ensure that when given an empty Destination span, the encoder consume no input and write no output
+ ///
+ [Fact]
+ public void Compress_WithEmptyDestination()
+ {
+ string testFile = UncompressedTestFile();
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile));
+ byte[] empty = new byte[0];
+ ReadOnlySpan source = new ReadOnlySpan(correctUncompressedBytes);
+ Span destination = new Span(empty);
+
+ Assert.False(BrotliEncoder.TryCompress(source, destination, out int bytesWritten), "TryCompress completed successfully but should have failed due to too short of a destination array");
+ Assert.Equal(0, bytesWritten);
+
+ BrotliEncoder encoder = default;
+ var result = encoder.Compress(source, destination, out int bytesConsumed, out bytesWritten, false);
+ Assert.Equal(0, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.DestinationTooSmall, result);
+
+ result = encoder.Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock: true);
+ Assert.Equal(0, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.DestinationTooSmall, result);
+ }
+
+ ///
+ /// Test to ensure that when given an empty source span, the decoder will consume no input and write no output (until the finishing block)
+ ///
+ [Fact]
+ public void Compress_WithEmptySource()
+ {
+ string testFile = UncompressedTestFile();
+ byte[] sourceBytes = new byte[0];
+ byte[] destinationBytes = new byte[100000];
+ ReadOnlySpan source = new ReadOnlySpan(sourceBytes);
+ Span destination = new Span(destinationBytes);
+
+ Assert.True(BrotliEncoder.TryCompress(source, destination, out int bytesWritten));
+ // The only byte written should be the Brotli end of stream byte which varies based on the window/quality
+ Assert.Equal(1, bytesWritten);
+
+ BrotliEncoder encoder = default;
+ var result = encoder.Compress(source, destination, out int bytesConsumed, out bytesWritten, false);
+ Assert.Equal(0, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.Done, result);
+
+ result = encoder.Compress(source, destination, out bytesConsumed, out bytesWritten, isFinalBlock: true);
+ Assert.Equal(1, bytesWritten);
+ Assert.Equal(0, bytesConsumed);
+ Assert.Equal(OperationStatus.Done, result);
+ }
+
+ ///
+ /// Test that the decoder can handle partial chunks of flushed encoded data sent from the BrotliEncoder
+ ///
+ [Fact]
+ public void RoundTrip_Chunks()
+ {
+ int chunkSize = 100;
+ int totalSize = 20000;
+ BrotliEncoder encoder = default;
+ BrotliDecoder decoder = default;
+ for (int i = 0; i < totalSize; i += chunkSize)
+ {
+ byte[] uncompressed = new byte[chunkSize];
+ new Random().NextBytes(uncompressed);
+ byte[] compressed = new byte[BrotliEncoder.GetMaxCompressedLength(chunkSize)];
+ byte[] deompressed = new byte[chunkSize];
+ var uncompressedSpan = new ReadOnlySpan(uncompressed);
+ var compressedSpan = new Span(compressed);
+ var decompressedSpan = new Span(deompressed);
+
+ int totalWrittenThisIteration = 0;
+ var compress = encoder.Compress(uncompressedSpan, compressedSpan, out int bytesConsumed, out int bytesWritten, isFinalBlock: false);
+ totalWrittenThisIteration += bytesWritten;
+ compress = encoder.Flush(compressedSpan.Slice(bytesWritten), out bytesWritten);
+ totalWrittenThisIteration += bytesWritten;
+
+ var res = decoder.Decompress(compressedSpan.Slice(0, totalWrittenThisIteration), decompressedSpan, out int decompressbytesConsumed, out int decompressbytesWritten);
+ Assert.Equal(totalWrittenThisIteration, decompressbytesConsumed);
+ Assert.Equal(bytesConsumed, decompressbytesWritten);
+ for (int j = 0; j < bytesConsumed; j++)
+ Assert.Equal(uncompressed[j], decompressedSpan[j]);
+
+ }
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void ReadFully(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile));
+ byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length + 10000];
+ ReadOnlySpan source = new ReadOnlySpan(compressedBytes);
+ Span destination = new Span(actualUncompressedBytes);
+ Assert.True(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress did not complete successfully");
+ Assert.Equal(correctUncompressedBytes.Length, bytesWritten);
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void ReadWithState(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile));
+ byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length];
+ Decompress_WithState(compressedBytes, actualUncompressedBytes);
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void ReadWithoutState(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile));
+ byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length];
+ Decompress_WithoutState(compressedBytes, actualUncompressedBytes);
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void WriteFully(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)];
+ byte[] actualUncompressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)];
+
+ Span destination = new Span(compressedBytes);
+
+ Assert.True(BrotliEncoder.TryCompress(correctUncompressedBytes, destination, out int bytesWritten));
+ Assert.True(BrotliDecoder.TryDecompress(destination, actualUncompressedBytes, out bytesWritten));
+ Assert.Equal(correctUncompressedBytes.Length, bytesWritten);
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void WriteWithState(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)];
+ byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length];
+
+ Compress_WithState(correctUncompressedBytes, compressedBytes);
+ Decompress_WithState(compressedBytes, actualUncompressedBytes);
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void WriteWithoutState(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)];
+ byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length];
+
+ Compress_WithoutState(correctUncompressedBytes, compressedBytes);
+ Decompress_WithoutState(compressedBytes, actualUncompressedBytes);
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [Theory]
+ [OuterLoop("Full set of UncompressedTestFiles takes around 15s to run")]
+ [MemberData(nameof(UncompressedTestFiles))]
+ public void WriteStream(string testFile)
+ {
+ byte[] correctUncompressedBytes = File.ReadAllBytes(testFile);
+ byte[] compressedBytes = Compress_Stream(correctUncompressedBytes, CompressionLevel.Optimal).ToArray();
+ byte[] actualUncompressedBytes = Decompress_Stream(compressedBytes).ToArray();
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ Assert.Equal(correctUncompressedBytes[i], actualUncompressedBytes[i]);
+ }
+
+ [OuterLoop("Full set of tests takes seconds to run")]
+ [Theory]
+ [InlineData(1, 0x400001, false)]
+ [InlineData(1, 0x400001, true)]
+ [InlineData(4, 0x800000, false)]
+ [InlineData(4, 0x800000, true)]
+ [InlineData(53, 12345, false)]
+ [InlineData(53, 12345, true)]
+ public static async Task Roundtrip_VaryingSizeReadsAndLengths_Success(int readSize, int totalLength, bool useAsync)
+ {
+ byte[] correctUncompressedBytes = Enumerable.Range(0, totalLength).Select(i => (byte)i).ToArray();
+ byte[] compressedBytes = Compress_Stream(correctUncompressedBytes, CompressionLevel.Fastest).ToArray();
+ byte[] actualBytes = new byte[correctUncompressedBytes.Length];
+
+ using (var s = new BrotliStream(new MemoryStream(compressedBytes), CompressionMode.Decompress))
+ {
+ int totalRead = 0;
+ while (totalRead < actualBytes.Length)
+ {
+ int numRead = useAsync ?
+ await s.ReadAsync(actualBytes, totalRead, Math.Min(readSize, actualBytes.Length - totalRead)) :
+ s.Read(actualBytes, totalRead, Math.Min(readSize, actualBytes.Length - totalRead));
+ totalRead += numRead;
+ }
+
+ for (int i = 0; i < correctUncompressedBytes.Length; i++)
+ {
+ Assert.Equal(correctUncompressedBytes[i], actualBytes[i]);
+ }
+ }
+ }
+
+ public static void Compress_WithState(ReadOnlySpan input, Span output)
+ {
+ BrotliEncoder encoder = default;
+ while (!input.IsEmpty && !output.IsEmpty)
+ {
+ encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock: false);
+ input = input.Slice(bytesConsumed);
+ output = output.Slice(written);
+ }
+ encoder.Compress(ReadOnlySpan.Empty, output, out int bytesConsumed2, out int bytesWritten, isFinalBlock: true);
+ }
+
+ public static void Decompress_WithState(ReadOnlySpan input, Span output)
+ {
+ BrotliDecoder decoder = default;
+ while (!input.IsEmpty && !output.IsEmpty)
+ {
+ decoder.Decompress(input, output, out int bytesConsumed, out int written);
+ input = input.Slice(bytesConsumed);
+ output = output.Slice(written);
+ }
+ }
+
+ public static void Compress_WithoutState(ReadOnlySpan input, Span output)
+ {
+ BrotliEncoder.TryCompress(input, output, out int bytesWritten);
+ }
+
+ public static void Decompress_WithoutState(ReadOnlySpan input, Span output)
+ {
+ BrotliDecoder.TryDecompress(input, output, out int bytesWritten);
+ }
+
+ public static MemoryStream Compress_Stream(ReadOnlySpan input, CompressionLevel compressionLevel)
+ {
+ using (var inputStream = new MemoryStream(input.ToArray()))
+ {
+ var outputStream = new MemoryStream();
+ var compressor = new BrotliStream(outputStream, compressionLevel, true);
+ inputStream.CopyTo(compressor);
+ compressor.Dispose();
+ return outputStream;
+ }
+ }
+
+ public static MemoryStream Decompress_Stream(ReadOnlySpan input)
+ {
+ using (var inputStream = new MemoryStream(input.ToArray()))
+ {
+ var outputStream = new MemoryStream();
+ var decompressor = new BrotliStream(inputStream, CompressionMode.Decompress, true);
+ decompressor.CopyTo(outputStream);
+ decompressor.Dispose();
+ return outputStream;
+ }
+ }
+ }
+}
diff --git a/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs
new file mode 100644
index 000000000000..8f066aa2856a
--- /dev/null
+++ b/external/corefx-bugfix/src/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Xunit;
+
+namespace System.IO.Compression.Tests
+{
+ public class BrotliGoogleTestData
+ {
+ public static IEnumerable