From af9b7d6a62fbf0d9246dd2f774f2e5bc72d0c253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gianguido=20Sor=C3=A0?= Date: Tue, 12 May 2020 18:50:21 +0200 Subject: [PATCH 1/2] add codec method to retrieve a Go type registered name Given a codec, users might want to know what's the Amino type associated with a given struct instance. This commit adds the functionality needed to do that, for both instance and pointer-to-instance types. Nil interfaces are rejected by default. Method completed with tests. --- codec.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/codec.go b/codec.go index b8b4c9b6..a063f513 100644 --- a/codec.go +++ b/codec.go @@ -308,6 +308,30 @@ func (cdc *Codec) PrintTypes(out io.Writer) error { return nil } +// ConcreteRegisteredName returns the name under which i has been registered. +func (cdc *Codec) ConcreteRegisteredName(i interface{}) (string, error) { + cdc.mtx.RLock() + defer cdc.mtx.RUnlock() + + if i == nil { + return "", errors.New("argument must not be nil") + } + + gt := reflect.TypeOf(i) + + // if i is a non-nil pointer, dereference it and grab its inner Elem + if gt.Kind() == reflect.Ptr { + gt = gt.Elem() + } + + ct, ok := cdc.typeInfos[gt] + if !ok { + return "", fmt.Errorf("no type registered for %s", gt.String()) + } + + return ct.Name, nil +} + // A heuristic to guess the size of a registered type and return it as a string. // If the size is not fixed it returns "variable". func getLengthStr(info *TypeInfo) string { From d963179238ea91afc05f59b5f33514844b082dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gianguido=20Sor=C3=A0?= Date: Tue, 12 May 2020 18:57:15 +0200 Subject: [PATCH 2/2] add tests --- codec_test.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/codec_test.go b/codec_test.go index 6a700269..167dc4fd 100644 --- a/codec_test.go +++ b/codec_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - amino "github.com/tendermint/go-amino" + "github.com/tendermint/go-amino" ) type SimpleStruct struct { @@ -250,3 +250,33 @@ func TestCodecSeal(t *testing.T) { assert.Panics(t, func() { cdc.RegisterInterface((*Bar)(nil), nil) }) assert.Panics(t, func() { cdc.RegisterConcrete(int(0), "int", nil) }) } + +func TestCodec_RegisteredName(t *testing.T) { + aminoStructType := "tendermint/SimpleStruct" + + // Struct is registered + cdc := amino.NewCodec() + cdc.RegisterConcrete(SimpleStruct{}, aminoStructType, nil) + rn, err := cdc.ConcreteRegisteredName(SimpleStruct{}) + require.NoError(t, err) + require.Equal(t, aminoStructType, rn) + + // Struct is not registered + cdc = amino.NewCodec() + rn, err = cdc.ConcreteRegisteredName(SimpleStruct{}) + require.Error(t, err) + require.Empty(t, rn) + + // Struct is pointer + cdc = amino.NewCodec() + cdc.RegisterConcrete(SimpleStruct{}, aminoStructType, nil) + rn, err = cdc.ConcreteRegisteredName(&SimpleStruct{}) + require.NoError(t, err) + require.Equal(t, aminoStructType, rn) + + // Struct is nil pointer + cdc = amino.NewCodec() + rn, err = cdc.ConcreteRegisteredName(nil) + require.Error(t, err) + require.Empty(t, rn) +}