diff --git a/codec.go b/codec.go index ee5bda1..9406ddb 100644 --- a/codec.go +++ b/codec.go @@ -604,6 +604,12 @@ func (c *Codec) SchemaCRC64Avro() int64 { return int64(c.Rabin) } +// TypeName returns the name of the type described by the +// schema used to create the Codec. +func (c *Codec) TypeName() name { + return *c.typeName +} + // convert a schema data structure to a codec, prefixing with specified // namespace func buildCodec(st map[string]*Codec, enclosingNamespace string, schema interface{}, cb *codecBuilder) (*Codec, error) { diff --git a/codec_test.go b/codec_test.go index f2efe19..bafe51c 100644 --- a/codec_test.go +++ b/codec_test.go @@ -145,6 +145,87 @@ func TestCodecRabin(t *testing.T) { } } +func TestTypeName(t *testing.T) { + cases := []struct { + Schema string + expectedFullName string + expectedNamespace string + }{ + { + Schema: `"null"`, + expectedFullName: "null", + expectedNamespace: "", + }, + { + Schema: `"boolean"`, + expectedFullName: "boolean", + expectedNamespace: "", + }, + { + Schema: `"int"`, + expectedFullName: "int", + expectedNamespace: "", + }, + { + Schema: `"long"`, + expectedFullName: "long", + expectedNamespace: "", + }, + { + Schema: `"float"`, + expectedFullName: "float", + expectedNamespace: "", + }, + { + Schema: `[ "int" ]`, + expectedFullName: "union", + expectedNamespace: "", + }, + { + Schema: `[ "int" , {"type":"boolean"} ]`, + expectedFullName: "union", + expectedNamespace: "", + }, + { + Schema: `{"fields":[], "type":"record", "name":"foo"}`, + expectedFullName: "foo", + expectedNamespace: "", + }, + { + Schema: `{"type":"enum", "name":"foo", "symbols":["A1"]}`, + expectedFullName: "foo", + expectedNamespace: "", + }, + { + Schema: `{"name":"foo","type":"fixed","size":15}`, + expectedFullName: "foo", + expectedNamespace: "", + }, + { + Schema: `{"fields":[], "type":"record", "name":"foo", "namespace":"x.y"}`, + expectedFullName: "foo", + expectedNamespace: "x.y", + }, + { + Schema: `{"namespace":"x.y.z", "type":"enum", "name":"foo", "doc":"foo bar", "symbols":["A1", "A2"]}`, + expectedFullName: "foo", + expectedNamespace: "x.y.z", + }, + } + + for _, c := range cases { + codec, err := NewCodec(c.Schema) + if err != nil { + t.Fatalf("CASE: %s; cannot create codec: %s", c.Schema, err) + } + typeName := codec.TypeName() + expected, _ := newName(c.expectedFullName, c.expectedNamespace, "") + if typeName != *expected { + t.Errorf("CASE: %s; GOT: %s; WANT: %s", c.Schema, codec.TypeName(), *expected) + } + } +} + func TestSingleObjectEncoding(t *testing.T) { t.Run("int", func(*testing.T) { schema := `"int"` diff --git a/name.go b/name.go index 234823d..b0d971a 100644 --- a/name.go +++ b/name.go @@ -141,3 +141,9 @@ func (n *name) short() string { } return n.fullName } + +// Shortname returns the name without the prefixed namespace. +// This uses the short method underneath but is visible outside the package. +func (n *name) ShortName() string { + return n.short() +} diff --git a/name_test.go b/name_test.go index afb4483..7bd9bee 100644 --- a/name_test.go +++ b/name_test.go @@ -12,6 +12,7 @@ package goavro // NOTE: part of goavro package because it tests private functionality import ( + "fmt" "testing" ) @@ -98,3 +99,26 @@ func TestNewNameFromSchemaMap(t *testing.T) { t.Errorf("GOT: %q; WANT: %q", got, want) } } + +func TestShortName(t *testing.T) { + cases := []struct { + name string + namespace string + want string + }{ + {"bar", "", "bar"}, + {"foo", "org.bar", "foo"}, + {"bar.foo", "org", "foo"}, + } + + for _, c := range cases { + n, err := newName(c.name, c.namespace, nullNamespace) + if err != nil { + t.Fatal(err) + } + fmt.Printf("n: %#v fullName: %v shortName: %v\n", n, n.String(), n.ShortName()) + if actual, expected := n.ShortName(), c.want; actual != expected { + t.Errorf("GOT: %#v; WANT: %#v", actual, expected) + } + } +}