// MapItemList generates a new MapItemList type alias for the given map. // // The following is generated: // // type $mapItemListName map[$keyType]$valueType // // func (v $mapItemListName) ForEach(f func(wire.MapItem) error) error { ... } // // func (v $mapItemListName) Close() { ... } // // And $mapItemListName is returned. This may be used where a MapItemList of the // given type is expected. func (m *mapGenerator) ItemList(g Generator, spec *compile.MapSpec) (string, error) { // TODO(abg): Unhashable types name := "_" + valueName(spec) + "_MapItemList" if m.HasLazyList(name) { return name, nil } err := g.DeclareFromTemplate( ` <$wire := import "go.uber.org/thriftrw/wire"> type <.Name> <typeReference .Spec> <$m := newVar "m"> <$f := newVar "f"> <$k := newVar "k"> <$v := newVar "v"> <$i := newVar "i"> <$kw := newVar "kw"> <$vw := newVar "vw"> func (<$m> <.Name>) ForEach(<$f> func(<$wire>.MapItem) error) error { <if isHashable .Spec.KeySpec> for <$k>, <$v> := range <$m> { <else> for _, <$i> := range <$m> { <$k> := <$i>.Key <$v> := <$i>.Value <end> <if not (isPrimitiveType .Spec.KeySpec)> if <$k> == nil { return <import "fmt">.Errorf("invalid map key: value is nil") } <end> <if not (isPrimitiveType .Spec.ValueSpec)> if <$v> == nil { return <import "fmt">.Errorf("invalid [%v]: value is nil", <$k>) } <end> <$kw>, err := <toWire .Spec.KeySpec $k> if err != nil { // TODO(abg): nested error "invalid map key: %v" return err } <$vw>, err := <toWire .Spec.ValueSpec $v> if err != nil { // TODO(abg): nested error "invalid [%v]: %v" return err } err = <$f>(<$wire>.MapItem{Key: <$kw>, Value: <$vw>}) if err != nil { return err } } return nil } func (<$m> <.Name>) Size() int { return len(<$m>) } func (<.Name>) KeyType() <$wire>.Type { return <typeCode .Spec.KeySpec> } func (<.Name>) ValueType() <$wire>.Type { return <typeCode .Spec.ValueSpec> } func (<.Name>) Close() {} `, struct { Name string Spec *compile.MapSpec }{Name: name, Spec: spec}, ) return name, wrapGenerateError(spec.ThriftName(), err) }
func (m *mapGenerator) Reader(g Generator, spec *compile.MapSpec) (string, error) { name := "_" + valueName(spec) + "_Read" if m.HasReader(name) { return name, nil } err := g.DeclareFromTemplate( ` <$wire := import "go.uber.org/thriftrw/wire"> <$mapType := typeReference .Spec> <$m := newVar "m"> <$o := newVar "o"> <$x := newVar "x"> <$k := newVar "k"> <$v := newVar "v"> func <.Name>(<$m> <$wire>.MapItemList) (<$mapType>, error) { if <$m>.KeyType() != <typeCode .Spec.KeySpec> { return nil, nil } if <$m>.ValueType() != <typeCode .Spec.ValueSpec> { return nil, nil } <if isHashable .Spec.KeySpec> <$o> := make(<$mapType>, <$m>.Size()) <else> <$o> := make(<$mapType>, 0, <$m>.Size()) <end> err := <$m>.ForEach(func(<$x> <$wire>.MapItem) error { <$k>, err := <fromWire .Spec.KeySpec (printf "%s.Key" $x)> if err != nil { return err } <$v>, err := <fromWire .Spec.ValueSpec (printf "%s.Value" $x)> if err != nil { return err } <if isHashable .Spec.KeySpec> <$o>[<$k>] = <$v> <else> <$o> = append(<$o>, struct { Key <typeReference .Spec.KeySpec> Value <typeReference .Spec.ValueSpec> }{<$k>, <$v>}) <end> return nil }) <$m>.Close() return <$o>, err } `, struct { Name string Spec *compile.MapSpec }{Name: name, Spec: spec}, ) return name, wrapGenerateError(spec.ThriftName(), err) }