-
Notifications
You must be signed in to change notification settings - Fork 290
/
namespace.go
158 lines (129 loc) · 4.26 KB
/
namespace.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package namespace
import (
"bytes"
"fmt"
)
type Namespace struct {
Version uint8
ID []byte
}
// New returns a new namespace with the provided version and id.
func New(version uint8, id []byte) (Namespace, error) {
err := validateVersion(version)
if err != nil {
return Namespace{}, err
}
err = validateID(version, id)
if err != nil {
return Namespace{}, err
}
return Namespace{
Version: version,
ID: id,
}, nil
}
// MustNew returns a new namespace with the provided version and id. It panics
// if the provided version or id are not supported.
func MustNew(version uint8, id []byte) Namespace {
ns, err := New(version, id)
if err != nil {
panic(err)
}
return ns
}
// MustNewV0 returns a new namespace with version 0 and the provided id. This
// function panics if the provided id is not exactly NamespaceVersionZeroIDSize bytes.
func MustNewV0(id []byte) Namespace {
if len(id) != NamespaceVersionZeroIDSize {
panic(fmt.Sprintf("invalid namespace id length: %v must be %v", len(id), NamespaceVersionZeroIDSize))
}
ns, err := New(NamespaceVersionZero, append(NamespaceVersionZeroPrefix, id...))
if err != nil {
panic(err)
}
return ns
}
// From returns a namespace from the provided byte slice.
func From(b []byte) (Namespace, error) {
if len(b) != NamespaceSize {
return Namespace{}, fmt.Errorf("invalid namespace length: %v must be %v", len(b), NamespaceSize)
}
rawVersion := b[0]
rawNamespace := b[1:]
return New(rawVersion, rawNamespace)
}
// Bytes returns this namespace as a byte slice.
func (n Namespace) Bytes() []byte {
return append([]byte{n.Version}, n.ID...)
}
// ValidateBlobNamespace returns an error if this namespace is not a valid blob namespace.
func (n Namespace) ValidateBlobNamespace() error {
if n.IsReserved() {
return fmt.Errorf("invalid blob namespace: %v cannot use a reserved namespace ID, want > %v", n.Bytes(), MaxReservedNamespace.Bytes())
}
if n.IsParityShares() {
return fmt.Errorf("invalid blob namespace: %v cannot use parity shares namespace ID", n.Bytes())
}
if n.IsTailPadding() {
return fmt.Errorf("invalid blob namespace: %v cannot use tail padding namespace ID", n.Bytes())
}
return nil
}
// validateVersion returns an error if the version is not supported.
func validateVersion(version uint8) error {
if version != NamespaceVersionZero && version != NamespaceVersionMax {
return fmt.Errorf("unsupported namespace version %v", version)
}
return nil
}
// validateID returns an error if the provided id does not meet the requirements
// for the provided version.
func validateID(version uint8, id []byte) error {
if len(id) != NamespaceIDSize {
return fmt.Errorf("unsupported namespace id length: id %v must be %v bytes but it was %v bytes", id, NamespaceIDSize, len(id))
}
if version == NamespaceVersionZero && !bytes.HasPrefix(id, NamespaceVersionZeroPrefix) {
return fmt.Errorf("unsupported namespace id with version %v. ID %v must start with %v leading zeros", version, id, len(NamespaceVersionZeroPrefix))
}
return nil
}
func (n Namespace) IsReserved() bool {
return bytes.Compare(n.Bytes(), MaxReservedNamespace.Bytes()) < 1
}
func (n Namespace) IsParityShares() bool {
return bytes.Equal(n.Bytes(), ParitySharesNamespace.Bytes())
}
func (n Namespace) IsTailPadding() bool {
return bytes.Equal(n.Bytes(), TailPaddingNamespace.Bytes())
}
func (n Namespace) IsReservedPadding() bool {
return bytes.Equal(n.Bytes(), ReservedPaddingNamespace.Bytes())
}
func (n Namespace) IsTx() bool {
return bytes.Equal(n.Bytes(), TxNamespace.Bytes())
}
func (n Namespace) IsPayForBlob() bool {
return bytes.Equal(n.Bytes(), PayForBlobNamespace.Bytes())
}
func (n Namespace) Repeat(times int) []Namespace {
ns := make([]Namespace, times)
for i := 0; i < times; i++ {
ns[i] = n
}
return ns
}
func (n Namespace) Equals(n2 Namespace) bool {
return bytes.Equal(n.Bytes(), n2.Bytes())
}
func (n Namespace) IsLessThan(n2 Namespace) bool {
return bytes.Compare(n.Bytes(), n2.Bytes()) == -1
}
func (n Namespace) IsLessOrEqualThan(n2 Namespace) bool {
return bytes.Compare(n.Bytes(), n2.Bytes()) < 1
}
func (n Namespace) IsGreaterThan(n2 Namespace) bool {
return bytes.Compare(n.Bytes(), n2.Bytes()) == 1
}
func (n Namespace) IsGreaterOrEqualThan(n2 Namespace) bool {
return bytes.Compare(n.Bytes(), n2.Bytes()) > -1
}