Skip to content

Commit

Permalink
Use enum default values to parse unknown values
Browse files Browse the repository at this point in the history
  • Loading branch information
actgardner committed Oct 15, 2021
1 parent 3fea199 commit 9a99f05
Show file tree
Hide file tree
Showing 21 changed files with 826 additions and 15 deletions.
26 changes: 23 additions & 3 deletions v10/compiler/method.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,30 @@ func (p *irMethod) compileRecord(writer, reader *schema.RecordDefinition) error

func (p *irMethod) compileEnum(writer, reader *schema.EnumDefinition) error {
log("compileEnum()\n writer:\n %v\n---\nreader: %v\n---\n", writer, reader)
p.addLiteral(vm.Read, vm.Int)
p.addLiteral(vm.Read, vm.Long)
errId := p.addError("Unexpected value for enum")
switchId := p.addSwitchStart(len(writer.Symbols()), errId)
if reader != nil {
p.addLiteral(vm.Set, vm.Int)
for i, wSymbol := range writer.Symbols() {
p.addSwitchCase(switchId, i, -1)
rIdx := reader.SymbolIndex(wSymbol)
if rIdx > -1 {
p.addLiteral(vm.SetInt, rIdx)
p.addLiteral(vm.Set, vm.Int)
} else if reader.Default() != "" {
rIdx = reader.SymbolIndex(reader.Default())
if rIdx == -1 {
return fmt.Errorf("Reader schema has invalid default symbol %q", reader.Default())
}
p.addLiteral(vm.SetInt, rIdx)
p.addLiteral(vm.Set, vm.Int)
} else {
typedErrId := p.addError(fmt.Sprintf("Reader schema has no value for symbol %q in enum", wSymbol))
p.addLiteral(vm.Halt, typedErrId)
}
}
}
p.addSwitchEnd(switchId)
return nil
}

Expand Down Expand Up @@ -323,7 +343,7 @@ writer:
return err
}
} else if unionReader, ok := reader.(*schema.UnionField); ok {
// Always try to find an extact match by name before trying to handle evolution
// Always try to find an exact match by name before trying to handle evolution
for readerIndex, r := range unionReader.AvroTypes() {
if r.Name() == t.Name() {
log("Union types have exact match by name: %q %q", r.Name(), t.Name())
Expand Down
6 changes: 6 additions & 0 deletions v10/generator/flat/templates/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/actgardner/gogen-avro/v10/vm"
)
var _ = fmt.Printf
{{ if ne .Doc "" }}// {{ .Doc}}{{ end }}
type {{ .GoType }} int32
Expand Down Expand Up @@ -41,7 +43,11 @@ func {{ .FromStringMethod }}(raw string) (r {{ .GoType }}, err error) {
{{ end -}}
}
{{ if ne .Default "" }}
return {{ $.SymbolName .Default }}, nil
{{ else }}
return -1, fmt.Errorf("invalid value for {{ $.GoType }}: '%s'", raw)
{{ end }}
}
func (b {{ .GoType }}) MarshalJSON() ([]byte, error) {
Expand Down
10 changes: 9 additions & 1 deletion v10/parser/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ func (n *Namespace) decodeEnumDefinition(namespace string, schemaMap map[string]
return nil, err
}

var defaultStr string
if dv, ok := schemaMap["default"]; ok {
defaultStr, ok = dv.(string)
if !ok {
return nil, NewWrongMapValueTypeError("default", "string", dv)
}
}

symbolStr, ok := interfaceSliceToStringSlice(symbolSlice)
if !ok {
return nil, fmt.Errorf("'symbols' must be an array of strings")
Expand All @@ -230,7 +238,7 @@ func (n *Namespace) decodeEnumDefinition(namespace string, schemaMap map[string]
}
}

return avro.NewEnumDefinition(name, aliases, symbolStr, docString, schemaMap), nil
return avro.NewEnumDefinition(name, aliases, symbolStr, docString, defaultStr, schemaMap), nil
}

// decodeFixedDefinition accepts a namespace and a map representing a fixed definition,
Expand Down
37 changes: 26 additions & 11 deletions v10/schema/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ import (
)

type EnumDefinition struct {
name QualifiedName
aliases []QualifiedName
symbols []string
doc string
definition map[string]interface{}
name QualifiedName
aliases []QualifiedName
symbols []string
doc string
defaultValue string
definition map[string]interface{}
}

func NewEnumDefinition(name QualifiedName, aliases []QualifiedName, symbols []string, doc string, definition map[string]interface{}) *EnumDefinition {
func NewEnumDefinition(name QualifiedName, aliases []QualifiedName, symbols []string, doc string, defaultValue string, definition map[string]interface{}) *EnumDefinition {
return &EnumDefinition{
name: name,
aliases: aliases,
symbols: symbols,
doc: doc,
definition: definition,
name: name,
aliases: aliases,
symbols: symbols,
doc: doc,
defaultValue: defaultValue,
definition: definition,
}
}

Expand All @@ -41,6 +43,15 @@ func (e *EnumDefinition) Aliases() []QualifiedName {
return e.aliases
}

func (e *EnumDefinition) SymbolIndex(symbol string) int {
for i, s := range e.symbols {
if s == symbol {
return i
}
}
return -1
}

func (e *EnumDefinition) Symbols() []string {
return e.symbols
}
Expand Down Expand Up @@ -99,3 +110,7 @@ func (s *EnumDefinition) WrapperPointer() bool { return false }
func (s *EnumDefinition) Children() []AvroType {
return []AvroType{}
}

func (s *EnumDefinition) Default() string {
return s.defaultValue
}
148 changes: 148 additions & 0 deletions v10/test/enum-default/enum_test_record.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions v10/test/enum-default/enum_test_record_container.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions v10/test/enum-default/evolution.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "record",
"name": "EnumTestRecord",
"fields": [
{
"name": "EnumField",
"type": {
"name": "TestEnumType",
"type": "enum",
"doc": "Test \nenum",
"symbols": ["TestSymbol3", "TestSymbol1"],
"default": "TestSymbol1"
}
}
]
}
18 changes: 18 additions & 0 deletions v10/test/enum-default/evolution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"data": {
"EnumField": "TestSymbol2"
},
"expected": {
"EnumField": "TestSymbol1"
}
},
{
"data": {
"EnumField": "TestSymbol3"
},
"expected": {
"EnumField": "TestSymbol3"
}
}
]
Loading

0 comments on commit 9a99f05

Please sign in to comment.