From 391d3d23d75838e90bc241a59a737e6cf92fc495 Mon Sep 17 00:00:00 2001 From: Vasilii Dorokhin Date: Mon, 9 Sep 2024 16:39:10 +0300 Subject: [PATCH 1/2] feat: use verbose schema for encoders --- cmd/avrogen/main.go | 1 + cmd/avrogen/testdata/golden_encoders.go | 2 +- gen/gen.go | 42 ++++++++++++++++++++++--- gen/testdata/golden_encoders.go | 4 +-- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/cmd/avrogen/main.go b/cmd/avrogen/main.go index a2adfb4..4114a83 100644 --- a/cmd/avrogen/main.go +++ b/cmd/avrogen/main.go @@ -84,6 +84,7 @@ func realMain(args []string, stdout, stderr io.Writer) int { gen.WithInitialisms(initialisms), gen.WithTemplate(string(template)), gen.WithStrictTypes(cfg.StrictTypes), + gen.WithLogWriter(stdout), } g := gen.NewGenerator(cfg.Pkg, tags, opts...) for _, file := range flgs.Args() { diff --git a/cmd/avrogen/testdata/golden_encoders.go b/cmd/avrogen/testdata/golden_encoders.go index 5f45e05..721f0f7 100644 --- a/cmd/avrogen/testdata/golden_encoders.go +++ b/cmd/avrogen/testdata/golden_encoders.go @@ -13,7 +13,7 @@ type Test struct { SomeInt int `avro:"someInt"` } -var schemaTest = avro.MustParse(`{"name":"a.b.test","type":"record","fields":[{"name":"someString","type":"string"},{"name":"someInt","type":"int"}]}`) +var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test is a test struct","type":"record","fields":[{"name":"someString","doc":"SomeString is a string","type":"string"},{"name":"someInt","type":"int"}]}`) // Schema returns the schema for Test. func (o *Test) Schema() avro.Schema { diff --git a/gen/gen.go b/gen/gen.go index 344af81..74de52e 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "maps" + "os" "strings" "text/template" "unicode/utf8" @@ -182,6 +183,16 @@ func WithLogicalType(logicalType LogicalType) OptsFunc { } } +// WithLogWriter sets a custom log writer for the Generator. +// It allows you to specify an `io.Writer` to which log messages will be written. +// +// Default output is `os.Stdout`. +func WithLogWriter(writer io.Writer) OptsFunc { + return func(g *Generator) { + g.logWriter = writer + } +} + func ensureTrailingPeriod(text string) string { if text == "" { return text @@ -209,6 +220,8 @@ type Generator struct { typedefs []typedef nameCaser *strcase.Caser + + logWriter io.Writer } // NewGenerator returns a generator. @@ -217,9 +230,10 @@ func NewGenerator(pkg string, tags map[string]TagStyle, opts ...OptsFunc) *Gener delete(clonedTags, "avro") g := &Generator{ - template: outputTemplate, - pkg: pkg, - tags: clonedTags, + template: outputTemplate, + pkg: pkg, + tags: clonedTags, + logWriter: os.Stdout, } for _, opt := range opts { @@ -304,11 +318,31 @@ func (g *Generator) resolveRecordSchema(schema *avro.RecordSchema) string { typeName := g.resolveTypeName(schema) if !g.hasTypeDef(typeName) { - g.typedefs = append(g.typedefs, newType(typeName, schema.Doc(), fields, schema.String())) + g.typedefs = append(g.typedefs, newType(typeName, schema.Doc(), fields, g.rawSchema(schema))) } return typeName } +func (g *Generator) rawSchema(schema *avro.RecordSchema) string { + var rawSchema string + if schemaJSON, err := schema.MarshalJSON(); err != nil { + g.log("Warning:", + fmt.Sprintf( + "Failed to marshal raw schema for '%s'. Falling back to using the canonical form of the schema.", + schema.FullName(), + ), + "Error:", err) + rawSchema = schema.String() + } else { + rawSchema = string(schemaJSON) + } + return rawSchema +} + +func (g *Generator) log(operands ...any) { + _, _ = fmt.Fprintln(g.logWriter, operands...) +} + func (g *Generator) hasTypeDef(name string) bool { for _, def := range g.typedefs { if def.Name != name { diff --git a/gen/testdata/golden_encoders.go b/gen/testdata/golden_encoders.go index 73d3518..908c13a 100644 --- a/gen/testdata/golden_encoders.go +++ b/gen/testdata/golden_encoders.go @@ -15,7 +15,7 @@ type InnerRecord struct { InnerPrimitiveNullableArrayUnion *[]string `avro:"innerPrimitiveNullableArrayUnion"` } -var schemaInnerRecord = avro.MustParse(`{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]}]}`) +var schemaInnerRecord = avro.MustParse(`{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}`) // Schema returns the schema for InnerRecord. func (o *InnerRecord) Schema() avro.Schema { @@ -219,7 +219,7 @@ type Test struct { UUID string `avro:"uuid"` } -var schemaTest = avro.MustParse(`{"name":"a.b.test","type":"record","fields":[{"name":"aString","type":"string"},{"name":"aBoolean","type":"boolean"},{"name":"anInt","type":"int"},{"name":"aFloat","type":"float"},{"name":"aDouble","type":"double"},{"name":"aLong","type":"long"},{"name":"justBytes","type":"bytes"},{"name":"primitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]},{"name":"innerRecord","type":{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]}]}},{"name":"anEnum","type":{"name":"a.b.Cards","type":"enum","symbols":["SPADES","HEARTS","DIAMONDS","CLUBS"]}},{"name":"aFixed","type":{"name":"a.b.fixedField","type":"fixed","size":7}},{"name":"aLogicalFixed","type":{"name":"a.b.logicalDuration","type":"fixed","size":12,"logicalType":"duration"}},{"name":"anotherLogicalFixed","type":"a.b.logicalDuration"},{"name":"mapOfStrings","type":{"type":"map","values":"string"}},{"name":"mapOfRecords","type":{"type":"map","values":{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}}},{"name":"aDate","type":{"type":"int","logicalType":"date"}},{"name":"aDuration","type":{"type":"int","logicalType":"time-millis"}},{"name":"aLongTimeMicros","type":{"type":"long","logicalType":"time-micros"}},{"name":"aLongTimestampMillis","type":{"type":"long","logicalType":"timestamp-millis"}},{"name":"aLongTimestampMicro","type":{"type":"long","logicalType":"timestamp-micros"}},{"name":"aBytesDecimal","type":{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}},{"name":"aRecordArray","type":{"type":"array","items":{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}}},{"name":"nullableRecordUnion","type":["null",{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nonNullableRecordUnion","type":[{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nullableRecordUnionWith3Options","type":["null",{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"ref","type":"a.b.record2InNullableUnion"},{"name":"uuid","type":{"type":"string","logicalType":"uuid"}}]}`) +var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test represents a golden record","type":"record","fields":[{"name":"aString","doc":"aString is just a string","type":"string"},{"name":"aBoolean","doc":"aBoolean is just a boolean.","type":"boolean"},{"name":"anInt","type":"int"},{"name":"aFloat","type":"float"},{"name":"aDouble","type":"double"},{"name":"aLong","type":"long"},{"name":"justBytes","type":"bytes"},{"name":"primitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null},{"name":"innerRecord","type":{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}},{"name":"anEnum","type":{"name":"a.b.Cards","type":"enum","symbols":["SPADES","HEARTS","DIAMONDS","CLUBS"]}},{"name":"aFixed","type":{"name":"a.b.fixedField","type":"fixed","size":7}},{"name":"aLogicalFixed","type":{"name":"a.b.logicalDuration","type":"fixed","size":12,"logicalType":"duration"}},{"name":"anotherLogicalFixed","type":"a.b.logicalDuration"},{"name":"mapOfStrings","type":{"type":"map","values":"string"}},{"name":"mapOfRecords","type":{"type":"map","values":{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}}},{"name":"aDate","type":{"type":"int","logicalType":"date"}},{"name":"aDuration","type":{"type":"int","logicalType":"time-millis"}},{"name":"aLongTimeMicros","type":{"type":"long","logicalType":"time-micros"}},{"name":"aLongTimestampMillis","type":{"type":"long","logicalType":"timestamp-millis"}},{"name":"aLongTimestampMicro","type":{"type":"long","logicalType":"timestamp-micros"}},{"name":"aBytesDecimal","type":{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}},{"name":"aRecordArray","type":{"type":"array","items":{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}}},{"name":"nullableRecordUnion","type":["null",{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"nonNullableRecordUnion","type":[{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nullableRecordUnionWith3Options","type":["null",{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"ref","type":"a.b.record2InNullableUnion"},{"name":"uuid","type":{"type":"string","logicalType":"uuid"}}]}`) // Schema returns the schema for Test. func (o *Test) Schema() avro.Schema { From 78b93350f19c6678fa1c6c7cf7d6141a53426e3b Mon Sep 17 00:00:00 2001 From: Vasilii Dorokhin Date: Tue, 10 Sep 2024 09:48:56 +0300 Subject: [PATCH 2/2] added feature flag for full schema usage --- cmd/avrogen/main.go | 4 +- cmd/avrogen/main_test.go | 23 ++ cmd/avrogen/testdata/golden_encoders.go | 2 +- .../testdata/golden_encoders_fullschema.go | 31 +++ gen/gen.go | 55 ++-- gen/gen_test.go | 17 ++ gen/testdata/golden_encoders.go | 4 +- gen/testdata/golden_encoders_fullschema.go | 237 ++++++++++++++++++ 8 files changed, 335 insertions(+), 38 deletions(-) create mode 100644 cmd/avrogen/testdata/golden_encoders_fullschema.go create mode 100644 gen/testdata/golden_encoders_fullschema.go diff --git a/cmd/avrogen/main.go b/cmd/avrogen/main.go index 4114a83..2009101 100644 --- a/cmd/avrogen/main.go +++ b/cmd/avrogen/main.go @@ -24,6 +24,7 @@ type config struct { Tags string FullName bool Encoders bool + FullSchema bool StrictTypes bool Initialisms string } @@ -42,6 +43,7 @@ func realMain(args []string, stdout, stderr io.Writer) int { flgs.StringVar(&cfg.Tags, "tags", "", "The additional field tags :{snake|camel|upper-camel|kebab}>[,...]") flgs.BoolVar(&cfg.FullName, "fullname", false, "Use the full name of the Record schema to create the struct name.") flgs.BoolVar(&cfg.Encoders, "encoders", false, "Generate encoders for the structs.") + flgs.BoolVar(&cfg.FullSchema, "fullschema", false, "Use the full schema in the generated encoders.") flgs.BoolVar(&cfg.StrictTypes, "strict-types", false, "Use strict type sizes (e.g. int32) during generation.") flgs.StringVar(&cfg.Initialisms, "initialisms", "", "Custom initialisms [,...] for struct and field names.") flgs.StringVar(&cfg.TemplateFileName, "template-filename", "", "Override output template with one loaded from file.") @@ -84,7 +86,7 @@ func realMain(args []string, stdout, stderr io.Writer) int { gen.WithInitialisms(initialisms), gen.WithTemplate(string(template)), gen.WithStrictTypes(cfg.StrictTypes), - gen.WithLogWriter(stdout), + gen.WithFullSchema(cfg.FullSchema), } g := gen.NewGenerator(cfg.Pkg, tags, opts...) for _, file := range flgs.Args() { diff --git a/cmd/avrogen/main_test.go b/cmd/avrogen/main_test.go index 4788be0..c15c3c4 100644 --- a/cmd/avrogen/main_test.go +++ b/cmd/avrogen/main_test.go @@ -143,6 +143,29 @@ func TestAvroGen_GeneratesSchemaWithEncoders(t *testing.T) { assert.Equal(t, want, got) } +func TestAvroGen_GeneratesSchemaWithFullSchema(t *testing.T) { + path, err := os.MkdirTemp("./", "avrogen") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(path) }) + + file := filepath.Join(path, "test.go") + args := []string{"avrogen", "-pkg", "testpkg", "-o", file, "-encoders", "-fullschema", "testdata/schema.avsc"} + gotCode := realMain(args, io.Discard, io.Discard) + require.Equal(t, 0, gotCode) + + got, err := os.ReadFile(file) + require.NoError(t, err) + + if *update { + err = os.WriteFile("testdata/golden_encoders_fullschema.go", got, 0600) + require.NoError(t, err) + } + + want, err := os.ReadFile("testdata/golden_encoders_fullschema.go") + require.NoError(t, err) + assert.Equal(t, want, got) +} + func TestAvroGen_GeneratesSchemaWithStrictTypes(t *testing.T) { path, err := os.MkdirTemp("./", "avrogen") require.NoError(t, err) diff --git a/cmd/avrogen/testdata/golden_encoders.go b/cmd/avrogen/testdata/golden_encoders.go index 721f0f7..5f45e05 100644 --- a/cmd/avrogen/testdata/golden_encoders.go +++ b/cmd/avrogen/testdata/golden_encoders.go @@ -13,7 +13,7 @@ type Test struct { SomeInt int `avro:"someInt"` } -var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test is a test struct","type":"record","fields":[{"name":"someString","doc":"SomeString is a string","type":"string"},{"name":"someInt","type":"int"}]}`) +var schemaTest = avro.MustParse(`{"name":"a.b.test","type":"record","fields":[{"name":"someString","type":"string"},{"name":"someInt","type":"int"}]}`) // Schema returns the schema for Test. func (o *Test) Schema() avro.Schema { diff --git a/cmd/avrogen/testdata/golden_encoders_fullschema.go b/cmd/avrogen/testdata/golden_encoders_fullschema.go new file mode 100644 index 0000000..721f0f7 --- /dev/null +++ b/cmd/avrogen/testdata/golden_encoders_fullschema.go @@ -0,0 +1,31 @@ +package testpkg + +// Code generated by avro/gen. DO NOT EDIT. + +import ( + "github.com/hamba/avro/v2" +) + +// Test is a test struct. +type Test struct { + // SomeString is a string. + SomeString string `avro:"someString"` + SomeInt int `avro:"someInt"` +} + +var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test is a test struct","type":"record","fields":[{"name":"someString","doc":"SomeString is a string","type":"string"},{"name":"someInt","type":"int"}]}`) + +// Schema returns the schema for Test. +func (o *Test) Schema() avro.Schema { + return schemaTest +} + +// Unmarshal decodes b into the receiver. +func (o *Test) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Test) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} diff --git a/gen/gen.go b/gen/gen.go index 7118559..010fc85 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "maps" - "os" "strings" "text/template" "unicode/utf8" @@ -24,6 +23,7 @@ type Config struct { Tags map[string]TagStyle FullName bool Encoders bool + FullSchema bool StrictTypes bool Initialisms []string LogicalTypes []LogicalType @@ -84,6 +84,7 @@ func StructFromSchema(schema avro.Schema, w io.Writer, cfg Config) error { WithEncoders(cfg.Encoders), WithInitialisms(cfg.Initialisms), WithStrictTypes(cfg.StrictTypes), + WithFullSchema(cfg.FullSchema), } for _, opt := range cfg.LogicalTypes { opts = append(opts, WithLogicalType(opt)) @@ -160,6 +161,13 @@ func WithPackageDoc(text string) OptsFunc { } } +// WithFullSchema configures the generator to store the full schema within the generation context. +func WithFullSchema(b bool) OptsFunc { + return func(g *Generator) { + g.fullSchema = b + } +} + // LogicalType used when the name of the "LogicalType" field in the Avro schema matches the Name attribute. type LogicalType struct { // Name of the LogicalType @@ -183,16 +191,6 @@ func WithLogicalType(logicalType LogicalType) OptsFunc { } } -// WithLogWriter sets a custom log writer for the Generator. -// It allows you to specify an `io.Writer` to which log messages will be written. -// -// Default output is `os.Stdout`. -func WithLogWriter(writer io.Writer) OptsFunc { - return func(g *Generator) { - g.logWriter = writer - } -} - func ensureTrailingPeriod(text string) string { if text == "" { return text @@ -211,6 +209,7 @@ type Generator struct { tags map[string]TagStyle fullName bool encoders bool + fullSchema bool strictTypes bool initialisms []string logicalTypes map[avro.LogicalType]LogicalType @@ -220,8 +219,6 @@ type Generator struct { typedefs []typedef nameCaser *strcase.Caser - - logWriter io.Writer } // NewGenerator returns a generator. @@ -230,10 +227,9 @@ func NewGenerator(pkg string, tags map[string]TagStyle, opts ...OptsFunc) *Gener delete(clonedTags, "avro") g := &Generator{ - template: outputTemplate, - pkg: pkg, - tags: clonedTags, - logWriter: os.Stdout, + template: outputTemplate, + pkg: pkg, + tags: clonedTags, } for _, opt := range opts { @@ -324,23 +320,14 @@ func (g *Generator) resolveRecordSchema(schema *avro.RecordSchema) string { } func (g *Generator) rawSchema(schema *avro.RecordSchema) string { - var rawSchema string - if schemaJSON, err := schema.MarshalJSON(); err != nil { - g.log("Warning:", - fmt.Sprintf( - "Failed to marshal raw schema for '%s'. Falling back to using the canonical form of the schema.", - schema.FullName(), - ), - "Error:", err) - rawSchema = schema.String() - } else { - rawSchema = string(schemaJSON) - } - return rawSchema -} - -func (g *Generator) log(operands ...any) { - _, _ = fmt.Fprintln(g.logWriter, operands...) + if g.fullSchema { + schemaJSON, err := schema.MarshalJSON() + if err != nil { + panic(fmt.Errorf("failed to marshal raw schema for '%s': %w", schema.FullName(), err)) + } + return string(schemaJSON) + } + return schema.String() } func (g *Generator) hasTypeDef(name string) bool { diff --git a/gen/gen_test.go b/gen/gen_test.go index 5d7c913..cceede1 100644 --- a/gen/gen_test.go +++ b/gen/gen_test.go @@ -261,6 +261,23 @@ func TestStruct_GenFromRecordSchemaWithEncoders(t *testing.T) { assert.Equal(t, string(want), string(file)) } +func TestStruct_GenFromRecordSchemaWithFullSchema(t *testing.T) { + schema, err := os.ReadFile("testdata/golden.avsc") + require.NoError(t, err) + + gc := gen.Config{PackageName: "Something", FullSchema: true, Encoders: true} + file, _ := generate(t, string(schema), gc) + + if *update { + err = os.WriteFile("testdata/golden_encoders_fullschema.go", file, 0600) + require.NoError(t, err) + } + + want, err := os.ReadFile("testdata/golden_encoders_fullschema.go") + require.NoError(t, err) + assert.Equal(t, string(want), string(file)) +} + func TestGenerator(t *testing.T) { unionSchema, err := avro.ParseFiles("testdata/uniontype.avsc") require.NoError(t, err) diff --git a/gen/testdata/golden_encoders.go b/gen/testdata/golden_encoders.go index 908c13a..73d3518 100644 --- a/gen/testdata/golden_encoders.go +++ b/gen/testdata/golden_encoders.go @@ -15,7 +15,7 @@ type InnerRecord struct { InnerPrimitiveNullableArrayUnion *[]string `avro:"innerPrimitiveNullableArrayUnion"` } -var schemaInnerRecord = avro.MustParse(`{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}`) +var schemaInnerRecord = avro.MustParse(`{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]}]}`) // Schema returns the schema for InnerRecord. func (o *InnerRecord) Schema() avro.Schema { @@ -219,7 +219,7 @@ type Test struct { UUID string `avro:"uuid"` } -var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test represents a golden record","type":"record","fields":[{"name":"aString","doc":"aString is just a string","type":"string"},{"name":"aBoolean","doc":"aBoolean is just a boolean.","type":"boolean"},{"name":"anInt","type":"int"},{"name":"aFloat","type":"float"},{"name":"aDouble","type":"double"},{"name":"aLong","type":"long"},{"name":"justBytes","type":"bytes"},{"name":"primitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null},{"name":"innerRecord","type":{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}},{"name":"anEnum","type":{"name":"a.b.Cards","type":"enum","symbols":["SPADES","HEARTS","DIAMONDS","CLUBS"]}},{"name":"aFixed","type":{"name":"a.b.fixedField","type":"fixed","size":7}},{"name":"aLogicalFixed","type":{"name":"a.b.logicalDuration","type":"fixed","size":12,"logicalType":"duration"}},{"name":"anotherLogicalFixed","type":"a.b.logicalDuration"},{"name":"mapOfStrings","type":{"type":"map","values":"string"}},{"name":"mapOfRecords","type":{"type":"map","values":{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}}},{"name":"aDate","type":{"type":"int","logicalType":"date"}},{"name":"aDuration","type":{"type":"int","logicalType":"time-millis"}},{"name":"aLongTimeMicros","type":{"type":"long","logicalType":"time-micros"}},{"name":"aLongTimestampMillis","type":{"type":"long","logicalType":"timestamp-millis"}},{"name":"aLongTimestampMicro","type":{"type":"long","logicalType":"timestamp-micros"}},{"name":"aBytesDecimal","type":{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}},{"name":"aRecordArray","type":{"type":"array","items":{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}}},{"name":"nullableRecordUnion","type":["null",{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"nonNullableRecordUnion","type":[{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nullableRecordUnionWith3Options","type":["null",{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"ref","type":"a.b.record2InNullableUnion"},{"name":"uuid","type":{"type":"string","logicalType":"uuid"}}]}`) +var schemaTest = avro.MustParse(`{"name":"a.b.test","type":"record","fields":[{"name":"aString","type":"string"},{"name":"aBoolean","type":"boolean"},{"name":"anInt","type":"int"},{"name":"aFloat","type":"float"},{"name":"aDouble","type":"double"},{"name":"aLong","type":"long"},{"name":"justBytes","type":"bytes"},{"name":"primitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]},{"name":"innerRecord","type":{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}]}]}},{"name":"anEnum","type":{"name":"a.b.Cards","type":"enum","symbols":["SPADES","HEARTS","DIAMONDS","CLUBS"]}},{"name":"aFixed","type":{"name":"a.b.fixedField","type":"fixed","size":7}},{"name":"aLogicalFixed","type":{"name":"a.b.logicalDuration","type":"fixed","size":12,"logicalType":"duration"}},{"name":"anotherLogicalFixed","type":"a.b.logicalDuration"},{"name":"mapOfStrings","type":{"type":"map","values":"string"}},{"name":"mapOfRecords","type":{"type":"map","values":{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}}},{"name":"aDate","type":{"type":"int","logicalType":"date"}},{"name":"aDuration","type":{"type":"int","logicalType":"time-millis"}},{"name":"aLongTimeMicros","type":{"type":"long","logicalType":"time-micros"}},{"name":"aLongTimestampMillis","type":{"type":"long","logicalType":"timestamp-millis"}},{"name":"aLongTimestampMicro","type":{"type":"long","logicalType":"timestamp-micros"}},{"name":"aBytesDecimal","type":{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}},{"name":"aRecordArray","type":{"type":"array","items":{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}}},{"name":"nullableRecordUnion","type":["null",{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nonNullableRecordUnion","type":[{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nullableRecordUnionWith3Options","type":["null",{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"ref","type":"a.b.record2InNullableUnion"},{"name":"uuid","type":{"type":"string","logicalType":"uuid"}}]}`) // Schema returns the schema for Test. func (o *Test) Schema() avro.Schema { diff --git a/gen/testdata/golden_encoders_fullschema.go b/gen/testdata/golden_encoders_fullschema.go new file mode 100644 index 0000000..908c13a --- /dev/null +++ b/gen/testdata/golden_encoders_fullschema.go @@ -0,0 +1,237 @@ +package something + +// Code generated by avro/gen. DO NOT EDIT. + +import ( + "math/big" + "time" + + "github.com/hamba/avro/v2" +) + +// InnerRecord is a generated struct. +type InnerRecord struct { + InnerJustBytes []byte `avro:"innerJustBytes"` + InnerPrimitiveNullableArrayUnion *[]string `avro:"innerPrimitiveNullableArrayUnion"` +} + +var schemaInnerRecord = avro.MustParse(`{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}`) + +// Schema returns the schema for InnerRecord. +func (o *InnerRecord) Schema() avro.Schema { + return schemaInnerRecord +} + +// Unmarshal decodes b into the receiver. +func (o *InnerRecord) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *InnerRecord) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// RecordInMap is a generated struct. +type RecordInMap struct { + Name string `avro:"name"` +} + +var schemaRecordInMap = avro.MustParse(`{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}`) + +// Schema returns the schema for RecordInMap. +func (o *RecordInMap) Schema() avro.Schema { + return schemaRecordInMap +} + +// Unmarshal decodes b into the receiver. +func (o *RecordInMap) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *RecordInMap) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// RecordInArray is a generated struct. +type RecordInArray struct { + AString string `avro:"aString"` +} + +var schemaRecordInArray = avro.MustParse(`{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for RecordInArray. +func (o *RecordInArray) Schema() avro.Schema { + return schemaRecordInArray +} + +// Unmarshal decodes b into the receiver. +func (o *RecordInArray) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *RecordInArray) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// RecordInNullableUnion is a generated struct. +type RecordInNullableUnion struct { + AString string `avro:"aString"` +} + +var schemaRecordInNullableUnion = avro.MustParse(`{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for RecordInNullableUnion. +func (o *RecordInNullableUnion) Schema() avro.Schema { + return schemaRecordInNullableUnion +} + +// Unmarshal decodes b into the receiver. +func (o *RecordInNullableUnion) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *RecordInNullableUnion) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// Record1InNonNullableUnion is a generated struct. +type Record1InNonNullableUnion struct { + AString string `avro:"aString"` +} + +var schemaRecord1InNonNullableUnion = avro.MustParse(`{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for Record1InNonNullableUnion. +func (o *Record1InNonNullableUnion) Schema() avro.Schema { + return schemaRecord1InNonNullableUnion +} + +// Unmarshal decodes b into the receiver. +func (o *Record1InNonNullableUnion) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Record1InNonNullableUnion) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// Record2InNonNullableUnion is a generated struct. +type Record2InNonNullableUnion struct { + AString string `avro:"aString"` +} + +var schemaRecord2InNonNullableUnion = avro.MustParse(`{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for Record2InNonNullableUnion. +func (o *Record2InNonNullableUnion) Schema() avro.Schema { + return schemaRecord2InNonNullableUnion +} + +// Unmarshal decodes b into the receiver. +func (o *Record2InNonNullableUnion) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Record2InNonNullableUnion) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// Record1InNullableUnion is a generated struct. +type Record1InNullableUnion struct { + AString string `avro:"aString"` +} + +var schemaRecord1InNullableUnion = avro.MustParse(`{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for Record1InNullableUnion. +func (o *Record1InNullableUnion) Schema() avro.Schema { + return schemaRecord1InNullableUnion +} + +// Unmarshal decodes b into the receiver. +func (o *Record1InNullableUnion) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Record1InNullableUnion) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// Record2InNullableUnion is a generated struct. +type Record2InNullableUnion struct { + AString string `avro:"aString"` +} + +var schemaRecord2InNullableUnion = avro.MustParse(`{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}`) + +// Schema returns the schema for Record2InNullableUnion. +func (o *Record2InNullableUnion) Schema() avro.Schema { + return schemaRecord2InNullableUnion +} + +// Unmarshal decodes b into the receiver. +func (o *Record2InNullableUnion) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Record2InNullableUnion) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +} + +// Test represents a golden record. +type Test struct { + // aString is just a string. + AString string `avro:"aString"` + // aBoolean is just a boolean. + ABoolean bool `avro:"aBoolean"` + AnInt int `avro:"anInt"` + AFloat float32 `avro:"aFloat"` + ADouble float64 `avro:"aDouble"` + ALong int64 `avro:"aLong"` + JustBytes []byte `avro:"justBytes"` + PrimitiveNullableArrayUnion *[]string `avro:"primitiveNullableArrayUnion"` + InnerRecord InnerRecord `avro:"innerRecord"` + AnEnum string `avro:"anEnum"` + AFixed [7]byte `avro:"aFixed"` + ALogicalFixed avro.LogicalDuration `avro:"aLogicalFixed"` + AnotherLogicalFixed avro.LogicalDuration `avro:"anotherLogicalFixed"` + MapOfStrings map[string]string `avro:"mapOfStrings"` + MapOfRecords map[string]RecordInMap `avro:"mapOfRecords"` + ADate time.Time `avro:"aDate"` + ADuration time.Duration `avro:"aDuration"` + ALongTimeMicros time.Duration `avro:"aLongTimeMicros"` + ALongTimestampMillis time.Time `avro:"aLongTimestampMillis"` + ALongTimestampMicro time.Time `avro:"aLongTimestampMicro"` + ABytesDecimal *big.Rat `avro:"aBytesDecimal"` + ARecordArray []RecordInArray `avro:"aRecordArray"` + NullableRecordUnion *RecordInNullableUnion `avro:"nullableRecordUnion"` + NonNullableRecordUnion any `avro:"nonNullableRecordUnion"` + NullableRecordUnionWith3Options any `avro:"nullableRecordUnionWith3Options"` + Ref Record2InNullableUnion `avro:"ref"` + UUID string `avro:"uuid"` +} + +var schemaTest = avro.MustParse(`{"name":"a.b.test","doc":"Test represents a golden record","type":"record","fields":[{"name":"aString","doc":"aString is just a string","type":"string"},{"name":"aBoolean","doc":"aBoolean is just a boolean.","type":"boolean"},{"name":"anInt","type":"int"},{"name":"aFloat","type":"float"},{"name":"aDouble","type":"double"},{"name":"aLong","type":"long"},{"name":"justBytes","type":"bytes"},{"name":"primitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null},{"name":"innerRecord","type":{"name":"a.c.InnerRecord","type":"record","fields":[{"name":"innerJustBytes","type":"bytes"},{"name":"innerPrimitiveNullableArrayUnion","type":["null",{"type":"array","items":"string"}],"default":null}]}},{"name":"anEnum","type":{"name":"a.b.Cards","type":"enum","symbols":["SPADES","HEARTS","DIAMONDS","CLUBS"]}},{"name":"aFixed","type":{"name":"a.b.fixedField","type":"fixed","size":7}},{"name":"aLogicalFixed","type":{"name":"a.b.logicalDuration","type":"fixed","size":12,"logicalType":"duration"}},{"name":"anotherLogicalFixed","type":"a.b.logicalDuration"},{"name":"mapOfStrings","type":{"type":"map","values":"string"}},{"name":"mapOfRecords","type":{"type":"map","values":{"name":"a.b.RecordInMap","type":"record","fields":[{"name":"name","type":"string"}]}}},{"name":"aDate","type":{"type":"int","logicalType":"date"}},{"name":"aDuration","type":{"type":"int","logicalType":"time-millis"}},{"name":"aLongTimeMicros","type":{"type":"long","logicalType":"time-micros"}},{"name":"aLongTimestampMillis","type":{"type":"long","logicalType":"timestamp-millis"}},{"name":"aLongTimestampMicro","type":{"type":"long","logicalType":"timestamp-micros"}},{"name":"aBytesDecimal","type":{"type":"bytes","logicalType":"decimal","precision":4,"scale":2}},{"name":"aRecordArray","type":{"type":"array","items":{"name":"a.b.recordInArray","type":"record","fields":[{"name":"aString","type":"string"}]}}},{"name":"nullableRecordUnion","type":["null",{"name":"a.b.recordInNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"nonNullableRecordUnion","type":[{"name":"a.b.record1InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNonNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}]},{"name":"nullableRecordUnionWith3Options","type":["null",{"name":"a.b.record1InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]},{"name":"a.b.record2InNullableUnion","type":"record","fields":[{"name":"aString","type":"string"}]}],"default":null},{"name":"ref","type":"a.b.record2InNullableUnion"},{"name":"uuid","type":{"type":"string","logicalType":"uuid"}}]}`) + +// Schema returns the schema for Test. +func (o *Test) Schema() avro.Schema { + return schemaTest +} + +// Unmarshal decodes b into the receiver. +func (o *Test) Unmarshal(b []byte) error { + return avro.Unmarshal(o.Schema(), b, o) +} + +// Marshal encodes the receiver. +func (o *Test) Marshal() ([]byte, error) { + return avro.Marshal(o.Schema(), o) +}