github.com/linuxboot/fiano@v1.2.0/pkg/compression/lzma.go (about)

     1  // Copyright 2018 the LinuxBoot Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package compression
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  
    11  	"github.com/ulikunitz/xz/lzma"
    12  )
    13  
    14  // Mapping from compression level to dictionary size.
    15  var lzmaDictCapExps = []uint{18, 20, 21, 22, 22, 23, 23, 24, 25, 26}
    16  var compressionLevel = 7
    17  
    18  // LZMA implements Compressor and uses a Go-based implementation.
    19  type LZMA struct{}
    20  
    21  // Name returns the type of compression employed.
    22  func (c *LZMA) Name() string {
    23  	return "LZMA"
    24  }
    25  
    26  // Decode decodes a byte slice of LZMA data.
    27  func (c *LZMA) Decode(encodedData []byte) ([]byte, error) {
    28  	r, err := lzma.NewReader(bytes.NewBuffer(encodedData))
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	return io.ReadAll(r)
    33  }
    34  
    35  // Encode encodes a byte slice with LZMA.
    36  func (c *LZMA) Encode(decodedData []byte) ([]byte, error) {
    37  	// These options are supported by the xz's LZMA command and EDK2's LZMA.
    38  	wc := lzma.WriterConfig{
    39  		SizeInHeader: true,
    40  		Size:         int64(len(decodedData)),
    41  		EOSMarker:    false,
    42  		Properties:   &lzma.Properties{LC: 3, LP: 0, PB: 2},
    43  		DictCap:      1 << lzmaDictCapExps[compressionLevel],
    44  	}
    45  	if err := wc.Verify(); err != nil {
    46  		return nil, err
    47  	}
    48  	buf := &bytes.Buffer{}
    49  	w, err := wc.NewWriter(buf)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	if _, err := io.Copy(w, bytes.NewBuffer(decodedData)); err != nil {
    54  		return nil, err
    55  	}
    56  	if err := w.Close(); err != nil {
    57  		return nil, err
    58  	}
    59  	return buf.Bytes(), nil
    60  }