| Index: common/data/base128/base128.go
|
| diff --git a/common/data/base128/base128.go b/common/data/base128/base128.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..81b62673fd067eb0c8e9f06079ae74b3c63d977c
|
| --- /dev/null
|
| +++ b/common/data/base128/base128.go
|
| @@ -0,0 +1,108 @@
|
| +// Copyright 2016 The LUCI Authors. All rights reserved.
|
| +// Use of this source code is governed under the Apache License, Version 2.0
|
| +// that can be found in the LICENSE file.
|
| +
|
| +// Package base128 implements base128 encoding and decoding.
|
| +//
|
| +// Encoded results are UTF8-safe, and will retain the same memcmp sorting
|
| +// properties of the input data.
|
| +package base128
|
| +
|
| +import "errors"
|
| +
|
| +var (
|
| + // ErrLength is returned from the Decode* methods if the input has an
|
| + // impossible length.
|
| + ErrLength = errors.New("base128: invalid length base128 string")
|
| +
|
| + // ErrBit is returned from the Decode* methods if the input has a byte with
|
| + // the high-bit set (e.g. 0x80). This will never be the case for strings
|
| + // produced from the Encode* methods in this package.
|
| + ErrBit = errors.New("base128: high bit set in base128 string")
|
| +)
|
| +
|
| +// Encode encodes src into EncodedLen(len(src)) bytes of dst. As a convenience,
|
| +// it returns the number of bytes written to dst, but this value is always
|
| +// EncodedLen(len(src)).
|
| +//
|
| +// Encode implements base128 encoding.
|
| +func Encode(dst, src []byte) int {
|
| + ret := EncodedLen(len(src))
|
| + if len(dst) < ret {
|
| + panic("dst has insufficient length")
|
| + }
|
| + dst = dst[:0]
|
| + whichByte := uint(1)
|
| + bufByte := byte(0)
|
| + for _, v := range src {
|
| + dst = append(dst, bufByte|(v>>whichByte))
|
| + bufByte = (v&(1<<whichByte) - 1) << (7 - whichByte)
|
| + if whichByte == 7 {
|
| + dst = append(dst, bufByte)
|
| + bufByte = 0
|
| + whichByte = 0
|
| + }
|
| + whichByte++
|
| + }
|
| + dst = append(dst, bufByte)
|
| + return ret
|
| +}
|
| +
|
| +// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
|
| +// number of bytes written to dst.
|
| +//
|
| +// If Decode encounters invalid input, it returns an error describing the
|
| +// failure.
|
| +func Decode(dst, src []byte) (int, error) {
|
| + dLen := DecodedLen(len(src))
|
| + if EncodedLen(dLen) != len(src) {
|
| + return 0, ErrLength
|
| + }
|
| + if len(dst) < dLen {
|
| + panic("dst has insufficient length")
|
| + }
|
| + dst = dst[:0]
|
| + whichByte := uint(1)
|
| + bufByte := byte(0)
|
| + for _, v := range src {
|
| + if (v & 0x80) != 0 {
|
| + return len(dst), ErrBit
|
| + }
|
| + if whichByte > 1 {
|
| + dst = append(dst, bufByte|(v>>(8-whichByte)))
|
| + }
|
| + bufByte = v << whichByte
|
| + if whichByte == 8 {
|
| + whichByte = 0
|
| + }
|
| + whichByte++
|
| + }
|
| + return len(dst), nil
|
| +}
|
| +
|
| +// DecodeString returns the bytes represented by the base128 string s.
|
| +func DecodeString(s string) ([]byte, error) {
|
| + src := []byte(s)
|
| + dst := make([]byte, DecodedLen(len(src)))
|
| + if _, err := Decode(dst, src); err != nil {
|
| + return nil, err
|
| + }
|
| + return dst, nil
|
| +}
|
| +
|
| +// DecodedLen returns the number of bytes `encLen` encoded bytes decodes to.
|
| +func DecodedLen(encLen int) int {
|
| + return (encLen * 7 / 8)
|
| +}
|
| +
|
| +// EncodedLen returns the number of bytes that `dataLen` bytes will encode to.
|
| +func EncodedLen(dataLen int) int {
|
| + return (((dataLen * 8) + 6) / 7)
|
| +}
|
| +
|
| +// EncodeToString returns the base128 encoding of src.
|
| +func EncodeToString(src []byte) string {
|
| + dst := make([]byte, EncodedLen(len(src)))
|
| + Encode(dst, src)
|
| + return string(dst)
|
| +}
|
|
|