aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go')
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/BUILD2
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/WORKSPACE21
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/BUILD26
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cbrotli_test.go367
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cgo.go13
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/reader.go161
-rw-r--r--roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/writer.go159
7 files changed, 749 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/BUILD b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/BUILD
new file mode 100644
index 000000000..72a5317f1
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/BUILD
@@ -0,0 +1,2 @@
+# Description:
+# cbrotli is a CGo wrapper for Brotli, a generic-purpose lossless compression algorithm.
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/WORKSPACE b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/WORKSPACE
new file mode 100644
index 000000000..e9652697c
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/WORKSPACE
@@ -0,0 +1,21 @@
+workspace(name = "org_brotli_go")
+
+local_repository(
+ name = "org_brotli",
+ path = "..",
+)
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "io_bazel_rules_go",
+ urls = [
+ "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.19.0/rules_go-0.19.0.tar.gz",
+ "https://github.com/bazelbuild/rules_go/releases/download/0.19.0/rules_go-0.19.0.tar.gz",
+ ],
+ sha256 = "9fb16af4d4836c8222142e54c9efa0bb5fc562ffc893ce2abeac3e25daead144",
+)
+
+load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
+go_rules_dependencies()
+go_register_toolchains()
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/BUILD b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/BUILD
new file mode 100644
index 000000000..ce594ad19
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/BUILD
@@ -0,0 +1,26 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"]) # MIT
+
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "cbrotli",
+ srcs = [
+ "reader.go",
+ "writer.go",
+ ],
+ cdeps = [
+ "@org_brotli//:brotlidec",
+ "@org_brotli//:brotlienc",
+ ],
+ cgo = True,
+ importpath = "github.com/google/brotli/go/cbrotli",
+)
+
+go_test(
+ name = "cbrotli_test",
+ size = "small",
+ srcs = ["cbrotli_test.go"],
+ embed = [":cbrotli"],
+)
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cbrotli_test.go b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cbrotli_test.go
new file mode 100644
index 000000000..f59ec582d
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cbrotli_test.go
@@ -0,0 +1,367 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Distributed under MIT license.
+// See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+
+package cbrotli
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math"
+ "math/rand"
+ "testing"
+ "time"
+)
+
+func checkCompressedData(compressedData, wantOriginalData []byte) error {
+ uncompressed, err := Decode(compressedData)
+ if err != nil {
+ return fmt.Errorf("brotli decompress failed: %v", err)
+ }
+ if !bytes.Equal(uncompressed, wantOriginalData) {
+ if len(wantOriginalData) != len(uncompressed) {
+ return fmt.Errorf(""+
+ "Data doesn't uncompress to the original value.\n"+
+ "Length of original: %v\n"+
+ "Length of uncompressed: %v",
+ len(wantOriginalData), len(uncompressed))
+ }
+ for i := range wantOriginalData {
+ if wantOriginalData[i] != uncompressed[i] {
+ return fmt.Errorf(""+
+ "Data doesn't uncompress to the original value.\n"+
+ "Original at %v is %v\n"+
+ "Uncompressed at %v is %v",
+ i, wantOriginalData[i], i, uncompressed[i])
+ }
+ }
+ }
+ return nil
+}
+
+func TestEncoderNoWrite(t *testing.T) {
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 5})
+ if err := e.Close(); err != nil {
+ t.Errorf("Close()=%v, want nil", err)
+ }
+ // Check Write after close.
+ if _, err := e.Write([]byte("hi")); err == nil {
+ t.Errorf("No error after Close() + Write()")
+ }
+}
+
+func TestEncoderEmptyWrite(t *testing.T) {
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 5})
+ n, err := e.Write([]byte(""))
+ if n != 0 || err != nil {
+ t.Errorf("Write()=%v,%v, want 0, nil", n, err)
+ }
+ if err := e.Close(); err != nil {
+ t.Errorf("Close()=%v, want nil", err)
+ }
+}
+
+func TestWriter(t *testing.T) {
+ // Test basic encoder usage.
+ input := []byte("<html><body><H1>Hello world</H1></body></html>")
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 1})
+ in := bytes.NewReader([]byte(input))
+ n, err := io.Copy(e, in)
+ if err != nil {
+ t.Errorf("Copy Error: %v", err)
+ }
+ if int(n) != len(input) {
+ t.Errorf("Copy() n=%v, want %v", n, len(input))
+ }
+ if err := e.Close(); err != nil {
+ t.Errorf("Close Error after copied %d bytes: %v", n, err)
+ }
+ if err := checkCompressedData(out.Bytes(), input); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestEncoderStreams(t *testing.T) {
+ // Test that output is streamed.
+ // Adjust window size to ensure the encoder outputs at least enough bytes
+ // to fill the window.
+ const lgWin = 16
+ windowSize := int(math.Pow(2, lgWin))
+ input := make([]byte, 8*windowSize)
+ rand.Read(input)
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 11, LGWin: lgWin})
+ halfInput := input[:len(input)/2]
+ in := bytes.NewReader(halfInput)
+
+ n, err := io.Copy(e, in)
+ if err != nil {
+ t.Errorf("Copy Error: %v", err)
+ }
+
+ // We've fed more data than the sliding window size. Check that some
+ // compressed data has been output.
+ if out.Len() == 0 {
+ t.Errorf("Output length is 0 after %d bytes written", n)
+ }
+ if err := e.Close(); err != nil {
+ t.Errorf("Close Error after copied %d bytes: %v", n, err)
+ }
+ if err := checkCompressedData(out.Bytes(), halfInput); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestEncoderLargeInput(t *testing.T) {
+ input := make([]byte, 1000000)
+ rand.Read(input)
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 5})
+ in := bytes.NewReader(input)
+
+ n, err := io.Copy(e, in)
+ if err != nil {
+ t.Errorf("Copy Error: %v", err)
+ }
+ if int(n) != len(input) {
+ t.Errorf("Copy() n=%v, want %v", n, len(input))
+ }
+ if err := e.Close(); err != nil {
+ t.Errorf("Close Error after copied %d bytes: %v", n, err)
+ }
+ if err := checkCompressedData(out.Bytes(), input); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestEncoderFlush(t *testing.T) {
+ input := make([]byte, 1000)
+ rand.Read(input)
+ out := bytes.Buffer{}
+ e := NewWriter(&out, WriterOptions{Quality: 5})
+ in := bytes.NewReader(input)
+ _, err := io.Copy(e, in)
+ if err != nil {
+ t.Fatalf("Copy Error: %v", err)
+ }
+ if err := e.Flush(); err != nil {
+ t.Fatalf("Flush(): %v", err)
+ }
+ if out.Len() == 0 {
+ t.Fatalf("0 bytes written after Flush()")
+ }
+ decompressed := make([]byte, 1000)
+ reader := NewReader(bytes.NewReader(out.Bytes()))
+ n, err := reader.Read(decompressed)
+ if n != len(decompressed) || err != nil {
+ t.Errorf("Expected <%v, nil>, but <%v, %v>", len(decompressed), n, err)
+ }
+ reader.Close()
+ if !bytes.Equal(decompressed, input) {
+ t.Errorf(""+
+ "Decompress after flush: %v\n"+
+ "%q\n"+
+ "want:\n%q",
+ err, decompressed, input)
+ }
+ if err := e.Close(); err != nil {
+ t.Errorf("Close(): %v", err)
+ }
+}
+
+type readerWithTimeout struct {
+ io.ReadCloser
+}
+
+func (r readerWithTimeout) Read(p []byte) (int, error) {
+ type result struct {
+ n int
+ err error
+ }
+ ch := make(chan result)
+ go func() {
+ n, err := r.ReadCloser.Read(p)
+ ch <- result{n, err}
+ }()
+ select {
+ case result := <-ch:
+ return result.n, result.err
+ case <-time.After(5 * time.Second):
+ return 0, fmt.Errorf("read timed out")
+ }
+}
+
+func TestDecoderStreaming(t *testing.T) {
+ pr, pw := io.Pipe()
+ writer := NewWriter(pw, WriterOptions{Quality: 5, LGWin: 20})
+ reader := readerWithTimeout{NewReader(pr)}
+ defer func() {
+ if err := reader.Close(); err != nil {
+ t.Errorf("reader.Close: %v", err)
+ }
+ go ioutil.ReadAll(pr) // swallow the "EOF" token from writer.Close
+ if err := writer.Close(); err != nil {
+ t.Errorf("writer.Close: %v", err)
+ }
+ }()
+
+ ch := make(chan []byte)
+ errch := make(chan error)
+ go func() {
+ for {
+ segment, ok := <-ch
+ if !ok {
+ return
+ }
+ if n, err := writer.Write(segment); err != nil || n != len(segment) {
+ errch <- fmt.Errorf("write=%v,%v, want %v,%v", n, err, len(segment), nil)
+ return
+ }
+ if err := writer.Flush(); err != nil {
+ errch <- fmt.Errorf("flush: %v", err)
+ return
+ }
+ }
+ }()
+ defer close(ch)
+
+ segments := [...][]byte{
+ []byte("first"),
+ []byte("second"),
+ []byte("third"),
+ }
+ for k, segment := range segments {
+ t.Run(fmt.Sprintf("Segment%d", k), func(t *testing.T) {
+ select {
+ case ch <- segment:
+ case err := <-errch:
+ t.Fatalf("write: %v", err)
+ case <-time.After(5 * time.Second):
+ t.Fatalf("timed out")
+ }
+ wantLen := len(segment)
+ got := make([]byte, wantLen)
+ if n, err := reader.Read(got); err != nil || n != wantLen || !bytes.Equal(got, segment) {
+ t.Fatalf("read[%d]=%q,%v,%v, want %q,%v,%v", k, got, n, err, segment, wantLen, nil)
+ }
+ })
+ }
+}
+
+func TestReader(t *testing.T) {
+ content := bytes.Repeat([]byte("hello world!"), 10000)
+ encoded, _ := Encode(content, WriterOptions{Quality: 5})
+ r := NewReader(bytes.NewReader(encoded))
+ var decodedOutput bytes.Buffer
+ n, err := io.Copy(&decodedOutput, r)
+ if err != nil {
+ t.Fatalf("Copy(): n=%v, err=%v", n, err)
+ }
+ if err := r.Close(); err != nil {
+ t.Errorf("Close(): %v", err)
+ }
+ if got := decodedOutput.Bytes(); !bytes.Equal(got, content) {
+ t.Errorf(""+
+ "Reader output:\n"+
+ "%q\n"+
+ "want:\n"+
+ "<%d bytes>",
+ got, len(content))
+ }
+}
+
+func TestDecode(t *testing.T) {
+ content := bytes.Repeat([]byte("hello world!"), 10000)
+ encoded, _ := Encode(content, WriterOptions{Quality: 5})
+ decoded, err := Decode(encoded)
+ if err != nil {
+ t.Errorf("Decode: %v", err)
+ }
+ if !bytes.Equal(decoded, content) {
+ t.Errorf(""+
+ "Decode content:\n"+
+ "%q\n"+
+ "want:\n"+
+ "<%d bytes>",
+ decoded, len(content))
+ }
+}
+
+func TestDecodeFuzz(t *testing.T) {
+ // Test that the decoder terminates with corrupted input.
+ content := bytes.Repeat([]byte("hello world!"), 100)
+ src := rand.NewSource(0)
+ encoded, err := Encode(content, WriterOptions{Quality: 5})
+ if err != nil {
+ t.Fatalf("Encode(<%d bytes>, _) = _, %s", len(content), err)
+ }
+ if len(encoded) == 0 {
+ t.Fatalf("Encode(<%d bytes>, _) produced empty output", len(content))
+ }
+ for i := 0; i < 100; i++ {
+ enc := append([]byte{}, encoded...)
+ for j := 0; j < 5; j++ {
+ enc[int(src.Int63())%len(enc)] = byte(src.Int63() % 256)
+ }
+ Decode(enc)
+ }
+}
+
+func TestDecodeTrailingData(t *testing.T) {
+ content := bytes.Repeat([]byte("hello world!"), 100)
+ encoded, _ := Encode(content, WriterOptions{Quality: 5})
+ _, err := Decode(append(encoded, 0))
+ if err == nil {
+ t.Errorf("Expected 'excessive input' error")
+ }
+}
+
+func TestEncodeDecode(t *testing.T) {
+ for _, test := range []struct {
+ data []byte
+ repeats int
+ }{
+ {nil, 0},
+ {[]byte("A"), 1},
+ {[]byte("<html><body><H1>Hello world</H1></body></html>"), 10},
+ {[]byte("<html><body><H1>Hello world</H1></body></html>"), 1000},
+ } {
+ t.Logf("case %q x %d", test.data, test.repeats)
+ input := bytes.Repeat(test.data, test.repeats)
+ encoded, err := Encode(input, WriterOptions{Quality: 5})
+ if err != nil {
+ t.Errorf("Encode: %v", err)
+ }
+ // Inputs are compressible, but may be too small to compress.
+ if maxSize := len(input)/2 + 20; len(encoded) >= maxSize {
+ t.Errorf(""+
+ "Encode returned %d bytes, want <%d\n"+
+ "Encoded=%q",
+ len(encoded), maxSize, encoded)
+ }
+ decoded, err := Decode(encoded)
+ if err != nil {
+ t.Errorf("Decode: %v", err)
+ }
+ if !bytes.Equal(decoded, input) {
+ var want string
+ if len(input) > 320 {
+ want = fmt.Sprintf("<%d bytes>", len(input))
+ } else {
+ want = fmt.Sprintf("%q", input)
+ }
+ t.Errorf(""+
+ "Decode content:\n"+
+ "%q\n"+
+ "want:\n"+
+ "%s",
+ decoded, want)
+ }
+ }
+}
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cgo.go b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cgo.go
new file mode 100644
index 000000000..f953f72cd
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/cgo.go
@@ -0,0 +1,13 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Distributed under MIT license.
+// See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+
+package cbrotli
+
+// Inform golang build system that it should link brotli libraries.
+
+// #cgo LDFLAGS: -lbrotlicommon
+// #cgo LDFLAGS: -lbrotlidec
+// #cgo LDFLAGS: -lbrotlienc
+import "C"
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/reader.go b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/reader.go
new file mode 100644
index 000000000..3d8d42450
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/reader.go
@@ -0,0 +1,161 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Distributed under MIT license.
+// See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+
+// Package cbrotli compresses and decompresses data with C-Brotli library.
+package cbrotli
+
+/*
+#include <stddef.h>
+#include <stdint.h>
+
+#include <brotli/decode.h>
+
+static BrotliDecoderResult DecompressStream(BrotliDecoderState* s,
+ uint8_t* out, size_t out_len,
+ const uint8_t* in, size_t in_len,
+ size_t* bytes_written,
+ size_t* bytes_consumed) {
+ size_t in_remaining = in_len;
+ size_t out_remaining = out_len;
+ BrotliDecoderResult result = BrotliDecoderDecompressStream(
+ s, &in_remaining, &in, &out_remaining, &out, NULL);
+ *bytes_written = out_len - out_remaining;
+ *bytes_consumed = in_len - in_remaining;
+ return result;
+}
+*/
+import "C"
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "io/ioutil"
+)
+
+type decodeError C.BrotliDecoderErrorCode
+
+func (err decodeError) Error() string {
+ return "cbrotli: " +
+ C.GoString(C.BrotliDecoderErrorString(C.BrotliDecoderErrorCode(err)))
+}
+
+var errExcessiveInput = errors.New("cbrotli: excessive input")
+var errInvalidState = errors.New("cbrotli: invalid state")
+var errReaderClosed = errors.New("cbrotli: Reader is closed")
+
+// Reader implements io.ReadCloser by reading Brotli-encoded data from an
+// underlying Reader.
+type Reader struct {
+ src io.Reader
+ state *C.BrotliDecoderState
+ buf []byte // scratch space for reading from src
+ in []byte // current chunk to decode; usually aliases buf
+}
+
+// readBufSize is a "good" buffer size that avoids excessive round-trips
+// between C and Go but doesn't waste too much memory on buffering.
+// It is arbitrarily chosen to be equal to the constant used in io.Copy.
+const readBufSize = 32 * 1024
+
+// NewReader initializes new Reader instance.
+// Close MUST be called to free resources.
+func NewReader(src io.Reader) *Reader {
+ return &Reader{
+ src: src,
+ state: C.BrotliDecoderCreateInstance(nil, nil, nil),
+ buf: make([]byte, readBufSize),
+ }
+}
+
+// Close implements io.Closer. Close MUST be invoked to free native resources.
+func (r *Reader) Close() error {
+ if r.state == nil {
+ return errReaderClosed
+ }
+ // Close despite the state; i.e. there might be some unread decoded data.
+ C.BrotliDecoderDestroyInstance(r.state)
+ r.state = nil
+ return nil
+}
+
+func (r *Reader) Read(p []byte) (n int, err error) {
+ if int(C.BrotliDecoderHasMoreOutput(r.state)) == 0 && len(r.in) == 0 {
+ m, readErr := r.src.Read(r.buf)
+ if m == 0 {
+ // If readErr is `nil`, we just proxy underlying stream behavior.
+ return 0, readErr
+ }
+ r.in = r.buf[:m]
+ }
+
+ if len(p) == 0 {
+ return 0, nil
+ }
+
+ for {
+ var written, consumed C.size_t
+ var data *C.uint8_t
+ if len(r.in) != 0 {
+ data = (*C.uint8_t)(&r.in[0])
+ }
+ result := C.DecompressStream(r.state,
+ (*C.uint8_t)(&p[0]), C.size_t(len(p)),
+ data, C.size_t(len(r.in)),
+ &written, &consumed)
+ r.in = r.in[int(consumed):]
+ n = int(written)
+
+ switch result {
+ case C.BROTLI_DECODER_RESULT_SUCCESS:
+ if len(r.in) > 0 {
+ return n, errExcessiveInput
+ }
+ return n, nil
+ case C.BROTLI_DECODER_RESULT_ERROR:
+ return n, decodeError(C.BrotliDecoderGetErrorCode(r.state))
+ case C.BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
+ if n == 0 {
+ return 0, io.ErrShortBuffer
+ }
+ return n, nil
+ case C.BROTLI_DECODER_NEEDS_MORE_INPUT:
+ }
+
+ if len(r.in) != 0 {
+ return 0, errInvalidState
+ }
+
+ // Calling r.src.Read may block. Don't block if we have data to return.
+ if n > 0 {
+ return n, nil
+ }
+
+ // Top off the buffer.
+ encN, err := r.src.Read(r.buf)
+ if encN == 0 {
+ // Not enough data to complete decoding.
+ if err == io.EOF {
+ return 0, io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ r.in = r.buf[:encN]
+ }
+
+ return n, nil
+}
+
+// Decode decodes Brotli encoded data.
+func Decode(encodedData []byte) ([]byte, error) {
+ r := &Reader{
+ src: bytes.NewReader(nil),
+ state: C.BrotliDecoderCreateInstance(nil, nil, nil),
+ buf: make([]byte, 4), // arbitrarily small but nonzero so that r.src.Read returns io.EOF
+ in: encodedData,
+ }
+ defer r.Close()
+ return ioutil.ReadAll(r)
+}
diff --git a/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/writer.go b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/writer.go
new file mode 100644
index 000000000..9fa75ab06
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/go/cbrotli/writer.go
@@ -0,0 +1,159 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Distributed under MIT license.
+// See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+
+package cbrotli
+
+/*
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <brotli/encode.h>
+
+struct CompressStreamResult {
+ size_t bytes_consumed;
+ const uint8_t* output_data;
+ size_t output_data_size;
+ int success;
+ int has_more;
+};
+
+static struct CompressStreamResult CompressStream(
+ BrotliEncoderState* s, BrotliEncoderOperation op,
+ const uint8_t* data, size_t data_size) {
+ struct CompressStreamResult result;
+ size_t available_in = data_size;
+ const uint8_t* next_in = data;
+ size_t available_out = 0;
+ result.success = BrotliEncoderCompressStream(s, op,
+ &available_in, &next_in, &available_out, 0, 0) ? 1 : 0;
+ result.bytes_consumed = data_size - available_in;
+ result.output_data = 0;
+ result.output_data_size = 0;
+ if (result.success) {
+ result.output_data = BrotliEncoderTakeOutput(s, &result.output_data_size);
+ }
+ result.has_more = BrotliEncoderHasMoreOutput(s) ? 1 : 0;
+ return result;
+}
+*/
+import "C"
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "unsafe"
+)
+
+// WriterOptions configures Writer.
+type WriterOptions struct {
+ // Quality controls the compression-speed vs compression-density trade-offs.
+ // The higher the quality, the slower the compression. Range is 0 to 11.
+ Quality int
+ // LGWin is the base 2 logarithm of the sliding window size.
+ // Range is 10 to 24. 0 indicates automatic configuration based on Quality.
+ LGWin int
+}
+
+// Writer implements io.WriteCloser by writing Brotli-encoded data to an
+// underlying Writer.
+type Writer struct {
+ dst io.Writer
+ state *C.BrotliEncoderState
+ buf, encoded []byte
+}
+
+var (
+ errEncode = errors.New("cbrotli: encode error")
+ errWriterClosed = errors.New("cbrotli: Writer is closed")
+)
+
+// NewWriter initializes new Writer instance.
+// Close MUST be called to free resources.
+func NewWriter(dst io.Writer, options WriterOptions) *Writer {
+ state := C.BrotliEncoderCreateInstance(nil, nil, nil)
+ C.BrotliEncoderSetParameter(
+ state, C.BROTLI_PARAM_QUALITY, (C.uint32_t)(options.Quality))
+ if options.LGWin > 0 {
+ C.BrotliEncoderSetParameter(
+ state, C.BROTLI_PARAM_LGWIN, (C.uint32_t)(options.LGWin))
+ }
+ return &Writer{
+ dst: dst,
+ state: state,
+ }
+}
+
+func (w *Writer) writeChunk(p []byte, op C.BrotliEncoderOperation) (n int, err error) {
+ if w.state == nil {
+ return 0, errWriterClosed
+ }
+
+ for {
+ var data *C.uint8_t
+ if len(p) != 0 {
+ data = (*C.uint8_t)(&p[0])
+ }
+ result := C.CompressStream(w.state, op, data, C.size_t(len(p)))
+ if result.success == 0 {
+ return n, errEncode
+ }
+ p = p[int(result.bytes_consumed):]
+ n += int(result.bytes_consumed)
+
+ length := int(result.output_data_size)
+ if length != 0 {
+ // It is a workaround for non-copying-wrapping of native memory.
+ // C-encoder never pushes output block longer than ((2 << 25) + 502).
+ // TODO: use natural wrapper, when it becomes available, see
+ // https://golang.org/issue/13656.
+ output := (*[1 << 30]byte)(unsafe.Pointer(result.output_data))[:length:length]
+ _, err = w.dst.Write(output)
+ if err != nil {
+ return n, err
+ }
+ }
+ if len(p) == 0 && result.has_more == 0 {
+ return n, nil
+ }
+ }
+}
+
+// Flush outputs encoded data for all input provided to Write. The resulting
+// output can be decoded to match all input before Flush, but the stream is
+// not yet complete until after Close.
+// Flush has a negative impact on compression.
+func (w *Writer) Flush() error {
+ _, err := w.writeChunk(nil, C.BROTLI_OPERATION_FLUSH)
+ return err
+}
+
+// Close flushes remaining data to the decorated writer and frees C resources.
+func (w *Writer) Close() error {
+ // If stream is already closed, it is reported by `writeChunk`.
+ _, err := w.writeChunk(nil, C.BROTLI_OPERATION_FINISH)
+ // C-Brotli tolerates `nil` pointer here.
+ C.BrotliEncoderDestroyInstance(w.state)
+ w.state = nil
+ return err
+}
+
+// Write implements io.Writer. Flush or Close must be called to ensure that the
+// encoded bytes are actually flushed to the underlying Writer.
+func (w *Writer) Write(p []byte) (n int, err error) {
+ return w.writeChunk(p, C.BROTLI_OPERATION_PROCESS)
+}
+
+// Encode returns content encoded with Brotli.
+func Encode(content []byte, options WriterOptions) ([]byte, error) {
+ var buf bytes.Buffer
+ writer := NewWriter(&buf, options)
+ _, err := writer.Write(content)
+ if closeErr := writer.Close(); err == nil {
+ err = closeErr
+ }
+ return buf.Bytes(), err
+}