Add a new generic container registry client via a new `container` package. Use this to create a command line utility as well as a new upload target for container registries. The code uses the github.com/containers/* project and packages to interact with container registires that is also used by skopeo, podman et al. One if the dependencies is `proglottis/gpgme` that is using cgo to bind libgpgme, so we have to add the corresponding devel package to the BuildRequires as well as installing it on CI. Checks will follow later via an integration test.
116 lines
2.7 KiB
Go
116 lines
2.7 KiB
Go
// Copyright 2014-2021 Ulrich Kunitz. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package lzma
|
|
|
|
import "errors"
|
|
|
|
// maxPosBits defines the number of bits of the position value that are used to
|
|
// to compute the posState value. The value is used to select the tree codec
|
|
// for length encoding and decoding.
|
|
const maxPosBits = 4
|
|
|
|
// minMatchLen and maxMatchLen give the minimum and maximum values for
|
|
// encoding and decoding length values. minMatchLen is also used as base
|
|
// for the encoded length values.
|
|
const (
|
|
minMatchLen = 2
|
|
maxMatchLen = minMatchLen + 16 + 256 - 1
|
|
)
|
|
|
|
// lengthCodec support the encoding of the length value.
|
|
type lengthCodec struct {
|
|
choice [2]prob
|
|
low [1 << maxPosBits]treeCodec
|
|
mid [1 << maxPosBits]treeCodec
|
|
high treeCodec
|
|
}
|
|
|
|
// deepcopy initializes the lc value as deep copy of the source value.
|
|
func (lc *lengthCodec) deepcopy(src *lengthCodec) {
|
|
if lc == src {
|
|
return
|
|
}
|
|
lc.choice = src.choice
|
|
for i := range lc.low {
|
|
lc.low[i].deepcopy(&src.low[i])
|
|
}
|
|
for i := range lc.mid {
|
|
lc.mid[i].deepcopy(&src.mid[i])
|
|
}
|
|
lc.high.deepcopy(&src.high)
|
|
}
|
|
|
|
// init initializes a new length codec.
|
|
func (lc *lengthCodec) init() {
|
|
for i := range lc.choice {
|
|
lc.choice[i] = probInit
|
|
}
|
|
for i := range lc.low {
|
|
lc.low[i] = makeTreeCodec(3)
|
|
}
|
|
for i := range lc.mid {
|
|
lc.mid[i] = makeTreeCodec(3)
|
|
}
|
|
lc.high = makeTreeCodec(8)
|
|
}
|
|
|
|
// Encode encodes the length offset. The length offset l can be compute by
|
|
// subtracting minMatchLen (2) from the actual length.
|
|
//
|
|
// l = length - minMatchLen
|
|
//
|
|
func (lc *lengthCodec) Encode(e *rangeEncoder, l uint32, posState uint32,
|
|
) (err error) {
|
|
if l > maxMatchLen-minMatchLen {
|
|
return errors.New("lengthCodec.Encode: l out of range")
|
|
}
|
|
if l < 8 {
|
|
if err = lc.choice[0].Encode(e, 0); err != nil {
|
|
return
|
|
}
|
|
return lc.low[posState].Encode(e, l)
|
|
}
|
|
if err = lc.choice[0].Encode(e, 1); err != nil {
|
|
return
|
|
}
|
|
if l < 16 {
|
|
if err = lc.choice[1].Encode(e, 0); err != nil {
|
|
return
|
|
}
|
|
return lc.mid[posState].Encode(e, l-8)
|
|
}
|
|
if err = lc.choice[1].Encode(e, 1); err != nil {
|
|
return
|
|
}
|
|
if err = lc.high.Encode(e, l-16); err != nil {
|
|
return
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Decode reads the length offset. Add minMatchLen to compute the actual length
|
|
// to the length offset l.
|
|
func (lc *lengthCodec) Decode(d *rangeDecoder, posState uint32,
|
|
) (l uint32, err error) {
|
|
var b uint32
|
|
if b, err = lc.choice[0].Decode(d); err != nil {
|
|
return
|
|
}
|
|
if b == 0 {
|
|
l, err = lc.low[posState].Decode(d)
|
|
return
|
|
}
|
|
if b, err = lc.choice[1].Decode(d); err != nil {
|
|
return
|
|
}
|
|
if b == 0 {
|
|
l, err = lc.mid[posState].Decode(d)
|
|
l += 8
|
|
return
|
|
}
|
|
l, err = lc.high.Decode(d)
|
|
l += 16
|
|
return
|
|
}
|