 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			1125 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1125 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package bindnode
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/ipld/go-ipld-prime/datamodel"
 | |
| 	"github.com/ipld/go-ipld-prime/node/basicnode"
 | |
| 	"github.com/ipld/go-ipld-prime/schema"
 | |
| )
 | |
| 
 | |
| func reprNode(node datamodel.Node) datamodel.Node {
 | |
| 	if node, ok := node.(schema.TypedNode); ok {
 | |
| 		return node.Representation()
 | |
| 	}
 | |
| 	// datamodel.Absent and datamodel.Null are not typed.
 | |
| 	// TODO: is this a problem? surely a typed struct's fields are always
 | |
| 	// typed, even when absent or null.
 | |
| 	return node
 | |
| }
 | |
| 
 | |
| func reprStrategy(typ schema.Type) interface{} {
 | |
| 	// Can't use an interface check, as each method has a different result type.
 | |
| 	// TODO: consider inlining this type switch at each call site,
 | |
| 	// as the call sites need the underlying schema.Type too.
 | |
| 	switch typ := typ.(type) {
 | |
| 	case *schema.TypeStruct:
 | |
| 		return typ.RepresentationStrategy()
 | |
| 	case *schema.TypeUnion:
 | |
| 		return typ.RepresentationStrategy()
 | |
| 	case *schema.TypeEnum:
 | |
| 		return typ.RepresentationStrategy()
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type _prototypeRepr _prototype
 | |
| 
 | |
| func (w *_prototypeRepr) NewBuilder() datamodel.NodeBuilder {
 | |
| 	return &_builderRepr{_assemblerRepr{
 | |
| 		cfg:        w.cfg,
 | |
| 		schemaType: w.schemaType,
 | |
| 		val:        reflect.New(w.goType).Elem(),
 | |
| 	}}
 | |
| }
 | |
| 
 | |
| type _nodeRepr _node
 | |
| 
 | |
| func (w *_nodeRepr) Kind() datamodel.Kind {
 | |
| 	switch reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Stringjoin:
 | |
| 		return datamodel.Kind_String
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		return datamodel.Kind_Map
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		return datamodel.Kind_List
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		return datamodel.Kind_Map
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		haveIdx, _ := unionMember(w.val)
 | |
| 		if haveIdx < 0 {
 | |
| 			panic(fmt.Sprintf("bindnode: kinded union %s has no member", w.val.Type()))
 | |
| 		}
 | |
| 		mtyp := w.schemaType.(*schema.TypeUnion).Members()[haveIdx]
 | |
| 		return mtyp.RepresentationBehavior()
 | |
| 	case schema.UnionRepresentation_Stringprefix:
 | |
| 		return datamodel.Kind_String
 | |
| 	case schema.EnumRepresentation_Int:
 | |
| 		return datamodel.Kind_Int
 | |
| 	case schema.EnumRepresentation_String:
 | |
| 		return datamodel.Kind_String
 | |
| 	default:
 | |
| 		return (*_node)(w).Kind()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func outboundMappedKey(stg schema.StructRepresentation_Map, key string) string {
 | |
| 	// TODO: why doesn't stg just allow us to "get" by the key string?
 | |
| 	field := schema.SpawnStructField(key, "", false, false)
 | |
| 	mappedKey := stg.GetFieldKey(field)
 | |
| 	return mappedKey
 | |
| }
 | |
| 
 | |
| func inboundMappedKey(typ *schema.TypeStruct, stg schema.StructRepresentation_Map, key string) string {
 | |
| 	// TODO: can't do a "reverse" lookup... needs better API probably.
 | |
| 	fields := typ.Fields()
 | |
| 	for _, field := range fields {
 | |
| 		mappedKey := stg.GetFieldKey(field)
 | |
| 		if key == mappedKey {
 | |
| 			return field.Name()
 | |
| 		}
 | |
| 	}
 | |
| 	return key // fallback to the same key
 | |
| }
 | |
| 
 | |
| func outboundMappedType(stg schema.UnionRepresentation_Keyed, key string) string {
 | |
| 	// TODO: why doesn't stg just allow us to "get" by the key string?
 | |
| 	typ := schema.SpawnBool(key)
 | |
| 	mappedKey := stg.GetDiscriminant(typ)
 | |
| 	return mappedKey
 | |
| }
 | |
| 
 | |
| func inboundMappedType(typ *schema.TypeUnion, stg schema.UnionRepresentation_Keyed, key string) string {
 | |
| 	// TODO: can't do a "reverse" lookup... needs better API probably.
 | |
| 	for _, member := range typ.Members() {
 | |
| 		mappedKey := stg.GetDiscriminant(member)
 | |
| 		if key == mappedKey {
 | |
| 			// println(key, "rev-mapped to", field.Name())
 | |
| 			return member.Name()
 | |
| 		}
 | |
| 	}
 | |
| 	// println(key, "had no mapping")
 | |
| 	return key // fallback to the same key
 | |
| }
 | |
| 
 | |
| // asKinded can be called on a kinded union node to obtain a node
 | |
| // representing one of its members, identified by kind.
 | |
| func (w *_nodeRepr) asKinded(stg schema.UnionRepresentation_Kinded, kind datamodel.Kind) *_nodeRepr {
 | |
| 	name := stg.GetMember(kind)
 | |
| 	members := w.schemaType.(*schema.TypeUnion).Members()
 | |
| 	for i, member := range members {
 | |
| 		if member.Name() != name {
 | |
| 			continue
 | |
| 		}
 | |
| 		w2 := *w
 | |
| 		w2.val = w.val.Field(i).Elem()
 | |
| 		w2.schemaType = member
 | |
| 		return &w2
 | |
| 	}
 | |
| 	panic("bindnode TODO: GetMember result is missing?")
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) LookupByString(key string) (datamodel.Node, error) {
 | |
| 	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
 | |
| 		w = w.asKinded(stg, datamodel.Kind_Map)
 | |
| 	}
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		revKey := inboundMappedKey(w.schemaType.(*schema.TypeStruct), stg, key)
 | |
| 		v, err := (*_node)(w).LookupByString(revKey)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return reprNode(v), nil
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		revKey := inboundMappedType(w.schemaType.(*schema.TypeUnion), stg, key)
 | |
| 		v, err := (*_node)(w).LookupByString(revKey)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return reprNode(v), nil
 | |
| 	default:
 | |
| 		v, err := (*_node)(w).LookupByString(key)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return reprNode(v), nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) LookupByIndex(idx int64) (datamodel.Node, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_List).LookupByIndex(idx)
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		fields := w.schemaType.(*schema.TypeStruct).Fields()
 | |
| 		if idx < 0 || int(idx) >= len(fields) {
 | |
| 			return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
 | |
| 		}
 | |
| 		field := fields[idx]
 | |
| 		v, err := (*_node)(w).LookupByString(field.Name())
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return reprNode(v), nil
 | |
| 	default:
 | |
| 		v, err := (*_node)(w).LookupByIndex(idx)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return reprNode(v), nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, error) {
 | |
| 	switch w.Kind() {
 | |
| 	case datamodel.Kind_Map:
 | |
| 		return w.LookupByString(seg.String())
 | |
| 	case datamodel.Kind_List:
 | |
| 		idx, err := seg.Index()
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return w.LookupByIndex(idx)
 | |
| 	}
 | |
| 	return nil, datamodel.ErrWrongKind{
 | |
| 		TypeName:        w.schemaType.Name(),
 | |
| 		MethodName:      "LookupBySegment",
 | |
| 		AppropriateKind: datamodel.KindSet_Recursive,
 | |
| 		ActualKind:      w.Kind(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) LookupByNode(key datamodel.Node) (datamodel.Node, error) {
 | |
| 	switch w.Kind() {
 | |
| 	case datamodel.Kind_Map:
 | |
| 		s, err := key.AsString()
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return w.LookupByString(s)
 | |
| 	case datamodel.Kind_List:
 | |
| 		i, err := key.AsInt()
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return w.LookupByIndex(i)
 | |
| 	}
 | |
| 	return nil, datamodel.ErrWrongKind{
 | |
| 		TypeName:        w.schemaType.Name(),
 | |
| 		MethodName:      "LookupByNode",
 | |
| 		AppropriateKind: datamodel.KindSet_Recursive,
 | |
| 		ActualKind:      w.Kind(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) MapIterator() datamodel.MapIterator {
 | |
| 	// TODO: we can try to reuse reprStrategy here and elsewhere
 | |
| 	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
 | |
| 		w = w.asKinded(stg, datamodel.Kind_Map)
 | |
| 	}
 | |
| 	switch reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		itr := (*_node)(w).MapIterator().(*_structIterator)
 | |
| 		// When we reach the last non-absent field, we should stop.
 | |
| 		itr.reprEnd = int(w.lengthMinusTrailingAbsents())
 | |
| 		return (*_structIteratorRepr)(itr)
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		itr := (*_node)(w).MapIterator().(*_unionIterator)
 | |
| 		return (*_unionIteratorRepr)(itr)
 | |
| 	default:
 | |
| 		iter, _ := (*_node)(w).MapIterator().(*_mapIterator)
 | |
| 		if iter == nil {
 | |
| 			return nil
 | |
| 		}
 | |
| 		return (*_mapIteratorRepr)(iter)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type _mapIteratorRepr _mapIterator
 | |
| 
 | |
| func (w *_mapIteratorRepr) Next() (key, value datamodel.Node, _ error) {
 | |
| 	k, v, err := (*_mapIterator)(w).Next()
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 	return reprNode(k), reprNode(v), nil
 | |
| }
 | |
| 
 | |
| func (w *_mapIteratorRepr) Done() bool {
 | |
| 	return w.nextIndex >= w.keysVal.Len()
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) ListIterator() datamodel.ListIterator {
 | |
| 	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
 | |
| 		w = w.asKinded(stg, datamodel.Kind_List)
 | |
| 	}
 | |
| 	switch reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		typ := w.schemaType.(*schema.TypeStruct)
 | |
| 		iter := _tupleIteratorRepr{cfg: w.cfg, schemaType: typ, fields: typ.Fields(), val: w.val}
 | |
| 		iter.reprEnd = int(w.lengthMinusTrailingAbsents())
 | |
| 		return &iter
 | |
| 	default:
 | |
| 		iter, _ := (*_node)(w).ListIterator().(*_listIterator)
 | |
| 		if iter == nil {
 | |
| 			return nil
 | |
| 		}
 | |
| 		return (*_listIteratorRepr)(iter)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type _listIteratorRepr _listIterator
 | |
| 
 | |
| func (w *_listIteratorRepr) Next() (index int64, value datamodel.Node, _ error) {
 | |
| 	idx, v, err := (*_listIterator)(w).Next()
 | |
| 	if err != nil {
 | |
| 		return idx, nil, err
 | |
| 	}
 | |
| 	return idx, reprNode(v), nil
 | |
| }
 | |
| 
 | |
| func (w *_listIteratorRepr) Done() bool {
 | |
| 	return w.nextIndex >= w.val.Len()
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) lengthMinusAbsents() int64 {
 | |
| 	fields := w.schemaType.(*schema.TypeStruct).Fields()
 | |
| 	n := int64(len(fields))
 | |
| 	for i, field := range fields {
 | |
| 		if field.IsOptional() && w.val.Field(i).IsNil() {
 | |
| 			n--
 | |
| 		}
 | |
| 	}
 | |
| 	return n
 | |
| }
 | |
| 
 | |
| type _tupleIteratorRepr struct {
 | |
| 	// TODO: support embedded fields?
 | |
| 	cfg        config
 | |
| 	schemaType *schema.TypeStruct
 | |
| 	fields     []schema.StructField
 | |
| 	val        reflect.Value // non-pointer
 | |
| 	nextIndex  int
 | |
| 
 | |
| 	// these are only used in repr.go
 | |
| 	reprEnd int
 | |
| }
 | |
| 
 | |
| func (w *_tupleIteratorRepr) Next() (index int64, value datamodel.Node, _ error) {
 | |
| _skipAbsent:
 | |
| 	_, value, err := (*_structIterator)(w).Next()
 | |
| 	if err != nil {
 | |
| 		return 0, nil, err
 | |
| 	}
 | |
| 	if w.nextIndex > w.reprEnd {
 | |
| 		goto _skipAbsent
 | |
| 	}
 | |
| 	return int64(w.nextIndex), reprNode(value), nil
 | |
| }
 | |
| 
 | |
| func (w *_tupleIteratorRepr) Done() bool {
 | |
| 	return w.nextIndex >= w.reprEnd
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) lengthMinusTrailingAbsents() int64 {
 | |
| 	fields := w.schemaType.(*schema.TypeStruct).Fields()
 | |
| 	for i := len(fields) - 1; i >= 0; i-- {
 | |
| 		field := fields[i]
 | |
| 		if !field.IsOptional() || !w.val.Field(i).IsNil() {
 | |
| 			return int64(i + 1)
 | |
| 		}
 | |
| 	}
 | |
| 	return 0
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) Length() int64 {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Stringjoin:
 | |
| 		return -1
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		return w.lengthMinusAbsents()
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		return w.lengthMinusTrailingAbsents()
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		return (*_node)(w).Length()
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		w = w.asKinded(stg, w.Kind())
 | |
| 		return (*_node)(w).Length()
 | |
| 	default:
 | |
| 		return (*_node)(w).Length()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) IsAbsent() bool {
 | |
| 	if reprStrategy(w.schemaType) == nil {
 | |
| 		return (*_node)(w).IsAbsent()
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) IsNull() bool {
 | |
| 	if reprStrategy(w.schemaType) == nil {
 | |
| 		return (*_node)(w).IsNull()
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsBool() (bool, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Bool).AsBool()
 | |
| 	default:
 | |
| 		return (*_node)(w).AsBool()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsInt() (int64, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Int).AsInt()
 | |
| 	case schema.EnumRepresentation_Int:
 | |
| 		kind := w.val.Kind()
 | |
| 		if kind == reflect.String {
 | |
| 			s, err := (*_node)(w).AsString()
 | |
| 			if err != nil {
 | |
| 				return 0, err
 | |
| 			}
 | |
| 			mapped, ok := stg[s]
 | |
| 			if !ok {
 | |
| 				// We assume that the schema strategy is correct,
 | |
| 				// so we can only fail if the stored string isn't a valid member.
 | |
| 				return 0, fmt.Errorf("AsInt: %q is not a valid member of enum %s", s, w.schemaType.Name())
 | |
| 			}
 | |
| 			// TODO: the strategy type should probably use int64 rather than int
 | |
| 			return int64(mapped), nil
 | |
| 		}
 | |
| 		var i int
 | |
| 		// TODO: check for overflows
 | |
| 		if kindInt[kind] {
 | |
| 			i = int(w.val.Int())
 | |
| 		} else if kindUint[kind] {
 | |
| 			i = int(w.val.Uint())
 | |
| 		} else {
 | |
| 			return 0, fmt.Errorf("AsInt: unexpected kind: %s", kind)
 | |
| 		}
 | |
| 		for _, reprInt := range stg {
 | |
| 			if reprInt == i {
 | |
| 				return int64(i), nil
 | |
| 			}
 | |
| 		}
 | |
| 		// We assume that the schema strategy is correct,
 | |
| 		// so we can only fail if the stored string isn't a valid member.
 | |
| 		return 0, fmt.Errorf("AsInt: %d is not a valid member of enum %s", i, w.schemaType.Name())
 | |
| 	default:
 | |
| 		return (*_node)(w).AsInt()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsFloat() (float64, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Float).AsFloat()
 | |
| 	default:
 | |
| 		return (*_node)(w).AsFloat()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsString() (string, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Stringjoin:
 | |
| 		var b strings.Builder
 | |
| 		itr := (*_node)(w).MapIterator()
 | |
| 		first := true
 | |
| 		for !itr.Done() {
 | |
| 			_, v, err := itr.Next()
 | |
| 			if err != nil {
 | |
| 				return "", err
 | |
| 			}
 | |
| 			s, err := reprNode(v).AsString()
 | |
| 			if err != nil {
 | |
| 				return "", err
 | |
| 			}
 | |
| 			if first {
 | |
| 				first = false
 | |
| 			} else {
 | |
| 				b.WriteString(stg.GetDelim())
 | |
| 			}
 | |
| 			b.WriteString(s)
 | |
| 		}
 | |
| 		return b.String(), nil
 | |
| 	case schema.UnionRepresentation_Stringprefix:
 | |
| 		haveIdx, mval := unionMember(w.val)
 | |
| 		mtyp := w.schemaType.(*schema.TypeUnion).Members()[haveIdx]
 | |
| 
 | |
| 		w2 := *w
 | |
| 		w2.val = mval
 | |
| 		w2.schemaType = mtyp
 | |
| 		s, err := w2.AsString()
 | |
| 		if err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 
 | |
| 		name := stg.GetDiscriminant(mtyp)
 | |
| 		return name + stg.GetDelim() + s, nil
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_String).AsString()
 | |
| 	case schema.EnumRepresentation_String:
 | |
| 		s, err := (*_node)(w).AsString()
 | |
| 		if err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 		if mapped := stg[s]; mapped != "" {
 | |
| 			return mapped, nil
 | |
| 		}
 | |
| 		members := w.schemaType.(*schema.TypeEnum).Members()
 | |
| 		for _, member := range members {
 | |
| 			if s == member {
 | |
| 				return s, nil
 | |
| 			}
 | |
| 		}
 | |
| 		for k, v := range stg {
 | |
| 			// a programming error? we may have the enum string value rather than the type
 | |
| 			if v == s {
 | |
| 				return "", fmt.Errorf("AsString: %q is not a valid member of enum %s (bindnode works at the type level; did you mean %q?)", s, w.schemaType.Name(), k)
 | |
| 			}
 | |
| 		}
 | |
| 		return "", fmt.Errorf("AsString: %q is not a valid member of enum %s", s, w.schemaType.Name())
 | |
| 	default:
 | |
| 		return (*_node)(w).AsString()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsBytes() ([]byte, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Bytes).AsBytes()
 | |
| 	default:
 | |
| 		return (*_node)(w).AsBytes()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) AsLink() (datamodel.Link, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Link).AsLink()
 | |
| 	default:
 | |
| 		return (*_node)(w).AsLink()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_nodeRepr) Prototype() datamodel.NodePrototype {
 | |
| 	return (*_prototypeRepr)((*_node)(w).Prototype().(*_prototype))
 | |
| }
 | |
| 
 | |
| type _builderRepr struct {
 | |
| 	_assemblerRepr
 | |
| }
 | |
| 
 | |
| // TODO: returning a repr node here is probably good, but there's a gotcha: one
 | |
| // can go from a typed node to a repr node via the Representation method, but
 | |
| // not the other way. That's probably why codegen returns a typed node here.
 | |
| // The solution might be to add a way to go from the repr node to its parent
 | |
| // typed node.
 | |
| 
 | |
| func (w *_builderRepr) Build() datamodel.Node {
 | |
| 	// TODO: see the notes above.
 | |
| 	// return &_nodeRepr{schemaType: w.schemaType, val: w.val}
 | |
| 	return &_node{cfg: w.cfg, schemaType: w.schemaType, val: w.val}
 | |
| }
 | |
| 
 | |
| func (w *_builderRepr) Reset() {
 | |
| 	panic("bindnode TODO: Reset")
 | |
| }
 | |
| 
 | |
| type _assemblerRepr struct {
 | |
| 	cfg        config
 | |
| 	schemaType schema.Type
 | |
| 	val        reflect.Value // non-pointer
 | |
| 	finish     func() error
 | |
| 
 | |
| 	nullable bool
 | |
| }
 | |
| 
 | |
| func assemblerRepr(am datamodel.NodeAssembler) datamodel.NodeAssembler {
 | |
| 	switch am := am.(type) {
 | |
| 	case *_assembler:
 | |
| 		return (*_assemblerRepr)(am)
 | |
| 	case _errorAssembler:
 | |
| 		return am
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("unexpected NodeAssembler type: %T", am))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) asKinded(stg schema.UnionRepresentation_Kinded, kind datamodel.Kind) datamodel.NodeAssembler {
 | |
| 	name := stg.GetMember(kind)
 | |
| 	members := w.schemaType.(*schema.TypeUnion).Members()
 | |
| 	kindSet := make([]datamodel.Kind, 0, len(members))
 | |
| 	for idx, member := range members {
 | |
| 		if member.Name() != name {
 | |
| 			kindSet = append(kindSet, member.RepresentationBehavior())
 | |
| 			continue
 | |
| 		}
 | |
| 		w2 := *w
 | |
| 		goType := w.val.Field(idx).Type().Elem()
 | |
| 		valPtr := reflect.New(goType)
 | |
| 		w2.val = valPtr.Elem()
 | |
| 		w2.schemaType = member
 | |
| 
 | |
| 		// Layer a new finish func on top, to set Index/Value.
 | |
| 		w2.finish = func() error {
 | |
| 			unionSetMember(w.val, idx, valPtr)
 | |
| 			if w.finish != nil {
 | |
| 				if err := w.finish(); err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 			}
 | |
| 			return nil
 | |
| 		}
 | |
| 		return &w2
 | |
| 	}
 | |
| 	return _errorAssembler{datamodel.ErrWrongKind{
 | |
| 		TypeName:        w.schemaType.Name() + ".Repr",
 | |
| 		MethodName:      "", // TODO: we could fill it via runtime.Callers
 | |
| 		AppropriateKind: datamodel.KindSet(kindSet),
 | |
| 		ActualKind:      kind,
 | |
| 	}}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) BeginMap(sizeHint int64) (datamodel.MapAssembler, error) {
 | |
| 	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
 | |
| 		return w.asKinded(stg, datamodel.Kind_Map).BeginMap(sizeHint)
 | |
| 	}
 | |
| 	asm, err := (*_assembler)(w).BeginMap(sizeHint)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	switch asm := asm.(type) {
 | |
| 	case *_structAssembler:
 | |
| 		return (*_structAssemblerRepr)(asm), nil
 | |
| 	case *_mapAssembler:
 | |
| 		return (*_mapAssemblerRepr)(asm), nil
 | |
| 	case *_unionAssembler:
 | |
| 		return (*_unionAssemblerRepr)(asm), nil
 | |
| 	case *basicMapAssembler:
 | |
| 		return asm, nil
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("bindnode BeginMap TODO: %T", asm)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) BeginList(sizeHint int64) (datamodel.ListAssembler, error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_List).BeginList(sizeHint)
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		asm, err := (*_assembler)(w).BeginMap(sizeHint)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return (*_listStructAssemblerRepr)(asm.(*_structAssembler)), nil
 | |
| 	default:
 | |
| 		asm, err := (*_assembler)(w).BeginList(sizeHint)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if _, ok := asm.(*basicListAssembler); ok {
 | |
| 			return asm, nil
 | |
| 		}
 | |
| 		return (*_listAssemblerRepr)(asm.(*_listAssembler)), nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignNull() error {
 | |
| 	return (*_assembler)(w).AssignNull()
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignBool(b bool) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Bool).AssignBool(b)
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignBool(b)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) assignUInt(uin datamodel.UintNode) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Int).(*_assemblerRepr).assignUInt(uin)
 | |
| 	case schema.EnumRepresentation_Int:
 | |
| 		uin, err := uin.AsUint()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		return fmt.Errorf("AssignInt: %d is not a valid member of enum %s", uin, w.schemaType.Name())
 | |
| 	default:
 | |
| 		return (*_assembler)(w).assignUInt(uin)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignInt(i int64) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Int).AssignInt(i)
 | |
| 	case schema.EnumRepresentation_Int:
 | |
| 		for member, reprInt := range stg {
 | |
| 			if int64(reprInt) != i {
 | |
| 				continue
 | |
| 			}
 | |
| 			val := (*_assembler)(w).createNonPtrVal()
 | |
| 			kind := val.Kind()
 | |
| 			if kind == reflect.String {
 | |
| 				// Reuse AssignString so we don't have to repeat ten lines.
 | |
| 				return (*_assembler)(w).AssignString(member)
 | |
| 			}
 | |
| 			// Short-cut to storing the repr int directly, akin to node.go's AssignInt.
 | |
| 			if kindInt[kind] {
 | |
| 				val.SetInt(i)
 | |
| 			} else if kindUint[kind] {
 | |
| 				if i < 0 {
 | |
| 					// TODO: write a test
 | |
| 					return fmt.Errorf("bindnode: cannot assign negative integer to %s", w.val.Type())
 | |
| 				}
 | |
| 				val.SetUint(uint64(i))
 | |
| 			} else {
 | |
| 				return fmt.Errorf("AsInt: unexpected kind: %s", val.Kind())
 | |
| 			}
 | |
| 			if w.finish != nil {
 | |
| 				if err := w.finish(); err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 			}
 | |
| 			return nil
 | |
| 		}
 | |
| 		return fmt.Errorf("AssignInt: %d is not a valid member of enum %s", i, w.schemaType.Name())
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignInt(i)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignFloat(f float64) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Float).AssignFloat(f)
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignFloat(f)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignString(s string) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Stringjoin:
 | |
| 		fields := w.schemaType.(*schema.TypeStruct).Fields()
 | |
| 		parts := strings.Split(s, stg.GetDelim())
 | |
| 		if len(parts) != len(fields) {
 | |
| 			return fmt.Errorf("bindnode TODO: len mismatch")
 | |
| 		}
 | |
| 		mapAsm, err := (*_assembler)(w).BeginMap(-1)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		for i, field := range fields {
 | |
| 			entryAsm, err := mapAsm.AssembleEntry(field.Name())
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			entryAsm = assemblerRepr(entryAsm)
 | |
| 			if err := entryAsm.AssignString(parts[i]); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 		return mapAsm.Finish()
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_String).AssignString(s)
 | |
| 	case schema.UnionRepresentation_Stringprefix:
 | |
| 		hasDelim := stg.GetDelim() != ""
 | |
| 
 | |
| 		var prefix, remainder string
 | |
| 		if hasDelim {
 | |
| 			parts := strings.SplitN(s, stg.GetDelim(), 2)
 | |
| 			if len(parts) != 2 {
 | |
| 				return fmt.Errorf("schema rejects data: the union type %s expects delimiter %q, and it was not found in the data %q", w.schemaType.Name(), stg.GetDelim(), s)
 | |
| 			}
 | |
| 			prefix, remainder = parts[0], parts[1]
 | |
| 		}
 | |
| 
 | |
| 		members := w.schemaType.(*schema.TypeUnion).Members()
 | |
| 		for idx, member := range members {
 | |
| 			descrm := stg.GetDiscriminant(member)
 | |
| 			if hasDelim {
 | |
| 				if stg.GetDiscriminant(member) != prefix {
 | |
| 					continue
 | |
| 				}
 | |
| 			} else {
 | |
| 				if !strings.HasPrefix(s, descrm) {
 | |
| 					continue
 | |
| 				}
 | |
| 				remainder = s[len(descrm):]
 | |
| 			}
 | |
| 
 | |
| 			// TODO: DRY: this has much in common with the asKinded method; it differs only in that we picked idx already in a different way.
 | |
| 			w2 := *w
 | |
| 			goType := w.val.Field(idx).Type().Elem()
 | |
| 			valPtr := reflect.New(goType)
 | |
| 			w2.val = valPtr.Elem()
 | |
| 			w2.schemaType = member
 | |
| 			w2.finish = func() error {
 | |
| 				unionSetMember(w.val, idx, valPtr)
 | |
| 				if w.finish != nil {
 | |
| 					if err := w.finish(); err != nil {
 | |
| 						return err
 | |
| 					}
 | |
| 				}
 | |
| 				return nil
 | |
| 			}
 | |
| 			return w2.AssignString(remainder)
 | |
| 		}
 | |
| 		return fmt.Errorf("schema rejects data: the union type %s requires a known prefix, and it was not found in the data %q", w.schemaType.Name(), s)
 | |
| 	case schema.EnumRepresentation_String:
 | |
| 		// Note that we need to do a reverse lookup.
 | |
| 		for member, mapped := range stg {
 | |
| 			if mapped == s {
 | |
| 				return (*_assembler)(w).AssignString(member)
 | |
| 			}
 | |
| 		}
 | |
| 		members := w.schemaType.(*schema.TypeEnum).Members()
 | |
| 		for _, member := range members {
 | |
| 			if s == member {
 | |
| 				return (*_assembler)(w).AssignString(member)
 | |
| 			}
 | |
| 		}
 | |
| 		return fmt.Errorf("AssignString: %q is not a valid member of enum %s", s, w.schemaType.Name())
 | |
| 	case schema.EnumRepresentation_Int:
 | |
| 		return datamodel.ErrWrongKind{
 | |
| 			TypeName:        w.schemaType.Name(),
 | |
| 			MethodName:      "AssignString",
 | |
| 			AppropriateKind: datamodel.KindSet_JustInt,
 | |
| 			ActualKind:      datamodel.Kind_String,
 | |
| 		}
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignString(s)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignBytes(p []byte) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Bytes).AssignBytes(p)
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignBytes(p)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignLink(link datamodel.Link) error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Kinded:
 | |
| 		return w.asKinded(stg, datamodel.Kind_Link).AssignLink(link)
 | |
| 	default:
 | |
| 		return (*_assembler)(w).AssignLink(link)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) AssignNode(node datamodel.Node) error {
 | |
| 	// TODO: attempt to take a shortcut, like assembler.AssignNode
 | |
| 	if uintNode, ok := node.(datamodel.UintNode); ok {
 | |
| 		return w.assignUInt(uintNode)
 | |
| 	}
 | |
| 	return datamodel.Copy(node, w)
 | |
| }
 | |
