cosmos-sdk/tx/textual/valuerenderer/enum.go
Amaury fe5b0ff4a5
feat(textual): Add Enum value renderer (#13853)
* feat(textual): Add Enum value renderer

* parse

* Update ADR

* Fix test

* Update tx/textual/internal/testpb/1.proto

Co-authored-by: Likhita Polavarapu <78951027+likhita-809@users.noreply.github.com>

Co-authored-by: Likhita Polavarapu <78951027+likhita-809@users.noreply.github.com>
2022-11-23 11:01:33 +00:00

56 lines
1.4 KiB
Go

package valuerenderer
import (
"context"
"fmt"
"google.golang.org/protobuf/reflect/protoreflect"
)
type enumValueRenderer struct {
ed protoreflect.EnumDescriptor
}
func NewEnumValueRenderer(fd protoreflect.FieldDescriptor) ValueRenderer {
ed := fd.Enum()
if ed == nil {
panic(fmt.Errorf("expected enum field, got %s", fd.Kind()))
}
return enumValueRenderer{ed: ed}
}
var _ ValueRenderer = (*enumValueRenderer)(nil)
func (er enumValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]Screen, error) {
// Get the full name of the enum variant.
evd := er.ed.Values().ByNumber(v.Enum())
if evd == nil {
return nil, fmt.Errorf("cannot get enum %s variant of number %d", er.ed.FullName(), v.Enum())
}
return []Screen{{Text: string(evd.FullName())}}, nil
}
func (er enumValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) {
if len(screens) != 1 {
return nilValue, fmt.Errorf("expected single screen: %v", screens)
}
formatted := screens[0].Text
// Loop through all enum variants until we find the one matching the
// formatted screen's one.
values := er.ed.Values()
for i := 0; i < values.Len(); i++ {
evd := values.Get(i)
if string(evd.FullName()) == formatted {
return protoreflect.ValueOfEnum(evd.Number()), nil
}
}
return nilValue, fmt.Errorf("cannot parse %s as enum on field %s", formatted, er.ed.FullName())
}