Пример #1
0
// ValueList generates a new ValueList type alias for the given set.
//
// The following is generated:
//
// 	type $valueListName map[$valueType]struct{}
//
// 	func (v $valueListName) ForEach(f func(wire.Value) error) error { ... }
//
// 	func (v $valueListName) Close() { ... }
//
// And $valueListName is returned. This may be used where a ValueList of the
// given type is expected.
func (s *setGenerator) ValueList(g Generator, spec *compile.SetSpec) (string, error) {
	// TODO(abg): Unhashable types
	name := "_" + valueName(spec) + "_ValueList"
	if s.HasLazyList(name) {
		return name, nil
	}

	err := g.DeclareFromTemplate(
		`
			<$wire := import "go.uber.org/thriftrw/wire">
			type <.Name> <typeReference .Spec>

			<$v := newVar "v">
			<$x := newVar "x">
			<$f := newVar "f">
			<$w := newVar "w">
			func (<$v> <.Name>) ForEach(<$f> func(<$wire>.Value) error) error {
				<if isHashable .Spec.ValueSpec>
					for <$x> := range <$v> {
				<else>
					for _, <$x> := range <$v> {
				<end>
						<if not (isPrimitiveType .Spec.ValueSpec)>
							if <$x> == nil {
								return <import "fmt">.Errorf("invalid set item: value is nil")
							}
						<end>

						<$w>, err := <toWire .Spec.ValueSpec $x>
						if err != nil {
							// TODO(abg): nested error "invalid set item: %v"
							return err
						}
						err = <$f>(<$w>)
						if err != nil {
							return err
						}
					}
				return nil
			}

			func (<$v> <.Name>) Size() int {
				return len(<$v>)
			}

			func (<.Name>) ValueType() <$wire>.Type {
				return <typeCode .Spec.ValueSpec>
			}

			func (<.Name>) Close() {}
		`,
		struct {
			Name string
			Spec *compile.SetSpec
		}{Name: name, Spec: spec},
	)

	return name, wrapGenerateError(spec.ThriftName(), err)
}
Пример #2
0
func (s *setGenerator) Reader(g Generator, spec *compile.SetSpec) (string, error) {
	name := "_" + valueName(spec) + "_Read"
	if s.HasReader(name) {
		return name, nil
	}

	err := g.DeclareFromTemplate(
		`
			<$wire := import "go.uber.org/thriftrw/wire">
			<$setType := typeReference .Spec>

			<$s := newVar "s">
			<$i := newVar "i">
			<$o := newVar "o">
			<$x := newVar "x">
			func <.Name>(<$s> <$wire>.ValueList) (<$setType>, error) {
				if <$s>.ValueType() != <typeCode .Spec.ValueSpec> {
					return nil, nil
				}

				<if isHashable .Spec.ValueSpec>
					<$o> := make(<$setType>, <$s>.Size())
				<else>
					<$o> := make(<$setType>, 0, <$s>.Size())
				<end>
				err := <$s>.ForEach(func(<$x> <$wire>.Value) error {
					<$i>, err := <fromWire .Spec.ValueSpec $x>
					if err != nil {
						return err
					}
					<if isHashable .Spec.ValueSpec>
						<$o>[<$i>] = struct{}{}
					<else>
						<$o> = append(<$o>, <$i>)
					<end>
					return nil
				})
				<$s>.Close()
				return <$o>, err
			}
		`,
		struct {
			Name string
			Spec *compile.SetSpec
		}{Name: name, Spec: spec},
	)

	return name, wrapGenerateError(spec.ThriftName(), err)
}