92 lines
3.3 KiB
Go
Vendored
92 lines
3.3 KiB
Go
Vendored
// Copyright 2014 The Cockroach Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
// implied. See the License for the specific language governing
|
|
// permissions and limitations under the License.
|
|
|
|
// This code originated from:
|
|
// https://github.com/cockroachdb/cockroach/blob/2dd65dde5d90c157f4b93f92502ca1063b904e1d/pkg/util/encoding/encoding.go
|
|
|
|
// Modified to not use pkg/errors
|
|
|
|
package scorch
|
|
|
|
import "fmt"
|
|
|
|
const (
|
|
// intMin is chosen such that the range of int tags does not overlap the
|
|
// ascii character set that is frequently used in testing.
|
|
intMin = 0x80 // 128
|
|
intMaxWidth = 8
|
|
intZero = intMin + intMaxWidth // 136
|
|
intSmall = intMax - intZero - intMaxWidth // 109
|
|
// intMax is the maximum int tag value.
|
|
intMax = 0xfd // 253
|
|
)
|
|
|
|
// encodeUvarintAscending encodes the uint64 value using a variable length
|
|
// (length-prefixed) representation. The length is encoded as a single
|
|
// byte indicating the number of encoded bytes (-8) to follow. See
|
|
// EncodeVarintAscending for rationale. The encoded bytes are appended to the
|
|
// supplied buffer and the final buffer is returned.
|
|
func encodeUvarintAscending(b []byte, v uint64) []byte {
|
|
switch {
|
|
case v <= intSmall:
|
|
return append(b, intZero+byte(v))
|
|
case v <= 0xff:
|
|
return append(b, intMax-7, byte(v))
|
|
case v <= 0xffff:
|
|
return append(b, intMax-6, byte(v>>8), byte(v))
|
|
case v <= 0xffffff:
|
|
return append(b, intMax-5, byte(v>>16), byte(v>>8), byte(v))
|
|
case v <= 0xffffffff:
|
|
return append(b, intMax-4, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
|
case v <= 0xffffffffff:
|
|
return append(b, intMax-3, byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8),
|
|
byte(v))
|
|
case v <= 0xffffffffffff:
|
|
return append(b, intMax-2, byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16),
|
|
byte(v>>8), byte(v))
|
|
case v <= 0xffffffffffffff:
|
|
return append(b, intMax-1, byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24),
|
|
byte(v>>16), byte(v>>8), byte(v))
|
|
default:
|
|
return append(b, intMax, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32),
|
|
byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
|
}
|
|
}
|
|
|
|
// decodeUvarintAscending decodes a varint encoded uint64 from the input
|
|
// buffer. The remainder of the input buffer and the decoded uint64
|
|
// are returned.
|
|
func decodeUvarintAscending(b []byte) ([]byte, uint64, error) {
|
|
if len(b) == 0 {
|
|
return nil, 0, fmt.Errorf("insufficient bytes to decode uvarint value")
|
|
}
|
|
length := int(b[0]) - intZero
|
|
b = b[1:] // skip length byte
|
|
if length <= intSmall {
|
|
return b, uint64(length), nil
|
|
}
|
|
length -= intSmall
|
|
if length < 0 || length > 8 {
|
|
return nil, 0, fmt.Errorf("invalid uvarint length of %d", length)
|
|
} else if len(b) < length {
|
|
return nil, 0, fmt.Errorf("insufficient bytes to decode uvarint value: %q", b)
|
|
}
|
|
var v uint64
|
|
// It is faster to range over the elements in a slice than to index
|
|
// into the slice on each loop iteration.
|
|
for _, t := range b[:length] {
|
|
v = (v << 8) | uint64(t)
|
|
}
|
|
return b[length:], v, nil
|
|
}
|