Skip to content
Open
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
8 changes: 7 additions & 1 deletion codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ var (
MaxBlockSize = int64(math.MaxInt32)
)

type CodecModifier func(map[string]*Codec)

// Codec supports decoding binary and text Avro data to Go native data types,
// and conversely encoding Go native data types to binary or text Avro data. A
// Codec is created as a stateless structure that can be safely used in multiple
Expand Down Expand Up @@ -86,7 +88,7 @@ type Codec struct {
// if err != nil {
// fmt.Println(err)
// }
func NewCodec(schemaSpecification string) (*Codec, error) {
func NewCodec(schemaSpecification string, modifiers ...CodecModifier) (*Codec, error) {
var schema interface{}

if err := json.Unmarshal([]byte(schemaSpecification), &schema); err != nil {
Expand All @@ -96,6 +98,10 @@ func NewCodec(schemaSpecification string) (*Codec, error) {
// bootstrap a symbol table with primitive type codecs for the new codec
st := newSymbolTable()

for _, modifier := range modifiers {
modifier(st)
}

c, err := buildCodec(st, nullNamespace, schema)
if err != nil {
return nil, err
Expand Down
76 changes: 76 additions & 0 deletions record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,82 @@ func TestRecordRecursiveRoundTrip(t *testing.T) {
}
}

func TestUnknownTypeCodecError(t *testing.T) {
_, err := NewCodec(`
{
"type": "record",
"name": "Parent",
"fields" : [
{"name": "child", "type": "Child"}
]
}
`)
ensureError(t, err, "Record \"Parent\" field 1 ought to be valid Avro named type: unknown type name: \"Child\"")
}

func TestCodecModifier(t *testing.T) {
childCodec, err := NewCodec(`
{
"type": "record",
"name": "Child",
"fields" : [
{"name": "age", "type": "int"}
]
}
`)
ensureError(t, err)

modifier := func(st map[string]*Codec) {
st["Child"] = childCodec
}

codec, err := NewCodec(`
{
"type": "record",
"name": "Parent",
"fields" : [
{"name": "child", "type": "Child"}
]
}
`, modifier)
ensureError(t, err)

child := map[string]interface{} {
"age": 7,
}
parent := map[string]interface{} {
"child": child,
}

// Convert native Go form to binary Avro data
buf, err := codec.BinaryFromNative(nil, parent)
ensureError(t, err)

// Convert binary Avro data back to native Go form
datum, _, err := codec.NativeFromBinary(buf)
ensureError(t, err)

actual, ok := datum.(map[string]interface{})
if !ok {
t.Fatalf("origin data contaminated")
}

child, ok = actual["child"].(map[string]interface{})
if !ok {
t.Fatalf("child type contaminated")
}

age, ok := child["age"].(int32)
if !ok {
t.Fatalf("child age field contaminated")
}

if age != 7 {
t.Fatalf("child age data contaminated")
}
}


func ExampleRecordRecursiveRoundTrip() {
codec, err := NewCodec(`
{
Expand Down