| 
 | |
| func (w *_assemblerRepr) Prototype() datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: Assembler.Prototype")
 | |
| }
 | |
| 
 | |
| type _structAssemblerRepr _structAssembler
 | |
| 
 | |
| func (w *_structAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		return (*_structAssembler)(w).AssembleKey()
 | |
| 	case schema.StructRepresentation_Stringjoin,
 | |
| 		schema.StructRepresentation_StringPairs:
 | |
| 		// TODO: perhaps the ErrorWrongKind type should also be extended to explicitly describe whether the method was applied on bare DM, type-level, or repr-level.
 | |
| 		return _errorAssembler{datamodel.ErrWrongKind{
 | |
| 			TypeName:        w.schemaType.Name() + ".Repr",
 | |
| 			MethodName:      "AssembleKey",
 | |
| 			AppropriateKind: datamodel.KindSet_JustMap,
 | |
| 			ActualKind:      datamodel.Kind_String,
 | |
| 		}}
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		return _errorAssembler{datamodel.ErrWrongKind{
 | |
| 			TypeName:        w.schemaType.Name() + ".Repr",
 | |
| 			MethodName:      "AssembleKey",
 | |
| 			AppropriateKind: datamodel.KindSet_JustMap,
 | |
| 			ActualKind:      datamodel.Kind_List,
 | |
| 		}}
 | |
| 	default:
 | |
| 		return _errorAssembler{fmt.Errorf("bindnode AssembleKey TODO: %T", stg)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_structAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		key := w.curKey.val.String()
 | |
| 		revKey := inboundMappedKey(w.schemaType, stg, key)
 | |
| 		w.curKey.val.SetString(revKey)
 | |
| 
 | |
| 		valAsm := (*_structAssembler)(w).AssembleValue()
 | |
| 		valAsm = assemblerRepr(valAsm)
 | |
| 		return valAsm
 | |
| 	default:
 | |
| 		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_structAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
 | |
| 	if err := w.AssembleKey().AssignString(k); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	am := w.AssembleValue()
 | |
| 	return am, nil
 | |
| }
 | |
| 
 | |
| func (w *_structAssemblerRepr) Finish() error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		err := (*_structAssembler)(w).Finish()
 | |
| 		if err, ok := err.(schema.ErrMissingRequiredField); ok {
 | |
| 			for i, name := range err.Missing {
 | |
| 				serial := outboundMappedKey(stg, name)
 | |
| 				if serial != name {
 | |
| 					err.Missing[i] += fmt.Sprintf(" (serial:%q)", serial)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		return err
 | |
| 	default:
 | |
| 		return fmt.Errorf("bindnode Finish TODO: %T", stg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_structAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO")
 | |
| }
 | |
| 
 | |
| func (w *_structAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: struct ValuePrototype")
 | |
| }
 | |
| 
 | |
| type _mapAssemblerRepr _mapAssembler
 | |
| 
 | |
| func (w *_mapAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
 | |
| 	asm := (*_mapAssembler)(w).AssembleKey()
 | |
| 	return (*_assemblerRepr)(asm.(*_assembler))
 | |
| }
 | |
| 
 | |
| func (w *_mapAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
 | |
| 	asm := (*_mapAssembler)(w).AssembleValue()
 | |
| 	return (*_assemblerRepr)(asm.(*_assembler))
 | |
| }
 | |
| 
 | |
| func (w *_mapAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
 | |
| 	if err := w.AssembleKey().AssignString(k); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	am := w.AssembleValue()
 | |
| 	return am, nil
 | |
| }
 | |
| 
 | |
| func (w *_mapAssemblerRepr) Finish() error {
 | |
| 	return (*_mapAssembler)(w).Finish()
 | |
| }
 | |
| 
 | |
| func (w *_mapAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO")
 | |
| }
 | |
| 
 | |
| func (w *_mapAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: struct ValuePrototype")
 | |
| }
 | |
| 
 | |
| type _listStructAssemblerRepr _structAssembler
 | |
| 
 | |
| func (w *_listStructAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		fields := w.schemaType.Fields()
 | |
| 		if w.nextIndex >= len(fields) {
 | |
| 			return _errorAssembler{datamodel.ErrNotExists{
 | |
| 				Segment: datamodel.PathSegmentOfInt(int64(w.nextIndex)),
 | |
| 			}}
 | |
| 		}
 | |
| 		field := fields[w.nextIndex]
 | |
| 		w.doneFields[w.nextIndex] = true
 | |
| 		w.nextIndex++
 | |
| 
 | |
| 		entryAsm, err := (*_structAssembler)(w).AssembleEntry(field.Name())
 | |
| 		if err != nil {
 | |
| 			return _errorAssembler{err}
 | |
| 		}
 | |
| 		entryAsm = assemblerRepr(entryAsm)
 | |
| 		return entryAsm
 | |
| 	default:
 | |
| 		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_listStructAssemblerRepr) Finish() error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Tuple:
 | |
| 		return (*_structAssembler)(w).Finish()
 | |
| 	default:
 | |
| 		return fmt.Errorf("bindnode Finish TODO: %T", stg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_listStructAssemblerRepr) ValuePrototype(idx int64) datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: list ValuePrototype")
 | |
| }
 | |
| 
 | |
| // Note that lists do not have any representation strategy right now.
 | |
| type _listAssemblerRepr _listAssembler
 | |
| 
 | |
| func (w *_listAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
 | |
| 	asm := (*_listAssembler)(w).AssembleValue()
 | |
| 	return (*_assemblerRepr)(asm.(*_assembler))
 | |
| }
 | |
| 
 | |
| func (w *_listAssemblerRepr) Finish() error {
 | |
| 	return (*_listAssembler)(w).Finish()
 | |
| }
 | |
| 
 | |
| func (w *_listAssemblerRepr) ValuePrototype(idx int64) datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: list ValuePrototype")
 | |
| }
 | |
| 
 | |
| type _unionAssemblerRepr _unionAssembler
 | |
| 
 | |
| func (w *_unionAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		return (*_unionAssembler)(w).AssembleKey()
 | |
| 	default:
 | |
| 		return _errorAssembler{fmt.Errorf("bindnode AssembleKey TODO: %T", stg)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_unionAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		key := w.curKey.val.String()
 | |
| 		revKey := inboundMappedType(w.schemaType, stg, key)
 | |
| 		w.curKey.val.SetString(revKey)
 | |
| 
 | |
| 		valAsm := (*_unionAssembler)(w).AssembleValue()
 | |
| 		valAsm = assemblerRepr(valAsm)
 | |
| 		return valAsm
 | |
| 	default:
 | |
| 		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_unionAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
 | |
| 	if err := w.AssembleKey().AssignString(k); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	am := w.AssembleValue()
 | |
| 	return am, nil
 | |
| }
 | |
| 
 | |
| func (w *_unionAssemblerRepr) Finish() error {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		return (*_unionAssembler)(w).Finish()
 | |
| 	default:
 | |
| 		return fmt.Errorf("bindnode Finish TODO: %T", stg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_unionAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO")
 | |
| }
 | |
| 
 | |
| func (w *_unionAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
 | |
| 	panic("bindnode TODO: union ValuePrototype")
 | |
| }
 | |
| 
 | |
| type _structIteratorRepr _structIterator
 | |
| 
 | |
| func (w *_structIteratorRepr) Next() (key, value datamodel.Node, _ error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 	_skipAbsent:
 | |
| 		key, value, err := (*_structIterator)(w).Next()
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 		if value.IsAbsent() {
 | |
| 			goto _skipAbsent
 | |
| 		}
 | |
| 		keyStr, _ := key.AsString()
 | |
| 		mappedKey := outboundMappedKey(stg, keyStr)
 | |
| 		if mappedKey != keyStr {
 | |
| 			key = basicnode.NewString(mappedKey)
 | |
| 		}
 | |
| 		return key, reprNode(value), nil
 | |
| 	default:
 | |
| 		return nil, nil, fmt.Errorf("bindnode Next TODO: %T", stg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_structIteratorRepr) Done() bool {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.StructRepresentation_Map:
 | |
| 		// TODO: the fact that repr map iterators skip absents should be
 | |
| 		// documented somewhere
 | |
| 		return w.nextIndex >= w.reprEnd
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("bindnode Done TODO: %T", stg))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type _unionIteratorRepr _unionIterator
 | |
| 
 | |
| func (w *_unionIteratorRepr) Next() (key, value datamodel.Node, _ error) {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		key, value, err := (*_unionIterator)(w).Next()
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 		keyStr, _ := key.AsString()
 | |
| 		mappedKey := outboundMappedType(stg, keyStr)
 | |
| 		if mappedKey != keyStr {
 | |
| 			key = basicnode.NewString(mappedKey)
 | |
| 		}
 | |
| 		return key, reprNode(value), nil
 | |
| 	default:
 | |
| 		return nil, nil, fmt.Errorf("bindnode Next TODO: %T", stg)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w *_unionIteratorRepr) Done() bool {
 | |
| 	switch stg := reprStrategy(w.schemaType).(type) {
 | |
| 	case schema.UnionRepresentation_Keyed:
 | |
| 		return (*_unionIterator)(w).Done()
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("bindnode Done TODO: %T", stg))
 | |
| 	}
 | |
| }
 |