forked from iotaledger/iota.go
/
serializable.go
234 lines (199 loc) · 7.66 KB
/
serializable.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package iotago
import (
"bytes"
"encoding/json"
"fmt"
"sort"
)
// Serializable is something which knows how to serialize/deserialize itself from/into bytes.
// This is almost analogous to BinaryMarshaler/BinaryUnmarshaler.
type Serializable interface {
json.Marshaler
json.Unmarshaler
// Deserialize deserializes the given data (by copying) into the object and returns the amount of bytes consumed from data.
// If the passed data is not big enough for deserialization, an error must be returned.
// During deserialization additional validation may be performed if the given modes are set.
Deserialize(data []byte, deSeriMode DeSerializationMode) (int, error)
// Serialize returns a serialized byte representation.
// This function does not check the serialized data for validity.
// During serialization additional validation may be performed if the given modes are set.
Serialize(deSeriMode DeSerializationMode) ([]byte, error)
}
// Serializables is a slice of Serializable.
type Serializables []Serializable
// SerializableSelectorFunc is a function that given a type byte, returns an empty instance of the given underlying type.
// If the type doesn't resolve, an error is returned.
type SerializableSelectorFunc func(ty uint32) (Serializable, error)
// DeSerializationMode defines the mode of de/serialization.
type DeSerializationMode byte
const (
// Instructs de/serialization to perform no validation.
DeSeriModeNoValidation DeSerializationMode = 0
// Instructs de/serialization to perform validation.
DeSeriModePerformValidation DeSerializationMode = 1 << 0
// Instructs de/deserialization to perform ordering of certain struct arrays by their lexical serialized form.
DeSeriModePerformLexicalOrdering DeSerializationMode = 1 << 1
)
// HasMode checks whether the de/serialization mode includes the given mode.
func (sm DeSerializationMode) HasMode(mode DeSerializationMode) bool {
return sm&mode > 0
}
// ArrayValidationMode defines the mode of array validation.
type ArrayValidationMode byte
const (
// Instructs the array validation to perform no validation.
ArrayValidationModeNone ArrayValidationMode = 0
// Instructs the array validation to check for duplicates.
ArrayValidationModeNoDuplicates ArrayValidationMode = 1 << 0
// Instructs the array validation to check for lexical order.
ArrayValidationModeLexicalOrdering ArrayValidationMode = 1 << 1
)
// HasMode checks whether the array element validation mode includes the given mode.
func (av ArrayValidationMode) HasMode(mode ArrayValidationMode) bool {
return av&mode > 0
}
// ArrayRules defines rules around a to be deserialized array.
// Min and Max at 0 define an unbounded array.
type ArrayRules struct {
// The min array bound.
Min uint16
// The max array bound.
Max uint16
// The mode of validation.
ValidationMode ArrayValidationMode
}
// CheckBounds checks whether the given count violates the array bounds.
func (ar *ArrayRules) CheckBounds(count uint16) error {
if ar.Min != 0 && count < ar.Min {
return fmt.Errorf("%w: min is %d but count is %d", ErrArrayValidationMinElementsNotReached, ar.Min, count)
}
if ar.Max != 0 && count > ar.Max {
return fmt.Errorf("%w: max is %d but count is %d", ErrArrayValidationMaxElementsExceeded, ar.Max, count)
}
return nil
}
// ElementValidationFunc is a function which runs during array validation (e.g. lexical ordering).
type ElementValidationFunc func(index int, next []byte) error
// ElementUniqueValidator returns an ElementValidationFunc which returns an error if the given element is not unique.
func (ar *ArrayRules) ElementUniqueValidator() ElementValidationFunc {
set := map[string]int{}
return func(index int, next []byte) error {
k := string(next)
if j, has := set[k]; has {
return fmt.Errorf("%w: element %d and %d are duplicates", ErrArrayValidationViolatesUniqueness, j, index)
}
set[k] = index
return nil
}
}
// LexicalOrderValidator returns an ElementValidationFunc which returns an error if the given byte slices
// are not ordered lexicographically.
func (ar *ArrayRules) LexicalOrderValidator() ElementValidationFunc {
var prev []byte
var prevIndex int
return func(index int, next []byte) error {
switch {
case prev == nil:
prev = next
prevIndex = index
case bytes.Compare(prev, next) > 0:
return fmt.Errorf("%w: element %d should have been before element %d", ErrArrayValidationOrderViolatesLexicalOrder, index, prevIndex)
default:
prev = next
prevIndex = index
}
return nil
}
}
// LexicalOrderWithoutDupsValidator returns an ElementValidationFunc which returns an error if the given byte slices
// are not ordered lexicographically or any elements are duplicated.
func (ar *ArrayRules) LexicalOrderWithoutDupsValidator() ElementValidationFunc {
var prev []byte
var prevIndex int
return func(index int, next []byte) error {
if prev == nil {
prev = next
prevIndex = index
return nil
}
switch bytes.Compare(prev, next) {
case 1:
return fmt.Errorf("%w: element %d should have been before element %d", ErrArrayValidationOrderViolatesLexicalOrder, index, prevIndex)
case 0:
// dup
return fmt.Errorf("%w: element %d and %d are duplicates", ErrArrayValidationViolatesUniqueness, index, prevIndex)
}
prev = next
prevIndex = index
return nil
}
}
// ElementValidationFunc returns a new ElementValidationFunc according to the given mode.
func (ar *ArrayRules) ElementValidationFunc(mode ArrayValidationMode) ElementValidationFunc {
var arrayElementValidator ElementValidationFunc
switch mode {
case ArrayValidationModeNone:
case ArrayValidationModeNoDuplicates:
arrayElementValidator = ar.ElementUniqueValidator()
case ArrayValidationModeLexicalOrdering:
arrayElementValidator = ar.LexicalOrderValidator()
case ArrayValidationModeNoDuplicates | ArrayValidationModeLexicalOrdering:
arrayElementValidator = ar.LexicalOrderWithoutDupsValidator()
default:
panic(ErrUnknownArrayValidationMode)
}
return arrayElementValidator
}
// LexicalOrderedByteSlices are byte slices ordered in lexical order.
type LexicalOrderedByteSlices [][]byte
func (l LexicalOrderedByteSlices) Len() int {
return len(l)
}
func (l LexicalOrderedByteSlices) Less(i, j int) bool {
return bytes.Compare(l[i], l[j]) < 0
}
func (l LexicalOrderedByteSlices) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
// LexicalOrdered32ByteArrays are 32 byte arrays ordered in lexical order.
type LexicalOrdered32ByteArrays [][32]byte
func (l LexicalOrdered32ByteArrays) Len() int {
return len(l)
}
func (l LexicalOrdered32ByteArrays) Less(i, j int) bool {
return bytes.Compare(l[i][:], l[j][:]) < 0
}
func (l LexicalOrdered32ByteArrays) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
// RemoveDupsAndSortByLexicalOrderArrayOf32Bytes returns a new SliceOfArraysOf32Bytes sorted by lexical order and without duplicates.
func RemoveDupsAndSortByLexicalOrderArrayOf32Bytes(slice SliceOfArraysOf32Bytes) SliceOfArraysOf32Bytes {
seen := make(map[string]struct{})
orderedArray := make(LexicalOrdered32ByteArrays, len(slice))
uniqueElements := 0
for _, v := range slice {
k := string(v[:])
if _, has := seen[k]; has {
continue
}
seen[k] = struct{}{}
orderedArray[uniqueElements] = v
uniqueElements++
}
orderedArray = orderedArray[:uniqueElements]
sort.Sort(orderedArray)
return SliceOfArraysOf32Bytes(orderedArray)
}
// SortedSerializables are Serializables sorted by their serialized form.
type SortedSerializables Serializables
func (ss SortedSerializables) Len() int {
return len(ss)
}
func (ss SortedSerializables) Less(i, j int) bool {
iData, _ := ss[i].Serialize(DeSeriModeNoValidation)
jData, _ := ss[j].Serialize(DeSeriModeNoValidation)
return bytes.Compare(iData, jData) < 0
}
func (ss SortedSerializables) Swap(i, j int) {
ss[i], ss[j] = ss[j], ss[i]
}