Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | |
| 3 // that can be found in the LICENSE file. | |
| 4 | |
| 5 // Package base128 implements base128 encoding and decoding. | |
| 6 // | |
| 7 // Encoded results are UTF8-safe, and will retain the same memcmp sorting | |
| 8 // properties of the input data. | |
| 9 package base128 | |
| 10 | |
| 11 import "errors" | |
| 12 | |
| 13 var ( | |
| 14 // ErrLength is returned from the Decode* methods if the input has an | |
| 15 // impossible length. | |
| 16 ErrLength = errors.New("base128: invalid length base128 string") | |
| 17 | |
| 18 // ErrBit is returned from the Decode* methods if the input has a byte w ith | |
| 19 // the high-bit set (e.g. 0x80). This will never be the case for strings | |
| 20 // produced from the Encode* methods in this package. | |
| 21 ErrBit = errors.New("base128: high bit set in base128 string") | |
| 22 ) | |
| 23 | |
| 24 // Encode encodes src into EncodedLen(len(src)) bytes of dst. As a convenience, | |
| 25 // it returns the number of bytes written to dst, but this value is always | |
| 26 // EncodedLen(len(src)). | |
| 27 // | |
| 28 // Encode implements base128 encoding. | |
| 29 func Encode(dst, src []byte) int { | |
| 30 ret := EncodedLen(len(src)) | |
| 31 if cap(dst) < ret { | |
|
dnj
2016/11/29 02:03:13
I think capacity is misleading, and can lead to in
iannucci
2016/11/29 02:14:55
Done.
| |
| 32 panic("dst has insufficient capacity") | |
| 33 } | |
| 34 dst = dst[:0] | |
| 35 whichByte := 0 | |
|
dnj
2016/11/29 02:03:13
nit: Just make this a uint, and cycle 1..7 instead
iannucci
2016/11/29 02:14:55
Done.
| |
| 36 bufByte := byte(0) | |
| 37 for _, v := range src { | |
| 38 dst = append(dst, bufByte|(v>>uint(whichByte+1))) | |
| 39 bufByte = (v&(1<<uint(whichByte+1)) - 1) << uint(6-whichByte) | |
| 40 if whichByte == 6 { | |
| 41 dst = append(dst, bufByte) | |
| 42 bufByte = 0 | |
|
dnj
2016/11/29 02:03:13
Instead of using modulus below, just reset whichby
iannucci
2016/11/29 02:14:55
Done.
| |
| 43 } | |
| 44 whichByte = (whichByte + 1) % 7 | |
|
dnj
2016/11/29 02:03:13
whichByte += 1
iannucci
2016/11/29 02:14:55
Done.
| |
| 45 } | |
| 46 dst = append(dst, bufByte) | |
| 47 return ret | |
| 48 } | |
| 49 | |
| 50 // Decode decodes src into DecodedLen(len(src)) bytes, returning the actual | |
| 51 // number of bytes written to dst. | |
| 52 // | |
| 53 // If Decode encounters invalid input, it returns an error describing the | |
| 54 // failure. | |
| 55 func Decode(dst, src []byte) (int, error) { | |
| 56 dLen := DecodedLen(len(src)) | |
| 57 if EncodedLen(dLen) != len(src) { | |
| 58 return 0, ErrLength | |
| 59 } | |
| 60 if cap(dst) < dLen { | |
|
dnj
2016/11/29 02:03:13
Same RE cap, uint comments, etc.
iannucci
2016/11/29 02:14:55
Done.
| |
| 61 panic("dst has insufficient capacity") | |
| 62 } | |
| 63 dst = dst[:0] | |
| 64 whichByte := 0 | |
| 65 bufByte := byte(0) | |
| 66 for _, v := range src { | |
| 67 if (v & 0x80) != 0 { | |
| 68 return len(dst), ErrBit | |
| 69 } | |
| 70 if whichByte > 0 { | |
| 71 dst = append(dst, bufByte|(v>>uint(7-whichByte))) | |
| 72 } | |
| 73 bufByte = v << uint(whichByte+1) | |
| 74 whichByte = (whichByte + 1) % 8 | |
| 75 } | |
| 76 return len(dst), nil | |
| 77 } | |
| 78 | |
| 79 // DecodeString returns the bytes represented by the base128 string s. | |
| 80 func DecodeString(s string) ([]byte, error) { | |
| 81 src := []byte(s) | |
| 82 dst := make([]byte, DecodedLen(len(src))) | |
|
dnj
2016/11/29 02:03:13
Doing "DecodedLen" calculation twice here. Fall th
iannucci
2016/11/29 02:14:55
meh
| |
| 83 _, err := Decode(dst, src) | |
|
dnj
2016/11/29 02:03:13
nit: if _, err := ...; err != nil {}
iannucci
2016/11/29 02:14:55
Done.
| |
| 84 if err != nil { | |
| 85 return nil, err | |
| 86 } | |
| 87 return dst, nil | |
| 88 } | |
| 89 | |
| 90 // DecodedLen returns the number of bytes `encLen` encoded bytes decodes to. | |
| 91 func DecodedLen(encLen int) int { | |
| 92 ret := (encLen / 8) * 7 | |
|
dnj
2016/11/29 02:03:13
Consider:
func DecodedLen(v int) int {
return (v
iannucci
2016/11/29 02:14:55
Done.
| |
| 93 if v := encLen % 8; v > 0 { | |
| 94 ret += v - 1 | |
| 95 } | |
| 96 return ret | |
| 97 } | |
| 98 | |
| 99 // EncodedLen returns the number of bytes that `dataLen` bytes will encode to. | |
| 100 func EncodedLen(dataLen int) int { | |
| 101 pre := ((dataLen * 8) - 1) | |
|
dnj
2016/11/29 02:03:13
Consider:
func EncodedLen(v int) int {
return (((
iannucci
2016/11/29 02:14:55
Done.
| |
| 102 if pre < 0 { | |
| 103 return 0 | |
| 104 } | |
| 105 return (pre / 7) + 1 | |
| 106 } | |
| 107 | |
| 108 // EncodeToString returns the base128 encoding of src. | |
| 109 func EncodeToString(src []byte) string { | |
| 110 dst := make([]byte, EncodedLen(len(src))) | |
|
dnj
2016/11/29 02:03:13
nit: you're calculating EncodedLen twice in Encode
iannucci
2016/11/29 02:14:55
meh
| |
| 111 Encode(dst, src) | |
| 112 return string(dst) | |
| 113 } | |
| OLD | NEW |