/
util.go
75 lines (66 loc) · 2.55 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
package util
import (
"encoding/binary"
"fmt"
"github.com/golang/protobuf/proto"
)
// IsNil returns true if b is either nil or zero-length array
func IsNil(b []byte) bool {
return b == nil || len(b) == 0
}
// NotNil returns true if b is a non-zero length array
func NotNil(b []byte) bool {
return !IsNil(b)
}
// EncodeOrderPreservingVarUint64 returns a byte-representation for a uint64 number such that
// all zero-bits starting bytes are trimmed in order to reduce the length of the array
// For preserving the order in a default bytes-comparision, first byte contains the number of remaining bytes.
// The presence of first byte also allows to use the returned bytes as part of other larger byte array such as a
// composite-key representation in db
func EncodeOrderPreservingVarUint64(number uint64) []byte {
bytes := make([]byte, 8)
binary.BigEndian.PutUint64(bytes, number)
startingIndex := 0
size := 0
for i, b := range bytes {
if b != 0x00 {
startingIndex = i
size = 8 - i
break
}
}
sizeBytes := proto.EncodeVarint(uint64(size))
if len(sizeBytes) > 1 {
panic(fmt.Errorf("[]sizeBytes should not be more than one byte because the max number it needs to hold is 8. size=%d", size))
}
encodedBytes := make([]byte, size+1)
encodedBytes[0] = sizeBytes[0]
copy(encodedBytes[1:], bytes[startingIndex:])
return encodedBytes
}
// DecodeOrderPreservingVarUint64 decodes the number from the bytes obtained from method 'EncodeOrderPreservingVarUint64'.
// Also, returns the number of bytes that are consumed in the process
func DecodeOrderPreservingVarUint64(bytes []byte) (uint64, int) {
s, _ := proto.DecodeVarint(bytes)
size := int(s)
decodedBytes := make([]byte, 8)
copy(decodedBytes[8-size:], bytes[1:size+1])
numBytesConsumed := size + 1
return binary.BigEndian.Uint64(decodedBytes), numBytesConsumed
}