Skip to content

Commit

Permalink
feat: Handle a nullable map union w/ a plain map
Browse files Browse the repository at this point in the history
Similar to how nullable slices are handles, this adds support for using
plain `map[string]any` for nullable unions of maps instead of using an
explicit pointer to a map.
  • Loading branch information
0xjac committed Oct 8, 2024
1 parent 67bf318 commit 8d09c83
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ When a non-`nil` union value is encountered, a single key is en/decoded. The key
type name, or scheam full name in the case of a named schema (enum, fixed or record).
* ***T:** This is allowed in a "nullable" union. A nullable union is defined as a two schema union,
with one of the types being `null` (ie. `["null", "string"]` or `["string", "null"]`), in this case
a `*T` is allowed, with `T` matching the conversion table above. In the case of a slice, the slice can be used
a `*T` is allowed, with `T` matching the conversion table above. In the case of a slice or a map, the slice or the map can be used
directly.
* **any:** An `interface` can be provided and the type or name resolved. Primitive types
are pre-registered, but named types, maps and slices will need to be registered with the `Register` function.
Expand Down
28 changes: 24 additions & 4 deletions codec_union.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@ import (
func createDecoderOfUnion(d *decoderContext, schema *UnionSchema, typ reflect2.Type) ValDecoder {
switch typ.Kind() {
case reflect.Map:
if typ.(reflect2.MapType).Key().Kind() != reflect.String ||
typ.(reflect2.MapType).Elem().Kind() != reflect.Interface {
if typ.(reflect2.MapType).Key().Kind() != reflect.String {
break
}

if typ.(reflect2.MapType).Elem().Kind() != reflect.Interface {
if !schema.Nullable() {
break
}

return decoderOfNullableUnion(d, schema, typ)
}

return decoderOfMapUnion(d, schema, typ)
case reflect.Slice:
if !schema.Nullable() {
Expand Down Expand Up @@ -44,10 +52,18 @@ func createDecoderOfUnion(d *decoderContext, schema *UnionSchema, typ reflect2.T
func createEncoderOfUnion(e *encoderContext, schema *UnionSchema, typ reflect2.Type) ValEncoder {
switch typ.Kind() {
case reflect.Map:
if typ.(reflect2.MapType).Key().Kind() != reflect.String ||
typ.(reflect2.MapType).Elem().Kind() != reflect.Interface {
if typ.(reflect2.MapType).Key().Kind() != reflect.String {
break
}

if typ.(reflect2.MapType).Elem().Kind() != reflect.Interface {
if !schema.Nullable() {
break
}

return encoderOfNullableUnion(e, schema, typ)
}

return encoderOfMapUnion(e, schema, typ)
case reflect.Slice:
if !schema.Nullable() {
Expand Down Expand Up @@ -179,6 +195,8 @@ func decoderOfNullableUnion(d *decoderContext, schema Schema, typ reflect2.Type)
isPtr = true
case *reflect2.UnsafeSliceType:
baseTyp = v
case *reflect2.UnsafeMapType:
baseTyp = v
}
decoder := decoderOfType(d, union.Types()[typeIdx], baseTyp)

Expand Down Expand Up @@ -249,6 +267,8 @@ func encoderOfNullableUnion(e *encoderContext, schema Schema, typ reflect2.Type)
isPtr = true
case *reflect2.UnsafeSliceType:
baseTyp = v
case *reflect2.UnsafeMapType:
baseTyp = v
}
encoder := encoderOfType(e, union.Types()[typeIdx], baseTyp)

Expand Down

0 comments on commit 8d09c83

Please sign in to comment.