Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add recursive structs supported #335

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Goland
.idea
37 changes: 14 additions & 23 deletions codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,11 @@ func (c *frozenConfig) DecoderOf(schema Schema, typ reflect2.Type) ValDecoder {
if decoder != nil {
return decoder
}

ptrType := typ.(*reflect2.UnsafePtrType)
decoder = decoderOfType(c, schema, ptrType.Elem())
c.addDecoderToCache(schema.Fingerprint(), rtype, decoder)
decoder = c.processingGroup.processingDecoderOfType(c, schema, typ, decoderOfType)
return decoder
}

func decoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func decoderOfType(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
if dec := createDecoderOfMarshaler(cfg, schema, typ); dec != nil {
return dec
}
Expand All @@ -93,22 +90,22 @@ func decoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecod
return createDecoderOfNative(schema, typ)

case Record:
return createDecoderOfRecord(cfg, schema, typ)
return createDecoderOfRecord(cfg, p, schema, typ)

case Ref:
return decoderOfType(cfg, schema.(*RefSchema).Schema(), typ)
return decoderOfType(cfg, p, schema.(*RefSchema).Schema(), typ)

case Enum:
return createDecoderOfEnum(schema, typ)

case Array:
return createDecoderOfArray(cfg, schema, typ)
return createDecoderOfArray(cfg, p, schema, typ)

case Map:
return createDecoderOfMap(cfg, schema, typ)
return createDecoderOfMap(cfg, p, schema, typ)

case Union:
return createDecoderOfUnion(cfg, schema, typ)
return createDecoderOfUnion(cfg, p, schema, typ)

case Fixed:
return createDecoderOfFixed(schema, typ)
Expand All @@ -123,18 +120,12 @@ func (c *frozenConfig) EncoderOf(schema Schema, typ reflect2.Type) ValEncoder {
if typ == nil {
typ = reflect2.TypeOf((*null)(nil))
}

rtype := typ.RType()
encoder := c.getEncoderFromCache(schema.Fingerprint(), rtype)
if encoder != nil {
return encoder
}

encoder = encoderOfType(c, schema, typ)
if typ.LikePtr() {
encoder = &onePtrEncoder{encoder}
}
c.addEncoderToCache(schema.Fingerprint(), rtype, encoder)
encoder = c.processingGroup.processingEncoderOfType(c, schema, typ, encoderOfType)
return encoder
}

Expand All @@ -146,7 +137,7 @@ func (e *onePtrEncoder) Encode(ptr unsafe.Pointer, w *Writer) {
e.enc.Encode(noescape(unsafe.Pointer(&ptr)), w)
}

func encoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func encoderOfType(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
if enc := createEncoderOfMarshaler(cfg, schema, typ); enc != nil {
return enc
}
Expand All @@ -160,22 +151,22 @@ func encoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncod
return createEncoderOfNative(schema, typ)

case Record:
return createEncoderOfRecord(cfg, schema, typ)
return createEncoderOfRecord(cfg, p, schema, typ)

case Ref:
return encoderOfType(cfg, schema.(*RefSchema).Schema(), typ)
return encoderOfType(cfg, p, schema.(*RefSchema).Schema(), typ)

case Enum:
return createEncoderOfEnum(schema, typ)

case Array:
return createEncoderOfArray(cfg, schema, typ)
return createEncoderOfArray(cfg, p, schema, typ)

case Map:
return createEncoderOfMap(cfg, schema, typ)
return createEncoderOfMap(cfg, p, schema, typ)

case Union:
return createEncoderOfUnion(cfg, schema, typ)
return createEncoderOfUnion(cfg, p, schema, typ)

case Fixed:
return createEncoderOfFixed(schema, typ)
Expand Down
16 changes: 8 additions & 8 deletions codec_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ import (
"github.com/modern-go/reflect2"
)

func createDecoderOfArray(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func createDecoderOfArray(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
if typ.Kind() == reflect.Slice {
return decoderOfArray(cfg, schema, typ)
return decoderOfArray(cfg, p, schema, typ)
}

return &errorDecoder{err: fmt.Errorf("avro: %s is unsupported for Avro %s", typ.String(), schema.Type())}
}

func createEncoderOfArray(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func createEncoderOfArray(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
if typ.Kind() == reflect.Slice {
return encoderOfArray(cfg, schema, typ)
return encoderOfArray(cfg, p, schema, typ)
}

return &errorEncoder{err: fmt.Errorf("avro: %s is unsupported for Avro %s", typ.String(), schema.Type())}
}

func decoderOfArray(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func decoderOfArray(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
arr := schema.(*ArraySchema)
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := decoderOfType(cfg, arr.Items(), sliceType.Elem())
decoder := decoderOfType(cfg, p, arr.Items(), sliceType.Elem())

return &arrayDecoder{typ: sliceType, decoder: decoder}
}
Expand Down Expand Up @@ -68,10 +68,10 @@ func (d *arrayDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
}
}

func encoderOfArray(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func encoderOfArray(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
arr := schema.(*ArraySchema)
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := encoderOfType(cfg, arr.Items(), sliceType.Elem())
encoder := encoderOfType(cfg, p, arr.Items(), sliceType.Elem())

return &arrayEncoder{
blockLength: cfg.getBlockLength(),
Expand Down
3 changes: 2 additions & 1 deletion codec_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ func genericDecode(schema Schema, r *Reader) any {
r.ReportError("Read", err.Error())
return nil
}
decoderOfType(r.cfg, schema, rTyp).Decode(rPtr, r)
dec := r.cfg.processingGroup.processingDecoderOfType(r.cfg, schema, rTyp, decoderOfType)
dec.Decode(rPtr, r)
if r.Error != nil {
return nil
}
Expand Down
28 changes: 14 additions & 14 deletions codec_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,38 @@ import (
"github.com/modern-go/reflect2"
)

func createDecoderOfMap(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func createDecoderOfMap(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
if typ.Kind() == reflect.Map {
keyType := typ.(reflect2.MapType).Key()
switch {
case keyType.Kind() == reflect.String:
return decoderOfMap(cfg, schema, typ)
return decoderOfMap(cfg, p, schema, typ)
case keyType.Implements(textUnmarshalerType):
return decoderOfMapUnmarshaler(cfg, schema, typ)
return decoderOfMapUnmarshaler(cfg, p, schema, typ)
}
}

return &errorDecoder{err: fmt.Errorf("avro: %s is unsupported for Avro %s", typ.String(), schema.Type())}
}

func createEncoderOfMap(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func createEncoderOfMap(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
if typ.Kind() == reflect.Map {
keyType := typ.(reflect2.MapType).Key()
switch {
case keyType.Kind() == reflect.String:
return encoderOfMap(cfg, schema, typ)
return encoderOfMap(cfg, p, schema, typ)
case keyType.Implements(textMarshalerType):
return encoderOfMapMarshaler(cfg, schema, typ)
return encoderOfMapMarshaler(cfg, p, schema, typ)
}
}

return &errorEncoder{err: fmt.Errorf("avro: %s is unsupported for Avro %s", typ.String(), schema.Type())}
}

func decoderOfMap(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func decoderOfMap(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
m := schema.(*MapSchema)
mapType := typ.(*reflect2.UnsafeMapType)
decoder := decoderOfType(cfg, m.Values(), mapType.Elem())
decoder := decoderOfType(cfg, p, m.Values(), mapType.Elem())

return &mapDecoder{
mapType: mapType,
Expand Down Expand Up @@ -82,10 +82,10 @@ func (d *mapDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
}
}

func decoderOfMapUnmarshaler(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func decoderOfMapUnmarshaler(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
m := schema.(*MapSchema)
mapType := typ.(*reflect2.UnsafeMapType)
decoder := decoderOfType(cfg, m.Values(), mapType.Elem())
decoder := decoderOfType(cfg, p, m.Values(), mapType.Elem())

return &mapDecoderUnmarshaler{
mapType: mapType,
Expand Down Expand Up @@ -141,10 +141,10 @@ func (d *mapDecoderUnmarshaler) Decode(ptr unsafe.Pointer, r *Reader) {
}
}

func encoderOfMap(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func encoderOfMap(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
m := schema.(*MapSchema)
mapType := typ.(*reflect2.UnsafeMapType)
encoder := encoderOfType(cfg, m.Values(), mapType.Elem())
encoder := encoderOfType(cfg, p, m.Values(), mapType.Elem())

return &mapEncoder{
blockLength: cfg.getBlockLength(),
Expand Down Expand Up @@ -186,10 +186,10 @@ func (e *mapEncoder) Encode(ptr unsafe.Pointer, w *Writer) {
}
}

func encoderOfMapMarshaler(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func encoderOfMapMarshaler(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
m := schema.(*MapSchema)
mapType := typ.(*reflect2.UnsafeMapType)
encoder := encoderOfType(cfg, m.Values(), mapType.Elem())
encoder := encoderOfType(cfg, p, m.Values(), mapType.Elem())

return &mapEncoderMarshaller{
blockLength: cfg.getBlockLength(),
Expand Down
8 changes: 4 additions & 4 deletions codec_ptr.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"github.com/modern-go/reflect2"
)

func decoderOfPtr(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
func decoderOfPtr(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValDecoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()

decoder := decoderOfType(cfg, schema, elemType)
decoder := decoderOfType(cfg, p, schema, elemType)

return &dereferenceDecoder{typ: elemType, decoder: decoder}
}
Expand All @@ -34,11 +34,11 @@ func (d *dereferenceDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
d.decoder.Decode(*((*unsafe.Pointer)(ptr)), r)
}

func encoderOfPtr(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
func encoderOfPtr(cfg *frozenConfig, p *processing, schema Schema, typ reflect2.Type) ValEncoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()

enc := encoderOfType(cfg, schema, elemType)
enc := encoderOfType(cfg, p, schema, elemType)

return &dereferenceEncoder{typ: elemType, encoder: enc}
}
Expand Down
Loading