Skip to content

Commit 7d642e7

Browse files
committedAug 6, 2021
Breaking stuff and changing API
1 parent 7df27b2 commit 7d642e7

File tree

4 files changed

+287
-189
lines changed

4 files changed

+287
-189
lines changed
 

‎.gitignore

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
launch.json
2-
notes.md
1+
/launch.json
2+
/*.sublime-workspace
3+
4+
/notes.md

‎bool.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"reflect"
99
)
1010

11-
// SchemaOptions are preset in each schema, and specify if null the value is nullable and if the schema allows weakdecoding
1211
type BoolSchema struct {
1312
SchemaOptions
1413
}
@@ -51,7 +50,7 @@ func (s *BoolSchema) Encode(w io.Writer, i interface{}) error {
5150
// EncodeValue uses the schema to write the encoded value of v to the output stream
5251
func (s *BoolSchema) EncodeValue(w io.Writer, v reflect.Value) error {
5352

54-
ok, err := PreEncode(s, w, &v)
53+
ok, err := PreEncode(s.Nullable(), w, &v)
5554
if err != nil {
5655
return err
5756
}
@@ -98,7 +97,7 @@ func (s *BoolSchema) Decode(r io.Reader, i interface{}) error {
9897
// DecodeValue uses the schema to read the next encoded value from the input stream and store it in v
9998
func (s *BoolSchema) DecodeValue(r io.Reader, v reflect.Value) error {
10099

101-
v, err := PreDecode(s, r, v)
100+
v, err := PreDecode(s.Nullable(), r, v)
102101
if err != nil {
103102
return err
104103
}

‎date.go

+76-56
Original file line numberDiff line numberDiff line change
@@ -5,71 +5,93 @@ import (
55
"fmt"
66
"io"
77
"reflect"
8+
"strings"
89
"time"
910
)
1011

1112
// each custom type has a unique name an a unique UUID
12-
const dateSchemaName string = "date"
13-
const dateSchemaUUID byte = 01 // each custom type has a unique id
13+
const dateSchemaUUID byte = 1 // each custom type has a unique id
1414

15-
type dateSchema struct {
15+
type DateSchema struct {
1616
SchemaOptions
1717
}
1818

19-
// CustomSchema receivers --------------------------------------
19+
type dateSchemaGenerator struct{}
2020

21-
func (s *dateSchema) Name() string {
22-
return dateSchemaName
21+
func (sg dateSchemaGenerator) SchemaOfType(t reflect.Type) (Schema, error) {
22+
nullable := false
23+
24+
// Dereference pointer / interface types
25+
for k := t.Kind(); k == reflect.Ptr || k == reflect.Interface; k = t.Kind() {
26+
t = t.Elem()
27+
28+
// If we encounter any pointers, then we know this type is nullable
29+
nullable = true
30+
}
31+
32+
if t.Name() == "Time" && t.PkgPath() == "time" {
33+
s := DateSchema{}
34+
s.SetNullable(nullable)
35+
return s, nil
36+
}
37+
38+
return nil, nil
2339
}
2440

25-
func (s *dateSchema) UUID() byte {
26-
return dateSchemaUUID
41+
func (sg dateSchemaGenerator) DecodeSchema(io.Reader) (Schema, error) {
2742
}
2843

29-
func (s *dateSchema) Unmarshaljson(buf []byte) (Schema, error) {
44+
// s.SchemaOptions.nullable = (buf[*byteIndex]&SchemaNullBit == SchemaNullBit)
45+
46+
// // advance to the UUID
47+
// *byteIndex++
48+
// if buf[*byteIndex] != s.UUID() {
49+
// return nil, fmt.Errorf("invalid call to dateSchema(), invalid UUID encountered in binary schema")
50+
// }
51+
52+
// // advance past the UUID
53+
// *byteIndex++
54+
55+
// return s, nil
56+
// }
57+
58+
func (sg dateSchemaGenerator) DecodeSchemaJSON(io.Reader) (Schema, error) {
3059
fields := make(map[string]interface{})
3160

3261
err := json.Unmarshal(buf, &fields)
3362
if err != nil {
3463
return nil, err
3564
}
3665

37-
b, ok := fields["nullable"].(bool)
66+
// Parse `type`
67+
tmp, ok := fields["type"].(string)
3868
if !ok {
39-
return nil, fmt.Errorf("missing nullable field in JSON data while decoding dateSchema")
69+
return nil, fmt.Errorf("missing or invalid schema type")
4070
}
71+
typeStr := strings.ToLower(tmp)
4172

42-
s.SchemaOptions.nullable = b
43-
return s, nil
44-
}
45-
46-
func (s *dateSchema) UnMarshalSchemer(buf []byte, byteIndex *int) (Schema, error) {
47-
48-
s.SchemaOptions.nullable = (buf[*byteIndex]&SchemaNullBit == SchemaNullBit)
49-
50-
// advance to the UUID
51-
*byteIndex++
52-
if buf[*byteIndex] != s.UUID() {
53-
return nil, fmt.Errorf("invalid call to dateSchema(), invalid UUID encountered in binary schema")
73+
if typeStr != "date" {
74+
return nil, nil
5475
}
5576

56-
// advance past the UUID
57-
*byteIndex++
77+
// Parse `nullable`
78+
nullable := false
79+
tmp, found := fields["nullable"]
80+
if found {
81+
if b, ok := tmp.(bool); ok {
82+
nullable = b
83+
}
84+
return fmt.Errorf("nullable must be a boolean")
85+
}
5886

87+
s := DateSchema{}
88+
s.SetNullable(nullable)
5989
return s, nil
6090
}
6191

62-
// loop through all registered GO types
63-
func (s *dateSchema) ForType(t reflect.Type) Schema {
64-
if t.Name() == "Time" && t.PkgPath() == "time" {
65-
return s
66-
}
67-
return nil
68-
}
69-
7092
// Schema receivers --------------------------------------
7193

72-
func (s *dateSchema) GoType() reflect.Type {
94+
func (s *DateSchema) GoType() reflect.Type {
7395
var t time.Time
7496
retval := reflect.TypeOf(t)
7597

@@ -79,44 +101,42 @@ func (s *dateSchema) GoType() reflect.Type {
79101
return retval
80102
}
81103

82-
func (s *dateSchema) MarshalJSON() ([]byte, error) {
83-
104+
func (s *DateSchema) MarshalJSON() ([]byte, error) {
84105
return json.Marshal(map[string]interface{}{
85-
"type": "custom",
86-
"customtype": dateSchemaName,
87-
"nullable": s.Nullable(),
106+
"type": "date",
107+
"nullable": s.Nullable(),
88108
})
89109
}
90110

91111
// Bytes encodes the schema in a portable binary format
92-
func (s *dateSchema) MarshalSchemer() []byte {
112+
func (s *DateSchema) MarshalSchemer() ([]byte, error) {
93113

94-
const schemerDateSize byte = 1 + 1 // 1 byte for the schema + 1 bytes for the UUID
114+
// const schemerDateSize byte = 1 + 1 // 1 byte for the schema + 1 bytes for the UUID
95115

96-
// string schemas are 1 byte long
97-
var schema []byte = make([]byte, schemerDateSize)
116+
// // string schemas are 1 byte long
117+
// var schema []byte = make([]byte, schemerDateSize)
98118

99-
schema[0] = CustomSchemaMask
119+
// schema[0] = CustomSchemaMask
100120

101-
// The most signifiant bit indicates whether or not the type is nullable
102-
if s.Nullable() {
103-
schema[0] |= 0x80
104-
}
121+
// // The most signifiant bit indicates whether or not the type is nullable
122+
// if s.Nullable() {
123+
// schema[0] |= 0x80
124+
// }
105125

106-
schema[1] = dateSchemaUUID
126+
// schema[1] = dateSchemaUUID
107127

108-
return schema
128+
// return schema
109129
}
110130

111131
// Encode uses the schema to write the encoded value of i to the output stream
112-
func (s *dateSchema) Encode(w io.Writer, i interface{}) error {
132+
func (s *DateSchema) Encode(w io.Writer, i interface{}) error {
113133
return s.EncodeValue(w, reflect.ValueOf(i))
114134
}
115135

116136
// EncodeValue uses the schema to write the encoded value of he output stream
117-
func (s *dateSchema) EncodeValue(w io.Writer, v reflect.Value) error {
137+
func (s *DateSchema) EncodeValue(w io.Writer, v reflect.Value) error {
118138

119-
ok, err := PreEncode(s, w, &v)
139+
ok, err := PreEncode(s.Nullable(), w, &v)
120140
if err != nil {
121141
return err
122142
}
@@ -128,7 +148,7 @@ func (s *dateSchema) EncodeValue(w io.Writer, v reflect.Value) error {
128148
k := t.Kind()
129149

130150
if k != reflect.Struct || t.Name() != "Time" || t.PkgPath() != "time" {
131-
return fmt.Errorf("dateSchema only supports encoding time.Time values")
151+
return fmt.Errorf("DateSchema only supports encoding time.Time values")
132152
}
133153

134154
// call method UnixNano() on v, which is guarenteed to be a time.Time() due to the above check.
@@ -148,15 +168,15 @@ func (s *dateSchema) EncodeValue(w io.Writer, v reflect.Value) error {
148168
}
149169

150170
// Decode uses the schema to read the next encoded value from the input stream and store it in i
151-
func (s *dateSchema) Decode(r io.Reader, i interface{}) error {
171+
func (s *DateSchema) Decode(r io.Reader, i interface{}) error {
152172
if i == nil {
153173
return fmt.Errorf("cannot decode to nil destination")
154174
}
155175
return s.DecodeValue(r, reflect.ValueOf(i))
156176
}
157177

158178
// DecodeValue uses the schema to read the next encoded valuethe input stream and store it in v
159-
func (s *dateSchema) DecodeValue(r io.Reader, v reflect.Value) error {
179+
func (s *DateSchema) DecodeValue(r io.Reader, v reflect.Value) error {
160180

161181
v, err := PreDecode(s, r, v)
162182
if err != nil {

‎schemer.go

+205-128
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const (
3030
SchemaNullBit = 0x80 // The most signifiant bit indicates whether or not the type is nullable
3131
)
3232

33+
// Schema is an interface that encodes and decodes data of a specific type
3334
type Schema interface {
3435
// Encode uses the schema to write the encoded value of i to the output
3536
// stream
@@ -47,26 +48,73 @@ type Schema interface {
4748
// stream and stores it in v
4849
DecodeValue(r io.Reader, v reflect.Value) error
4950

50-
// Nullable returns true if and only if the type is nullable
51-
Nullable() bool
51+
// GoType returns the default Go type that represents the schema
52+
GoType() reflect.Type
53+
}
5254

53-
// MarshalJSON returns the JSON encoding of the schema
54-
MarshalJSON() ([]byte, error)
55+
// Marshaler is an interface implemented by a schema, allowing it to encode
56+
// itself into a portable binary format
57+
type Marshaler interface {
58+
MarshalSchemer() ([]byte, error)
59+
}
5560

56-
// MarshalSchemer encodes the schema in a portable binary format
57-
MarshalSchemer() []byte
61+
// SchemaGenerator is an interface implemented by custom schema generators.
62+
// When Register is called on a SchemaGenerator, the global SchemaOf,
63+
// DecodeSchema, and DecodeSchemaJSON functions will call the identically
64+
// named method on each schema generator to determine if a custom schema should
65+
// be returned.
66+
// If a SchemaGenerator cannot return a Schema for a specific type, it should
67+
// return nil, nil.
68+
// If all schema generators return a nil Schema or if Register is never called,
69+
// then the built-in logic for returning a Schema is used.
70+
type SchemaGenerator interface {
71+
SchemaOfType(i interface{}) (Schema, error)
72+
DecodeSchema(io.Reader) (Schema, error)
73+
DecodeSchemaJSON(io.Reader) (Schema, error)
74+
}
5875

59-
// GoType returns the default Go type that represents the schema
60-
GoType() reflect.Type
76+
type hasSchemaOfType interface {
77+
SchemaOfType(i interface{}) (Schema, error)
78+
}
79+
type hasDecodeSchema interface {
80+
DecodeSchema(io.Reader) (Schema, error)
81+
}
82+
type hasDecodeSchemaJSON interface {
83+
DecodeSchemaJSON(io.Reader) (Schema, error)
84+
}
85+
86+
var (
87+
regSchemaOfType = []hasSchemaOfType{}
88+
regDecodeSchema = []hasDecodeSchema{}
89+
regDecodeSchemaJSON = []hasDecodeSchemaJSON{}
90+
)
91+
92+
// Register records custom schema generators that implement `SchemaOfType`,
93+
// `DecodeSchema`, and/or `DecodeSchemaJSON`. When `schemer.SchemaOfType` is
94+
// called, `SchemaOfType` is called on each registered schema generator to
95+
// determine if a custom Schema should be used for a given type.
96+
func Register(ifaces ...interface{}) error {
97+
for _, iface := range ifaces {
98+
if sg, ok := iface.(hasSchemaOfType); ok {
99+
regSchemaOfType = append(regSchemaOfType, sg)
100+
}
101+
if sg, ok := iface.(hasDecodeSchema); ok {
102+
regDecodeSchema = append(regDecodeSchema, sg)
103+
}
104+
if sg, ok := iface.(hasDecodeSchemaJSON); ok {
105+
regDecodeSchemaJSON = append(regDecodeSchemaJSON, sg)
106+
}
107+
}
61108
}
62109

63-
// SchemaOf returns a Schema for the specified interface value
64-
// If i is a pointer or interface type, the pointer/interface value is used to
65-
// generate the Schema. If i is nil, an zero-field FixedObjectSchema is returned.
66-
func SchemaOf(i interface{}) Schema {
110+
// SchemaOf returns a Schema for the specified interface value.
111+
// If i is a pointer or interface type, the value of the pointer/interface is
112+
// used to generate the Schema.
113+
// If i is nil, an zero-field FixedObjectSchema is returned.
114+
func SchemaOf(i interface{}) (Schema, error) {
67115
if i == nil {
68116
// Return a Schema for an empty struct
69-
return &FixedObjectSchema{}
117+
return &FixedObjectSchema{}, nil
70118
}
71119

72120
t := reflect.TypeOf(i)
@@ -80,7 +128,14 @@ func SchemaOf(i interface{}) Schema {
80128
}
81129

82130
// SchemaOfType returns a Schema for the specified Go type
83-
func SchemaOfType(t reflect.Type) Schema {
131+
func SchemaOfType(t reflect.Type) (Schema, error) {
132+
// Call registered schema generators
133+
for _, sg := range regSchemaOfType {
134+
if s, err := sg.SchemaOfType(t); s != nil || err != nil {
135+
return s, err
136+
}
137+
}
138+
84139
nullable := false
85140

86141
// Dereference pointer / interface types
@@ -91,19 +146,13 @@ func SchemaOfType(t reflect.Type) Schema {
91146
nullable = true
92147
}
93148

94-
for _, s := range RegisteredSchemas() {
95-
if s.ForType(t) != nil {
96-
return s.(Schema)
97-
}
98-
}
99-
100149
k := t.Kind()
101150

102151
switch k {
103152
case reflect.Bool:
104153
s := &BoolSchema{}
105154
s.SetNullable(nullable)
106-
return s
155+
return s, nil
107156

108157
// all int types default to signed varint
109158
case reflect.Int:
@@ -117,9 +166,9 @@ func SchemaOfType(t reflect.Type) Schema {
117166
case reflect.Int64:
118167
s := &VarIntSchema{Signed: true}
119168
s.SetNullable(nullable)
120-
return s
169+
return s, nil
121170

122-
// all unint types default to unsigned varint
171+
// all uint types default to unsigned varint
123172
case reflect.Uint:
124173
fallthrough
125174
case reflect.Uint8:
@@ -131,54 +180,70 @@ func SchemaOfType(t reflect.Type) Schema {
131180
case reflect.Uint64:
132181
s := &VarIntSchema{Signed: false}
133182
s.SetNullable(nullable)
134-
return s
183+
return s, nil
135184

136185
case reflect.Float32:
137186
s := &FloatSchema{Bits: 32}
138187
s.SetNullable(nullable)
139-
return s
188+
return s, nil
140189
case reflect.Float64:
141190
s := &FloatSchema{Bits: 64}
142191
s.SetNullable(nullable)
143-
return s
192+
return s, nil
144193

145194
case reflect.Complex64:
146195
s := &ComplexSchema{Bits: 64}
147196
s.SetNullable(nullable)
148-
return s
197+
return s, nil
149198

150199
case reflect.Complex128:
151200
s := &ComplexSchema{Bits: 128}
152201
s.SetNullable(nullable)
153-
return s
202+
return s, nil
154203

155204
case reflect.String:
156-
s := &VarLenStringSchema{}
205+
s := &VarStringSchema{}
157206
s.SetNullable(nullable)
158-
return s
207+
return s, nil
159208

160209
case reflect.Array:
210+
el, err := SchemaOfType(t.Elem())
211+
if err != nil {
212+
return nil, fmt.Errorf("array type: %w", err)
213+
}
161214
s := &FixedArraySchema{
162215
Length: t.Len(),
163-
Element: SchemaOfType(t.Elem()),
216+
Element: el,
164217
}
165218
s.SetNullable(nullable)
166-
return s
219+
return s, nil
167220

168221
case reflect.Slice:
222+
el, err := SchemaOfType(t.Elem())
223+
if err != nil {
224+
return nil, fmt.Errorf("slice type: %w", err)
225+
}
169226
s := &VarArraySchema{
170-
Element: SchemaOfType(t.Elem()),
227+
Element: el,
171228
}
172229
s.SetNullable(nullable)
173-
return s
230+
return s, nil
174231

175232
case reflect.Map:
233+
key, err := SchemaOfType(t.Key())
234+
if err != nil {
235+
return nil, fmt.Errorf("map key type: %w", err)
236+
}
237+
val, err := SchemaOfType(t.Elem())
238+
if err != nil {
239+
return nil, fmt.Errorf("map value type: %w", err)
240+
}
176241
s := &VarObjectSchema{
177-
Key: SchemaOfType(t.Key()),
178-
Value: SchemaOfType(t.Elem()),
242+
Key: key,
243+
Value: val,
179244
}
180245
s.SetNullable(nullable)
181-
return s
246+
return s, nil
182247

183248
case reflect.Struct:
184249
s := &FixedObjectSchema{
@@ -188,49 +253,66 @@ func SchemaOfType(t reflect.Type) Schema {
188253

189254
for i := 0; i < t.NumField(); i++ {
190255
f := t.Field(i)
256+
ofs, err := SchemaOfType(f.Type)
257+
if err != nil {
258+
return nil, fmt.Errorf("struct field %v: %w", f.Name, err)
259+
}
191260
of := ObjectField{
192-
Schema: SchemaOfType(f.Type),
261+
Schema: ofs,
193262
}
194-
if of.Schema == nil {
263+
264+
exported := len(f.PkgPath) == 0
265+
if of.Schema == nil || !exported {
195266
continue // skip this field
196267
}
197-
ofSchemaOpts := of.Schema.(interface {
198-
SetNullable(bool)
199-
SetWeakDecoding(bool)
200-
})
201268

202269
// Parse struct tag and set aliases and schema options
203270
tagOpts := ParseStructTag(f.Tag.Get(StructTagName))
204271

205-
// Note: only override option if explicitly set in the tag
206-
if tagOpts.NullableSet {
207-
ofSchemaOpts.SetNullable(tagOpts.Nullable)
208-
}
209-
if tagOpts.WeakDecodingSet {
210-
ofSchemaOpts.SetWeakDecoding(tagOpts.WeakDecoding)
211-
}
212-
213272
if tagOpts.FieldAliasesSet {
214273
of.Aliases = tagOpts.FieldAliases
215274
} else {
216-
// if no aliases set in the struct tag, use the struct field name
275+
// if no aliases set in the tag, use the struct field name
217276
of.Aliases = []string{f.Name}
218277
}
219278

220-
// check if this field is not exported
221-
exported := len(f.PkgPath) == 0
222-
if exported && len(of.Aliases) > 0 {
223-
s.Fields = append(s.Fields, of)
279+
if len(of.Aliases) == 0 {
280+
continue // skip this field
224281
}
282+
283+
// Note: only override option if explicitly set in the tag
284+
if tagOpts.NullableSet {
285+
if opt, ok := of.Schema.(interface {
286+
SetNullable(bool)
287+
}); ok {
288+
opt.SetNullable(tagOpts.Nullable)
289+
}
290+
}
291+
if tagOpts.WeakDecodingSet {
292+
if opt, ok := of.Schema.(interface {
293+
SetWeakDecoding(bool)
294+
}); ok {
295+
opt.SetWeakDecoding(tagOpts.WeakDecoding)
296+
}
297+
}
298+
299+
// Add to FixedObjectSchema field list
300+
s.Fields = append(s.Fields, of)
225301
}
226-
return s
302+
return s, nil
227303
}
228304

229-
return nil
305+
return nil, fmt.Errorf("unsupported type %v", k)
230306
}
231307

232-
// DecodeJSONSchema takes a buffer of JSON data and parses it to create a schema
233-
func DecodeJSONSchema(buf []byte) (Schema, error) {
308+
// DecodeSchemaJSON takes a buffer of JSON data and parses it to create a schema
309+
func DecodeSchemaJSON(buf []byte) (Schema, error) {
310+
// Call registered schema generators
311+
for _, sg := range regDecodeSchemaJSON {
312+
if s, err := sg.DecodeSchemaJSON(buf); s != nil || err != nil {
313+
return s, err
314+
}
315+
}
234316

235317
fields := make(map[string]interface{})
236318

@@ -239,90 +321,89 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
239321
return nil, err
240322
}
241323

242-
tmpStr, ok := fields["type"].(string)
324+
// Parse `type`
325+
tmp, ok := fields["type"].(string)
243326
if !ok {
244-
return nil, fmt.Errorf("expected element 'type' not present in JSON data")
327+
return nil, fmt.Errorf("missing or invalid schema type")
245328
}
246-
schemaType := strings.ToLower(tmpStr)
247-
248-
switch schemaType {
249-
250-
// if we encounter a custom schema, loop through all registered custom schemas
251-
// and see if any of them is a match
252-
case "custom":
253-
for _, s := range RegisteredSchemas() {
329+
typeStr := strings.ToLower(tmp)
254330

255-
customtype, ok := fields["customtype"].(string)
256-
if !ok {
257-
return nil, fmt.Errorf("invalid customtype")
258-
}
259-
260-
if s.Name() == customtype {
261-
s, err := s.Unmarshaljson(buf)
262-
if err != nil {
263-
return nil, err
264-
}
265-
return s, nil
266-
}
331+
// Parse `nullable`
332+
nullable := false
333+
tmp, found := fields["nullable"]
334+
if found {
335+
if b, ok := tmp.(bool); ok {
336+
nullable = b
267337
}
338+
return fmt.Errorf("nullable must be a boolean")
339+
}
268340

341+
switch typeStr {
269342
case "bool":
270343
s := &BoolSchema{}
271-
b, _ := fields["nullable"].(bool)
272-
s.SchemaOptions.nullable = b
344+
s.SetNullable(nullable)
273345
return s, nil
274346

275347
case "int":
276-
numBits, ok := fields["bits"].(float64)
277-
278-
// if bits are present, then we are dealing with a fixed int
348+
bitsStr, ok := fields["bits"]
349+
// if bits is present, then we are dealing with a fixed int
279350
if ok {
351+
bits, ok := bitsStr.(float64)
352+
if !ok {
353+
return nil, fmt.Errorf("bits must be a number")
354+
}
280355
s := &FixedIntSchema{}
356+
s.SetNullable(nullable)
357+
if str, ok := fields["signed"]; ok {
358+
b, ok := str.(bool)
359+
if !ok {
360+
return nil, fmt.Errorf("signed must be a boolean")
361+
}
362+
s.Signed = b
363+
}
281364

282-
b, _ := fields["nullable"].(bool)
283-
s.SchemaOptions.nullable = b
284-
b, _ = fields["signed"].(bool)
285-
s.Signed = b
286-
287-
switch numBits {
365+
switch bits {
288366
case 8:
289367
fallthrough
290368
case 16:
291369
fallthrough
292370
case 32:
293371
fallthrough
294372
case 64:
295-
s.Bits = int(numBits)
373+
s.Bits = int(bits)
296374
default:
297-
return nil, fmt.Errorf("invalid int bit size encountered in JSON data: %d", int(numBits))
375+
return nil, fmt.Errorf("invalid bit size: %d", int(bits))
298376
}
299377

300378
return s, nil
301379
} else {
302380
s := &VarIntSchema{}
303-
304-
b, _ := fields["nullable"].(bool)
305-
s.SchemaOptions.nullable = b
306-
b, _ = fields["signed"].(bool)
307-
s.Signed = b
381+
s.SetNullable(nullable)
382+
if str, ok := fields["signed"]; ok {
383+
b, ok := str.(bool)
384+
if !ok {
385+
return nil, fmt.Errorf("signed must be a boolean")
386+
}
387+
s.Signed = b
388+
}
308389

309390
return s, nil
310391
}
311392

312393
case "float":
313394
s := &FloatSchema{}
314-
numBits, ok := fields["bits"].(float64)
395+
bits, ok := fields["bits"].(float64)
315396

316397
if !ok {
317398
return nil, fmt.Errorf("bits not present for float type in JSON data")
318399
}
319400

320-
if numBits == 64 {
401+
if bits == 64 {
321402
s.Bits = 64
322-
} else if numBits == 32 {
403+
} else if bits == 32 {
323404
s.Bits = 32
324405
} else {
325-
return nil, fmt.Errorf("invalid float bit size encountered in JSON data: %d", int(numBits))
406+
return nil, fmt.Errorf("invalid float bit size encountered in JSON data: %d", int(bits))
326407
}
327408

328409
b, _ := fields["nullable"].(bool)
@@ -332,18 +413,18 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
332413

333414
case "complex":
334415
s := &ComplexSchema{}
335-
numBits, ok := fields["bits"].(float64)
416+
bits, ok := fields["bits"].(float64)
336417

337418
if !ok {
338419
return nil, fmt.Errorf("bits not present for complex type in JSON data")
339420
}
340421

341-
if numBits == 128 {
422+
if bits == 128 {
342423
s.Bits = 128
343-
} else if numBits == 64 {
424+
} else if bits == 64 {
344425
s.Bits = 64
345426
} else {
346-
return nil, fmt.Errorf("invalid complex bit size encountered in JSON data: %d", int(numBits))
427+
return nil, fmt.Errorf("invalid complex bit size encountered in JSON data: %d", int(bits))
347428
}
348429
b, _ := fields["nullable"].(bool)
349430
s.SchemaOptions.nullable = b
@@ -418,7 +499,7 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
418499
return nil, err
419500
}
420501

421-
s.Element, err = DecodeJSONSchema(tmp)
502+
s.Element, err = DecodeSchemaJSON(tmp)
422503
if err != nil {
423504
return nil, err
424505
}
@@ -436,7 +517,7 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
436517
return nil, err
437518
}
438519

439-
s.Element, err = DecodeJSONSchema(tmp)
520+
s.Element, err = DecodeSchemaJSON(tmp)
440521
if err != nil {
441522
return nil, err
442523
}
@@ -481,7 +562,7 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
481562
return nil, err
482563
}
483564
// recursive call to process this field of this object...
484-
of.Schema, err = DecodeJSONSchema(tmp)
565+
of.Schema, err = DecodeSchemaJSON(tmp)
485566
if err != nil {
486567
return nil, err
487568
}
@@ -500,7 +581,7 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
500581
if err != nil {
501582
return nil, err
502583
}
503-
s.Key, err = DecodeJSONSchema(tmp)
584+
s.Key, err = DecodeSchemaJSON(tmp)
504585
if err != nil {
505586
return nil, err
506587
}
@@ -509,7 +590,7 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
509590
if err != nil {
510591
return nil, err
511592
}
512-
s.Value, err = DecodeJSONSchema(tmp)
593+
s.Value, err = DecodeSchemaJSON(tmp)
513594
if err != nil {
514595
return nil, err
515596
}
@@ -519,18 +600,13 @@ func DecodeJSONSchema(buf []byte) (Schema, error) {
519600
}
520601
}
521602

522-
return nil, fmt.Errorf("invalid JSON schema type: %s", schemaType)
603+
return nil, fmt.Errorf("invalid schema type: %s", typeStr)
523604
}
524605

525606
// DecodeSchema decodes a Schema from its binary representation
526-
func DecodeSchema(buf []byte) (Schema, error) {
527-
528-
byteIndex := 0 // always start at the beginning of the buffer
529-
530-
// and then decodeSchema() will advance *byteIndex as it goes
531-
tmp, err := decodeSchema(buf, &byteIndex)
532-
533-
return tmp, err
607+
func DecodeSchema(buf []byte) (Schema, int, error) {
608+
byteIndex := 0
609+
return decodeSchema(buf, &byteIndex)
534610
}
535611

536612
// decodeSchema processes buf[] to actually decode the binary schema.
@@ -820,13 +896,13 @@ func decodeSchema(buf []byte, byteIndex *int) (Schema, error) {
820896
// nullable.
821897
// If this routine returns false, no more processing is needed on the
822898
// encoder who called this routine.
823-
func PreEncode(s Schema, w io.Writer, v *reflect.Value) (bool, error) {
899+
func PreEncode(nullable bool, w io.Writer, v *reflect.Value) (bool, error) {
824900
// Dereference pointer / interface types
825901
for k := v.Kind(); k == reflect.Ptr || k == reflect.Interface; k = v.Kind() {
826902
*v = v.Elem()
827903
}
828904

829-
if s.Nullable() {
905+
if nullable {
830906
// did the caller pass in a nil value, or a null pointer?
831907
if !v.IsValid() {
832908
// per the revised spec, 1 indicates null
@@ -852,15 +928,15 @@ func PreEncode(s Schema, w io.Writer, v *reflect.Value) (bool, error) {
852928
// is nullable.
853929
// This routine also handles derefering pointers and interfaces, and returns
854930
// the new value of v after it is set.
855-
func PreDecode(s Schema, r io.Reader, v reflect.Value) (reflect.Value, error) {
931+
func PreDecode(nullable bool, r io.Reader, v reflect.Value) (reflect.Value, error) {
856932
// if t is a ptr or interface type, remove exactly ONE level of indirection
857933
if k := v.Kind(); !v.CanSet() && (k == reflect.Ptr || k == reflect.Interface) {
858934
v = v.Elem()
859935
}
860936

861937
// if the data indicates this type is nullable, then the actual
862938
// value is preceeded by one byte [which indicates if the encoder encoded a nill value]
863-
if s.Nullable() {
939+
if nullable {
864940
buf := make([]byte, 1)
865941

866942
// first byte indicates whether value is null or not...
@@ -903,6 +979,7 @@ func PreDecode(s Schema, r io.Reader, v reflect.Value) (reflect.Value, error) {
903979

904980
// initialization function for the Schemer Library
905981
func init() {
906-
RegisterCustomSchema(&dateSchema{})
907-
RegisterCustomSchema(&ipv4Schema{})
982+
Register(dateSchemaGenerator{})
983+
// RegisterCustomSchema(&dateSchema{})
984+
// RegisterCustomSchema(&ipv4Schema{})
908985
}

0 commit comments

Comments
 (0)
Please sign in to comment.