github.com/ipld/go-ipld-prime@v0.21.0/node/bindnode/repr.go (about)

     1  package bindnode
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  
     8  	"github.com/ipld/go-ipld-prime/datamodel"
     9  	"github.com/ipld/go-ipld-prime/node/basicnode"
    10  	"github.com/ipld/go-ipld-prime/schema"
    11  )
    12  
    13  func reprNode(node datamodel.Node) datamodel.Node {
    14  	if node, ok := node.(schema.TypedNode); ok {
    15  		return node.Representation()
    16  	}
    17  	// datamodel.Absent and datamodel.Null are not typed.
    18  	// TODO: is this a problem? surely a typed struct's fields are always
    19  	// typed, even when absent or null.
    20  	return node
    21  }
    22  
    23  func reprStrategy(typ schema.Type) interface{} {
    24  	// Can't use an interface check, as each method has a different result type.
    25  	// TODO: consider inlining this type switch at each call site,
    26  	// as the call sites need the underlying schema.Type too.
    27  	switch typ := typ.(type) {
    28  	case *schema.TypeStruct:
    29  		return typ.RepresentationStrategy()
    30  	case *schema.TypeUnion:
    31  		return typ.RepresentationStrategy()
    32  	case *schema.TypeEnum:
    33  		return typ.RepresentationStrategy()
    34  	}
    35  	return nil
    36  }
    37  
    38  type _prototypeRepr _prototype
    39  
    40  func (w *_prototypeRepr) NewBuilder() datamodel.NodeBuilder {
    41  	return &_builderRepr{_assemblerRepr{
    42  		cfg:        w.cfg,
    43  		schemaType: w.schemaType,
    44  		val:        reflect.New(w.goType).Elem(),
    45  	}}
    46  }
    47  
    48  type _nodeRepr _node
    49  
    50  func (w *_nodeRepr) Kind() datamodel.Kind {
    51  	switch reprStrategy(w.schemaType).(type) {
    52  	case schema.StructRepresentation_Stringjoin:
    53  		return datamodel.Kind_String
    54  	case schema.StructRepresentation_Map:
    55  		return datamodel.Kind_Map
    56  	case schema.StructRepresentation_Tuple, schema.StructRepresentation_ListPairs:
    57  		return datamodel.Kind_List
    58  	case schema.UnionRepresentation_Keyed:
    59  		return datamodel.Kind_Map
    60  	case schema.UnionRepresentation_Kinded:
    61  		haveIdx, _ := unionMember(w.val)
    62  		if haveIdx < 0 {
    63  			panic(fmt.Sprintf("bindnode: kinded union %s has no member", w.val.Type()))
    64  		}
    65  		mtyp := w.schemaType.(*schema.TypeUnion).Members()[haveIdx]
    66  		return mtyp.RepresentationBehavior()
    67  	case schema.UnionRepresentation_Stringprefix:
    68  		return datamodel.Kind_String
    69  	case schema.EnumRepresentation_Int:
    70  		return datamodel.Kind_Int
    71  	case schema.EnumRepresentation_String:
    72  		return datamodel.Kind_String
    73  	default:
    74  		return (*_node)(w).Kind()
    75  	}
    76  }
    77  
    78  func outboundMappedKey(stg schema.StructRepresentation_Map, key string) string {
    79  	// TODO: why doesn't stg just allow us to "get" by the key string?
    80  	field := schema.SpawnStructField(key, "", false, false)
    81  	mappedKey := stg.GetFieldKey(field)
    82  	return mappedKey
    83  }
    84  
    85  func inboundMappedKey(typ *schema.TypeStruct, stg schema.StructRepresentation_Map, key string) string {
    86  	// TODO: can't do a "reverse" lookup... needs better API probably.
    87  	fields := typ.Fields()
    88  	for _, field := range fields {
    89  		mappedKey := stg.GetFieldKey(field)
    90  		if key == mappedKey {
    91  			return field.Name()
    92  		}
    93  	}
    94  	return key // fallback to the same key
    95  }
    96  
    97  func outboundMappedType(stg schema.UnionRepresentation_Keyed, key string) string {
    98  	// TODO: why doesn't stg just allow us to "get" by the key string?
    99  	typ := schema.SpawnBool(key)
   100  	mappedKey := stg.GetDiscriminant(typ)
   101  	return mappedKey
   102  }
   103  
   104  func inboundMappedType(typ *schema.TypeUnion, stg schema.UnionRepresentation_Keyed, key string) string {
   105  	// TODO: can't do a "reverse" lookup... needs better API probably.
   106  	for _, member := range typ.Members() {
   107  		mappedKey := stg.GetDiscriminant(member)
   108  		if key == mappedKey {
   109  			// println(key, "rev-mapped to", field.Name())
   110  			return member.Name()
   111  		}
   112  	}
   113  	// println(key, "had no mapping")
   114  	return key // fallback to the same key
   115  }
   116  
   117  // asKinded can be called on a kinded union node to obtain a node
   118  // representing one of its members, identified by kind.
   119  func (w *_nodeRepr) asKinded(stg schema.UnionRepresentation_Kinded, kind datamodel.Kind) *_nodeRepr {
   120  	name := stg.GetMember(kind)
   121  	members := w.schemaType.(*schema.TypeUnion).Members()
   122  	for i, member := range members {
   123  		if member.Name() != name {
   124  			continue
   125  		}
   126  		w2 := *w
   127  		w2.val = w.val.Field(i).Elem()
   128  		w2.schemaType = member
   129  		return &w2
   130  	}
   131  	panic("bindnode TODO: GetMember result is missing?")
   132  }
   133  
   134  func (w *_nodeRepr) LookupByString(key string) (datamodel.Node, error) {
   135  	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
   136  		w = w.asKinded(stg, datamodel.Kind_Map)
   137  	}
   138  	switch stg := reprStrategy(w.schemaType).(type) {
   139  	case schema.StructRepresentation_Map:
   140  		revKey := inboundMappedKey(w.schemaType.(*schema.TypeStruct), stg, key)
   141  		v, err := (*_node)(w).LookupByString(revKey)
   142  		if err != nil {
   143  			return nil, err
   144  		}
   145  		return reprNode(v), nil
   146  	case schema.UnionRepresentation_Keyed:
   147  		revKey := inboundMappedType(w.schemaType.(*schema.TypeUnion), stg, key)
   148  		v, err := (*_node)(w).LookupByString(revKey)
   149  		if err != nil {
   150  			return nil, err
   151  		}
   152  		return reprNode(v), nil
   153  	default:
   154  		v, err := (*_node)(w).LookupByString(key)
   155  		if err != nil {
   156  			return nil, err
   157  		}
   158  		return reprNode(v), nil
   159  	}
   160  }
   161  
   162  func (w *_nodeRepr) LookupByIndex(idx int64) (datamodel.Node, error) {
   163  	switch stg := reprStrategy(w.schemaType).(type) {
   164  	case schema.UnionRepresentation_Kinded:
   165  		return w.asKinded(stg, datamodel.Kind_List).LookupByIndex(idx)
   166  	case schema.StructRepresentation_Tuple:
   167  		fields := w.schemaType.(*schema.TypeStruct).Fields()
   168  		if idx < 0 || int(idx) >= len(fields) {
   169  			return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
   170  		}
   171  		field := fields[idx]
   172  		v, err := (*_node)(w).LookupByString(field.Name())
   173  		if err != nil {
   174  			return nil, err
   175  		}
   176  		return reprNode(v), nil
   177  	case schema.StructRepresentation_ListPairs:
   178  		fields := w.schemaType.(*schema.TypeStruct).Fields()
   179  		if idx < 0 || int(idx) >= len(fields) {
   180  			return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
   181  		}
   182  		var curField int64
   183  		for _, field := range fields {
   184  			value, err := (*_node)(w).LookupByString(field.Name())
   185  			if err != nil {
   186  				return nil, err
   187  			}
   188  			if value.IsAbsent() {
   189  				continue
   190  			}
   191  			if curField == idx {
   192  				return buildListpairsField(basicnode.NewString(field.Name()), reprNode(value))
   193  			}
   194  			curField++
   195  		}
   196  		return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
   197  	default:
   198  		v, err := (*_node)(w).LookupByIndex(idx)
   199  		if err != nil {
   200  			return nil, err
   201  		}
   202  		return reprNode(v), nil
   203  	}
   204  }
   205  
   206  func (w *_nodeRepr) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, error) {
   207  	switch w.Kind() {
   208  	case datamodel.Kind_Map:
   209  		return w.LookupByString(seg.String())
   210  	case datamodel.Kind_List:
   211  		idx, err := seg.Index()
   212  		if err != nil {
   213  			return nil, err
   214  		}
   215  		return w.LookupByIndex(idx)
   216  	}
   217  	return nil, datamodel.ErrWrongKind{
   218  		TypeName:        w.schemaType.Name(),
   219  		MethodName:      "LookupBySegment",
   220  		AppropriateKind: datamodel.KindSet_Recursive,
   221  		ActualKind:      w.Kind(),
   222  	}
   223  }
   224  
   225  func (w *_nodeRepr) LookupByNode(key datamodel.Node) (datamodel.Node, error) {
   226  	switch w.Kind() {
   227  	case datamodel.Kind_Map:
   228  		s, err := key.AsString()
   229  		if err != nil {
   230  			return nil, err
   231  		}
   232  		return w.LookupByString(s)
   233  	case datamodel.Kind_List:
   234  		i, err := key.AsInt()
   235  		if err != nil {
   236  			return nil, err
   237  		}
   238  		return w.LookupByIndex(i)
   239  	}
   240  	return nil, datamodel.ErrWrongKind{
   241  		TypeName:        w.schemaType.Name(),
   242  		MethodName:      "LookupByNode",
   243  		AppropriateKind: datamodel.KindSet_Recursive,
   244  		ActualKind:      w.Kind(),
   245  	}
   246  }
   247  
   248  func (w *_nodeRepr) MapIterator() datamodel.MapIterator {
   249  	// TODO: we can try to reuse reprStrategy here and elsewhere
   250  	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
   251  		w = w.asKinded(stg, datamodel.Kind_Map)
   252  	}
   253  	switch reprStrategy(w.schemaType).(type) {
   254  	case schema.StructRepresentation_Map:
   255  		itr := (*_node)(w).MapIterator().(*_structIterator)
   256  		// When we reach the last non-absent field, we should stop.
   257  		itr.reprEnd = int(w.lengthMinusTrailingAbsents())
   258  		return (*_structIteratorRepr)(itr)
   259  	case schema.UnionRepresentation_Keyed:
   260  		itr := (*_node)(w).MapIterator().(*_unionIterator)
   261  		return (*_unionIteratorRepr)(itr)
   262  	default:
   263  		iter, _ := (*_node)(w).MapIterator().(*_mapIterator)
   264  		if iter == nil {
   265  			return nil
   266  		}
   267  		return (*_mapIteratorRepr)(iter)
   268  	}
   269  }
   270  
   271  type _mapIteratorRepr _mapIterator
   272  
   273  func (w *_mapIteratorRepr) Next() (key, value datamodel.Node, _ error) {
   274  	k, v, err := (*_mapIterator)(w).Next()
   275  	if err != nil {
   276  		return nil, nil, err
   277  	}
   278  	return reprNode(k), reprNode(v), nil
   279  }
   280  
   281  func (w *_mapIteratorRepr) Done() bool {
   282  	return w.nextIndex >= w.keysVal.Len()
   283  }
   284  
   285  func (w *_nodeRepr) ListIterator() datamodel.ListIterator {
   286  	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
   287  		w = w.asKinded(stg, datamodel.Kind_List)
   288  	}
   289  	switch reprStrategy(w.schemaType).(type) {
   290  	case schema.StructRepresentation_Tuple:
   291  		typ := w.schemaType.(*schema.TypeStruct)
   292  		iter := _tupleIteratorRepr{cfg: w.cfg, schemaType: typ, fields: typ.Fields(), val: w.val}
   293  		iter.reprEnd = int(w.lengthMinusTrailingAbsents())
   294  		return &iter
   295  	case schema.StructRepresentation_ListPairs:
   296  		typ := w.schemaType.(*schema.TypeStruct)
   297  		iter := _listpairsIteratorRepr{cfg: w.cfg, schemaType: typ, fields: typ.Fields(), val: w.val}
   298  		iter.reprEnd = int(w.lengthMinusTrailingAbsents())
   299  		return &iter
   300  	default:
   301  		iter, _ := (*_node)(w).ListIterator().(*_listIterator)
   302  		if iter == nil {
   303  			return nil
   304  		}
   305  		return (*_listIteratorRepr)(iter)
   306  	}
   307  }
   308  
   309  type _listIteratorRepr _listIterator
   310  
   311  func (w *_listIteratorRepr) Next() (index int64, value datamodel.Node, _ error) {
   312  	idx, v, err := (*_listIterator)(w).Next()
   313  	if err != nil {
   314  		return idx, nil, err
   315  	}
   316  	return idx, reprNode(v), nil
   317  }
   318  
   319  func (w *_listIteratorRepr) Done() bool {
   320  	return w.nextIndex >= w.val.Len()
   321  }
   322  
   323  func (w *_nodeRepr) lengthMinusAbsents() int64 {
   324  	fields := w.schemaType.(*schema.TypeStruct).Fields()
   325  	n := int64(len(fields))
   326  	for i, field := range fields {
   327  		if field.IsOptional() && w.val.Field(i).IsNil() {
   328  			n--
   329  		}
   330  	}
   331  	return n
   332  }
   333  
   334  type _tupleIteratorRepr struct {
   335  	// TODO: support embedded fields?
   336  	cfg        config
   337  	schemaType *schema.TypeStruct
   338  	fields     []schema.StructField
   339  	val        reflect.Value // non-pointer
   340  	nextIndex  int
   341  
   342  	// these are only used in repr.go
   343  	reprEnd int
   344  }
   345  
   346  func (w *_tupleIteratorRepr) Next() (index int64, value datamodel.Node, _ error) {
   347  	for {
   348  		idx := w.nextIndex
   349  		_, value, err := (*_structIterator)(w).Next()
   350  		if err != nil {
   351  			return 0, nil, err
   352  		}
   353  		if w.nextIndex <= w.reprEnd {
   354  			return int64(idx), reprNode(value), nil
   355  		}
   356  	}
   357  }
   358  
   359  func (w *_tupleIteratorRepr) Done() bool {
   360  	return w.nextIndex >= w.reprEnd
   361  }
   362  
   363  type _listpairsIteratorRepr struct {
   364  	cfg        config
   365  	schemaType *schema.TypeStruct
   366  	fields     []schema.StructField
   367  	val        reflect.Value // non-pointer
   368  	nextIndex  int
   369  
   370  	// these are only used in repr.go
   371  	reprEnd int
   372  }
   373  
   374  func (w *_listpairsIteratorRepr) Next() (index int64, value datamodel.Node, _ error) {
   375  	for {
   376  		if w.Done() {
   377  			return 0, nil, datamodel.ErrIteratorOverread{}
   378  		}
   379  		idx := w.nextIndex
   380  		key, value, err := (*_structIterator)(w).Next()
   381  		if err != nil {
   382  			return 0, nil, err
   383  		}
   384  		if value.IsAbsent() || w.nextIndex > w.reprEnd {
   385  			continue
   386  		}
   387  		field, err := buildListpairsField(key, reprNode(value))
   388  		if err != nil {
   389  			return 0, nil, err
   390  		}
   391  		return int64(idx), field, nil
   392  	}
   393  }
   394  
   395  func (w *_listpairsIteratorRepr) Done() bool {
   396  	return w.nextIndex >= w.reprEnd
   397  }
   398  
   399  func buildListpairsField(key, value datamodel.Node) (datamodel.Node, error) {
   400  	nb := basicnode.Prototype.List.NewBuilder()
   401  	la, err := nb.BeginList(2)
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  	if err := la.AssembleValue().AssignNode(key); err != nil {
   406  		return nil, err
   407  	}
   408  	if err := la.AssembleValue().AssignNode(value); err != nil {
   409  		return nil, err
   410  	}
   411  	if err := la.Finish(); err != nil {
   412  		return nil, err
   413  	}
   414  	return nb.Build(), nil
   415  }
   416  
   417  func (w *_nodeRepr) lengthMinusTrailingAbsents() int64 {
   418  	fields := w.schemaType.(*schema.TypeStruct).Fields()
   419  	for i := len(fields) - 1; i >= 0; i-- {
   420  		field := fields[i]
   421  		if !field.IsOptional() || !w.val.Field(i).IsNil() {
   422  			return int64(i + 1)
   423  		}
   424  	}
   425  	return 0
   426  }
   427  
   428  func (w *_nodeRepr) Length() int64 {
   429  	switch stg := reprStrategy(w.schemaType).(type) {
   430  	case schema.StructRepresentation_Stringjoin:
   431  		return -1
   432  	case schema.StructRepresentation_Map:
   433  		return w.lengthMinusAbsents()
   434  	case schema.StructRepresentation_Tuple:
   435  		return w.lengthMinusTrailingAbsents()
   436  	case schema.StructRepresentation_ListPairs:
   437  		return w.lengthMinusAbsents()
   438  	case schema.UnionRepresentation_Keyed:
   439  		return (*_node)(w).Length()
   440  	case schema.UnionRepresentation_Kinded:
   441  		w = w.asKinded(stg, w.Kind())
   442  		return (*_node)(w).Length()
   443  	default:
   444  		return (*_node)(w).Length()
   445  	}
   446  }
   447  
   448  func (w *_nodeRepr) IsAbsent() bool {
   449  	if reprStrategy(w.schemaType) == nil {
   450  		return (*_node)(w).IsAbsent()
   451  	}
   452  	return false
   453  }
   454  
   455  func (w *_nodeRepr) IsNull() bool {
   456  	if reprStrategy(w.schemaType) == nil {
   457  		return (*_node)(w).IsNull()
   458  	}
   459  	return false
   460  }
   461  
   462  func (w *_nodeRepr) AsBool() (bool, error) {
   463  	switch stg := reprStrategy(w.schemaType).(type) {
   464  	case schema.UnionRepresentation_Kinded:
   465  		return w.asKinded(stg, datamodel.Kind_Bool).AsBool()
   466  	default:
   467  		return (*_node)(w).AsBool()
   468  	}
   469  }
   470  
   471  func (w *_nodeRepr) AsInt() (int64, error) {
   472  	switch stg := reprStrategy(w.schemaType).(type) {
   473  	case schema.UnionRepresentation_Kinded:
   474  		return w.asKinded(stg, datamodel.Kind_Int).AsInt()
   475  	case schema.EnumRepresentation_Int:
   476  		kind := w.val.Kind()
   477  		if kind == reflect.String {
   478  			s, err := (*_node)(w).AsString()
   479  			if err != nil {
   480  				return 0, err
   481  			}
   482  			mapped, ok := stg[s]
   483  			if !ok {
   484  				// We assume that the schema strategy is correct,
   485  				// so we can only fail if the stored string isn't a valid member.
   486  				return 0, fmt.Errorf("AsInt: %q is not a valid member of enum %s", s, w.schemaType.Name())
   487  			}
   488  			// TODO: the strategy type should probably use int64 rather than int
   489  			return int64(mapped), nil
   490  		}
   491  		var i int
   492  		// TODO: check for overflows
   493  		if kindInt[kind] {
   494  			i = int(w.val.Int())
   495  		} else if kindUint[kind] {
   496  			i = int(w.val.Uint())
   497  		} else {
   498  			return 0, fmt.Errorf("AsInt: unexpected kind: %s", kind)
   499  		}
   500  		for _, reprInt := range stg {
   501  			if reprInt == i {
   502  				return int64(i), nil
   503  			}
   504  		}
   505  		// We assume that the schema strategy is correct,
   506  		// so we can only fail if the stored string isn't a valid member.
   507  		return 0, fmt.Errorf("AsInt: %d is not a valid member of enum %s", i, w.schemaType.Name())
   508  	default:
   509  		return (*_node)(w).AsInt()
   510  	}
   511  }
   512  
   513  func (w *_nodeRepr) AsFloat() (float64, error) {
   514  	switch stg := reprStrategy(w.schemaType).(type) {
   515  	case schema.UnionRepresentation_Kinded:
   516  		return w.asKinded(stg, datamodel.Kind_Float).AsFloat()
   517  	default:
   518  		return (*_node)(w).AsFloat()
   519  	}
   520  }
   521  
   522  func (w *_nodeRepr) AsString() (string, error) {
   523  	switch stg := reprStrategy(w.schemaType).(type) {
   524  	case schema.StructRepresentation_Stringjoin:
   525  		var b strings.Builder
   526  		itr := (*_node)(w).MapIterator()
   527  		first := true
   528  		for !itr.Done() {
   529  			_, v, err := itr.Next()
   530  			if err != nil {
   531  				return "", err
   532  			}
   533  			s, err := reprNode(v).AsString()
   534  			if err != nil {
   535  				return "", err
   536  			}
   537  			if first {
   538  				first = false
   539  			} else {
   540  				b.WriteString(stg.GetDelim())
   541  			}
   542  			b.WriteString(s)
   543  		}
   544  		return b.String(), nil
   545  	case schema.UnionRepresentation_Stringprefix:
   546  		haveIdx, mval := unionMember(w.val)
   547  		mtyp := w.schemaType.(*schema.TypeUnion).Members()[haveIdx]
   548  
   549  		w2 := *w
   550  		w2.val = mval
   551  		w2.schemaType = mtyp
   552  		s, err := w2.AsString()
   553  		if err != nil {
   554  			return "", err
   555  		}
   556  
   557  		name := stg.GetDiscriminant(mtyp)
   558  		return name + stg.GetDelim() + s, nil
   559  	case schema.UnionRepresentation_Kinded:
   560  		return w.asKinded(stg, datamodel.Kind_String).AsString()
   561  	case schema.EnumRepresentation_String:
   562  		s, err := (*_node)(w).AsString()
   563  		if err != nil {
   564  			return "", err
   565  		}
   566  		if mapped := stg[s]; mapped != "" {
   567  			return mapped, nil
   568  		}
   569  		members := w.schemaType.(*schema.TypeEnum).Members()
   570  		for _, member := range members {
   571  			if s == member {
   572  				return s, nil
   573  			}
   574  		}
   575  		for k, v := range stg {
   576  			// a programming error? we may have the enum string value rather than the type
   577  			if v == s {
   578  				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)
   579  			}
   580  		}
   581  		return "", fmt.Errorf("AsString: %q is not a valid member of enum %s", s, w.schemaType.Name())
   582  	default:
   583  		return (*_node)(w).AsString()
   584  	}
   585  }
   586  
   587  func (w *_nodeRepr) AsBytes() ([]byte, error) {
   588  	switch stg := reprStrategy(w.schemaType).(type) {
   589  	case schema.UnionRepresentation_Kinded:
   590  		return w.asKinded(stg, datamodel.Kind_Bytes).AsBytes()
   591  	default:
   592  		return (*_node)(w).AsBytes()
   593  	}
   594  }
   595  
   596  func (w *_nodeRepr) AsLink() (datamodel.Link, error) {
   597  	switch stg := reprStrategy(w.schemaType).(type) {
   598  	case schema.UnionRepresentation_Kinded:
   599  		return w.asKinded(stg, datamodel.Kind_Link).AsLink()
   600  	default:
   601  		return (*_node)(w).AsLink()
   602  	}
   603  }
   604  
   605  func (w *_nodeRepr) Prototype() datamodel.NodePrototype {
   606  	return (*_prototypeRepr)((*_node)(w).Prototype().(*_prototype))
   607  }
   608  
   609  type _builderRepr struct {
   610  	_assemblerRepr
   611  }
   612  
   613  // TODO: returning a repr node here is probably good, but there's a gotcha: one
   614  // can go from a typed node to a repr node via the Representation method, but
   615  // not the other way. That's probably why codegen returns a typed node here.
   616  // The solution might be to add a way to go from the repr node to its parent
   617  // typed node.
   618  
   619  func (w *_builderRepr) Build() datamodel.Node {
   620  	// TODO: see the notes above.
   621  	// return &_nodeRepr{schemaType: w.schemaType, val: w.val}
   622  	return &_node{cfg: w.cfg, schemaType: w.schemaType, val: w.val}
   623  }
   624  
   625  func (w *_builderRepr) Reset() {
   626  	panic("bindnode TODO: Reset")
   627  }
   628  
   629  type _assemblerRepr struct {
   630  	cfg        config
   631  	schemaType schema.Type
   632  	val        reflect.Value // non-pointer
   633  	finish     func() error
   634  
   635  	nullable bool
   636  }
   637  
   638  func assemblerRepr(am datamodel.NodeAssembler) datamodel.NodeAssembler {
   639  	switch am := am.(type) {
   640  	case *_assembler:
   641  		return (*_assemblerRepr)(am)
   642  	case _errorAssembler:
   643  		return am
   644  	default:
   645  		panic(fmt.Sprintf("unexpected NodeAssembler type: %T", am))
   646  	}
   647  }
   648  
   649  func (w *_assemblerRepr) asKinded(stg schema.UnionRepresentation_Kinded, kind datamodel.Kind) datamodel.NodeAssembler {
   650  	name := stg.GetMember(kind)
   651  	members := w.schemaType.(*schema.TypeUnion).Members()
   652  	kindSet := make([]datamodel.Kind, 0, len(members))
   653  	for idx, member := range members {
   654  		if member.Name() != name {
   655  			kindSet = append(kindSet, member.RepresentationBehavior())
   656  			continue
   657  		}
   658  		w2 := *w
   659  		goType := w.val.Field(idx).Type().Elem()
   660  		valPtr := reflect.New(goType)
   661  		w2.val = valPtr.Elem()
   662  		w2.schemaType = member
   663  
   664  		// Layer a new finish func on top, to set Index/Value.
   665  		w2.finish = func() error {
   666  			unionSetMember(w.val, idx, valPtr)
   667  			if w.finish != nil {
   668  				if err := w.finish(); err != nil {
   669  					return err
   670  				}
   671  			}
   672  			return nil
   673  		}
   674  		return &w2
   675  	}
   676  	return _errorAssembler{datamodel.ErrWrongKind{
   677  		TypeName:        w.schemaType.Name() + ".Repr",
   678  		MethodName:      "", // TODO: we could fill it via runtime.Callers
   679  		AppropriateKind: datamodel.KindSet(kindSet),
   680  		ActualKind:      kind,
   681  	}}
   682  }
   683  
   684  func (w *_assemblerRepr) BeginMap(sizeHint int64) (datamodel.MapAssembler, error) {
   685  	if stg, ok := reprStrategy(w.schemaType).(schema.UnionRepresentation_Kinded); ok {
   686  		return w.asKinded(stg, datamodel.Kind_Map).BeginMap(sizeHint)
   687  	}
   688  	asm, err := (*_assembler)(w).BeginMap(sizeHint)
   689  	if err != nil {
   690  		return nil, err
   691  	}
   692  	switch asm := asm.(type) {
   693  	case *_structAssembler:
   694  		return (*_structAssemblerRepr)(asm), nil
   695  	case *_mapAssembler:
   696  		return (*_mapAssemblerRepr)(asm), nil
   697  	case *_unionAssembler:
   698  		return (*_unionAssemblerRepr)(asm), nil
   699  	case *basicMapAssembler:
   700  		return asm, nil
   701  	default:
   702  		return nil, fmt.Errorf("bindnode BeginMap TODO: %T", asm)
   703  	}
   704  }
   705  
   706  func (w *_assemblerRepr) BeginList(sizeHint int64) (datamodel.ListAssembler, error) {
   707  	switch stg := reprStrategy(w.schemaType).(type) {
   708  	case schema.UnionRepresentation_Kinded:
   709  		return w.asKinded(stg, datamodel.Kind_List).BeginList(sizeHint)
   710  	case schema.StructRepresentation_Tuple, schema.StructRepresentation_ListPairs:
   711  		asm, err := (*_assembler)(w).BeginMap(sizeHint)
   712  		if err != nil {
   713  			return nil, err
   714  		}
   715  		return (*_listStructAssemblerRepr)(asm.(*_structAssembler)), nil
   716  	default:
   717  		asm, err := (*_assembler)(w).BeginList(sizeHint)
   718  		if err != nil {
   719  			return nil, err
   720  		}
   721  		if _, ok := asm.(*basicListAssembler); ok {
   722  			return asm, nil
   723  		}
   724  		return (*_listAssemblerRepr)(asm.(*_listAssembler)), nil
   725  	}
   726  }
   727  
   728  func (w *_assemblerRepr) AssignNull() error {
   729  	return (*_assembler)(w).AssignNull()
   730  }
   731  
   732  func (w *_assemblerRepr) AssignBool(b bool) error {
   733  	switch stg := reprStrategy(w.schemaType).(type) {
   734  	case schema.UnionRepresentation_Kinded:
   735  		return w.asKinded(stg, datamodel.Kind_Bool).AssignBool(b)
   736  	default:
   737  		return (*_assembler)(w).AssignBool(b)
   738  	}
   739  }
   740  
   741  func (w *_assemblerRepr) assignUInt(uin datamodel.UintNode) error {
   742  	switch stg := reprStrategy(w.schemaType).(type) {
   743  	case schema.UnionRepresentation_Kinded:
   744  		return w.asKinded(stg, datamodel.Kind_Int).(*_assemblerRepr).assignUInt(uin)
   745  	case schema.EnumRepresentation_Int:
   746  		uin, err := uin.AsUint()
   747  		if err != nil {
   748  			return err
   749  		}
   750  		return fmt.Errorf("AssignInt: %d is not a valid member of enum %s", uin, w.schemaType.Name())
   751  	default:
   752  		return (*_assembler)(w).assignUInt(uin)
   753  	}
   754  }
   755  
   756  func (w *_assemblerRepr) AssignInt(i int64) error {
   757  	switch stg := reprStrategy(w.schemaType).(type) {
   758  	case schema.UnionRepresentation_Kinded:
   759  		return w.asKinded(stg, datamodel.Kind_Int).AssignInt(i)
   760  	case schema.EnumRepresentation_Int:
   761  		for member, reprInt := range stg {
   762  			if int64(reprInt) != i {
   763  				continue
   764  			}
   765  			val := (*_assembler)(w).createNonPtrVal()
   766  			kind := val.Kind()
   767  			if kind == reflect.String {
   768  				// Reuse AssignString so we don't have to repeat ten lines.
   769  				return (*_assembler)(w).AssignString(member)
   770  			}
   771  			// Short-cut to storing the repr int directly, akin to node.go's AssignInt.
   772  			if kindInt[kind] {
   773  				val.SetInt(i)
   774  			} else if kindUint[kind] {
   775  				if i < 0 {
   776  					// TODO: write a test
   777  					return fmt.Errorf("bindnode: cannot assign negative integer to %s", w.val.Type())
   778  				}
   779  				val.SetUint(uint64(i))
   780  			} else {
   781  				return fmt.Errorf("AsInt: unexpected kind: %s", val.Kind())
   782  			}
   783  			if w.finish != nil {
   784  				if err := w.finish(); err != nil {
   785  					return err
   786  				}
   787  			}
   788  			return nil
   789  		}
   790  		return fmt.Errorf("AssignInt: %d is not a valid member of enum %s", i, w.schemaType.Name())
   791  	default:
   792  		return (*_assembler)(w).AssignInt(i)
   793  	}
   794  }
   795  
   796  func (w *_assemblerRepr) AssignFloat(f float64) error {
   797  	switch stg := reprStrategy(w.schemaType).(type) {
   798  	case schema.UnionRepresentation_Kinded:
   799  		return w.asKinded(stg, datamodel.Kind_Float).AssignFloat(f)
   800  	default:
   801  		return (*_assembler)(w).AssignFloat(f)
   802  	}
   803  }
   804  
   805  func (w *_assemblerRepr) AssignString(s string) error {
   806  	switch stg := reprStrategy(w.schemaType).(type) {
   807  	case schema.StructRepresentation_Stringjoin:
   808  		fields := w.schemaType.(*schema.TypeStruct).Fields()
   809  		parts := strings.Split(s, stg.GetDelim())
   810  		if len(parts) != len(fields) {
   811  			return fmt.Errorf("bindnode TODO: len mismatch")
   812  		}
   813  		mapAsm, err := (*_assembler)(w).BeginMap(-1)
   814  		if err != nil {
   815  			return err
   816  		}
   817  		for i, field := range fields {
   818  			entryAsm, err := mapAsm.AssembleEntry(field.Name())
   819  			if err != nil {
   820  				return err
   821  			}
   822  			entryAsm = assemblerRepr(entryAsm)
   823  			if err := entryAsm.AssignString(parts[i]); err != nil {
   824  				return err
   825  			}
   826  		}
   827  		return mapAsm.Finish()
   828  	case schema.UnionRepresentation_Kinded:
   829  		return w.asKinded(stg, datamodel.Kind_String).AssignString(s)
   830  	case schema.UnionRepresentation_Stringprefix:
   831  		hasDelim := stg.GetDelim() != ""
   832  
   833  		var prefix, remainder string
   834  		if hasDelim {
   835  			parts := strings.SplitN(s, stg.GetDelim(), 2)
   836  			if len(parts) != 2 {
   837  				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)
   838  			}
   839  			prefix, remainder = parts[0], parts[1]
   840  		}
   841  
   842  		members := w.schemaType.(*schema.TypeUnion).Members()
   843  		for idx, member := range members {
   844  			descrm := stg.GetDiscriminant(member)
   845  			if hasDelim {
   846  				if stg.GetDiscriminant(member) != prefix {
   847  					continue
   848  				}
   849  			} else {
   850  				if !strings.HasPrefix(s, descrm) {
   851  					continue
   852  				}
   853  				remainder = s[len(descrm):]
   854  			}
   855  
   856  			// TODO: DRY: this has much in common with the asKinded method; it differs only in that we picked idx already in a different way.
   857  			w2 := *w
   858  			goType := w.val.Field(idx).Type().Elem()
   859  			valPtr := reflect.New(goType)
   860  			w2.val = valPtr.Elem()
   861  			w2.schemaType = member
   862  			w2.finish = func() error {
   863  				unionSetMember(w.val, idx, valPtr)
   864  				if w.finish != nil {
   865  					if err := w.finish(); err != nil {
   866  						return err
   867  					}
   868  				}
   869  				return nil
   870  			}
   871  			return w2.AssignString(remainder)
   872  		}
   873  		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)
   874  	case schema.EnumRepresentation_String:
   875  		// Note that we need to do a reverse lookup.
   876  		for member, mapped := range stg {
   877  			if mapped == s {
   878  				return (*_assembler)(w).AssignString(member)
   879  			}
   880  		}
   881  		members := w.schemaType.(*schema.TypeEnum).Members()
   882  		for _, member := range members {
   883  			if s == member {
   884  				return (*_assembler)(w).AssignString(member)
   885  			}
   886  		}
   887  		return fmt.Errorf("AssignString: %q is not a valid member of enum %s", s, w.schemaType.Name())
   888  	case schema.EnumRepresentation_Int:
   889  		return datamodel.ErrWrongKind{
   890  			TypeName:        w.schemaType.Name(),
   891  			MethodName:      "AssignString",
   892  			AppropriateKind: datamodel.KindSet_JustInt,
   893  			ActualKind:      datamodel.Kind_String,
   894  		}
   895  	default:
   896  		return (*_assembler)(w).AssignString(s)
   897  	}
   898  }
   899  
   900  func (w *_assemblerRepr) AssignBytes(p []byte) error {
   901  	switch stg := reprStrategy(w.schemaType).(type) {
   902  	case schema.UnionRepresentation_Kinded:
   903  		return w.asKinded(stg, datamodel.Kind_Bytes).AssignBytes(p)
   904  	default:
   905  		return (*_assembler)(w).AssignBytes(p)
   906  	}
   907  }
   908  
   909  func (w *_assemblerRepr) AssignLink(link datamodel.Link) error {
   910  	switch stg := reprStrategy(w.schemaType).(type) {
   911  	case schema.UnionRepresentation_Kinded:
   912  		return w.asKinded(stg, datamodel.Kind_Link).AssignLink(link)
   913  	default:
   914  		return (*_assembler)(w).AssignLink(link)
   915  	}
   916  }
   917  
   918  func (w *_assemblerRepr) AssignNode(node datamodel.Node) error {
   919  	// TODO: attempt to take a shortcut, like assembler.AssignNode
   920  	if uintNode, ok := node.(datamodel.UintNode); ok {
   921  		return w.assignUInt(uintNode)
   922  	}
   923  	return datamodel.Copy(node, w)
   924  }
   925  
   926  func (w *_assemblerRepr) Prototype() datamodel.NodePrototype {
   927  	panic("bindnode TODO: Assembler.Prototype")
   928  }
   929  
   930  type _structAssemblerRepr _structAssembler
   931  
   932  func (w *_structAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
   933  	switch stg := reprStrategy(w.schemaType).(type) {
   934  	case schema.StructRepresentation_Map:
   935  		return (*_structAssembler)(w).AssembleKey()
   936  	case schema.StructRepresentation_Stringjoin,
   937  		schema.StructRepresentation_StringPairs:
   938  		// 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.
   939  		return _errorAssembler{datamodel.ErrWrongKind{
   940  			TypeName:        w.schemaType.Name() + ".Repr",
   941  			MethodName:      "AssembleKey",
   942  			AppropriateKind: datamodel.KindSet_JustMap,
   943  			ActualKind:      datamodel.Kind_String,
   944  		}}
   945  	case schema.StructRepresentation_Tuple, schema.StructRepresentation_ListPairs:
   946  		return _errorAssembler{datamodel.ErrWrongKind{
   947  			TypeName:        w.schemaType.Name() + ".Repr",
   948  			MethodName:      "AssembleKey",
   949  			AppropriateKind: datamodel.KindSet_JustMap,
   950  			ActualKind:      datamodel.Kind_List,
   951  		}}
   952  	default:
   953  		return _errorAssembler{fmt.Errorf("bindnode AssembleKey TODO: %T", stg)}
   954  	}
   955  }
   956  
   957  func (w *_structAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
   958  	switch stg := reprStrategy(w.schemaType).(type) {
   959  	case schema.StructRepresentation_Map:
   960  		key := w.curKey.val.String()
   961  		revKey := inboundMappedKey(w.schemaType, stg, key)
   962  		w.curKey.val.SetString(revKey)
   963  
   964  		valAsm := (*_structAssembler)(w).AssembleValue()
   965  		valAsm = assemblerRepr(valAsm)
   966  		return valAsm
   967  	default:
   968  		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
   969  	}
   970  }
   971  
   972  func (w *_structAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
   973  	if err := w.AssembleKey().AssignString(k); err != nil {
   974  		return nil, err
   975  	}
   976  	am := w.AssembleValue()
   977  	return am, nil
   978  }
   979  
   980  func (w *_structAssemblerRepr) Finish() error {
   981  	switch stg := reprStrategy(w.schemaType).(type) {
   982  	case schema.StructRepresentation_Map:
   983  		err := (*_structAssembler)(w).Finish()
   984  		if err, ok := err.(schema.ErrMissingRequiredField); ok {
   985  			for i, name := range err.Missing {
   986  				serial := outboundMappedKey(stg, name)
   987  				if serial != name {
   988  					err.Missing[i] += fmt.Sprintf(" (serial:%q)", serial)
   989  				}
   990  			}
   991  		}
   992  		return err
   993  	default:
   994  		return fmt.Errorf("bindnode Finish TODO: %T", stg)
   995  	}
   996  }
   997  
   998  func (w *_structAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
   999  	panic("bindnode TODO")
  1000  }
  1001  
  1002  func (w *_structAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
  1003  	panic("bindnode TODO: struct ValuePrototype")
  1004  }
  1005  
  1006  type _mapAssemblerRepr _mapAssembler
  1007  
  1008  func (w *_mapAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
  1009  	asm := (*_mapAssembler)(w).AssembleKey()
  1010  	return (*_assemblerRepr)(asm.(*_assembler))
  1011  }
  1012  
  1013  func (w *_mapAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
  1014  	asm := (*_mapAssembler)(w).AssembleValue()
  1015  	return (*_assemblerRepr)(asm.(*_assembler))
  1016  }
  1017  
  1018  func (w *_mapAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
  1019  	if err := w.AssembleKey().AssignString(k); err != nil {
  1020  		return nil, err
  1021  	}
  1022  	am := w.AssembleValue()
  1023  	return am, nil
  1024  }
  1025  
  1026  func (w *_mapAssemblerRepr) Finish() error {
  1027  	return (*_mapAssembler)(w).Finish()
  1028  }
  1029  
  1030  func (w *_mapAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
  1031  	panic("bindnode TODO")
  1032  }
  1033  
  1034  func (w *_mapAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
  1035  	panic("bindnode TODO: struct ValuePrototype")
  1036  }
  1037  
  1038  type _listStructAssemblerRepr _structAssembler
  1039  
  1040  func (w *_listStructAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
  1041  	switch stg := reprStrategy(w.schemaType).(type) {
  1042  	case schema.StructRepresentation_Tuple:
  1043  		fields := w.schemaType.Fields()
  1044  		if w.nextIndex >= len(fields) {
  1045  			return _errorAssembler{datamodel.ErrNotExists{
  1046  				Segment: datamodel.PathSegmentOfInt(int64(w.nextIndex)),
  1047  			}}
  1048  		}
  1049  		field := fields[w.nextIndex]
  1050  		w.doneFields[w.nextIndex] = true
  1051  		w.nextIndex++
  1052  
  1053  		entryAsm, err := (*_structAssembler)(w).AssembleEntry(field.Name())
  1054  		if err != nil {
  1055  			return _errorAssembler{err}
  1056  		}
  1057  		entryAsm = assemblerRepr(entryAsm)
  1058  		return entryAsm
  1059  	case schema.StructRepresentation_ListPairs:
  1060  		return &_listpairsFieldAssemblerRepr{parent: (*_structAssembler)(w)}
  1061  	default:
  1062  		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
  1063  	}
  1064  }
  1065  
  1066  func (w *_listStructAssemblerRepr) Finish() error {
  1067  	switch stg := reprStrategy(w.schemaType).(type) {
  1068  	case schema.StructRepresentation_Tuple, schema.StructRepresentation_ListPairs:
  1069  		return (*_structAssembler)(w).Finish()
  1070  	default:
  1071  		return fmt.Errorf("bindnode Finish TODO: %T", stg)
  1072  	}
  1073  }
  1074  
  1075  func (w *_listStructAssemblerRepr) ValuePrototype(idx int64) datamodel.NodePrototype {
  1076  	panic("bindnode TODO: list ValuePrototype")
  1077  }
  1078  
  1079  type _listpairsFieldAssemblerRepr struct {
  1080  	parent *_structAssembler
  1081  }
  1082  
  1083  func (w _listpairsFieldAssemblerRepr) BeginMap(int64) (datamodel.MapAssembler, error) {
  1084  	return nil, datamodel.ErrWrongKind{
  1085  		TypeName:        w.parent.schemaType.Name(),
  1086  		MethodName:      "BeginMap",
  1087  		AppropriateKind: datamodel.KindSet_JustList,
  1088  		ActualKind:      datamodel.Kind_Map,
  1089  	}
  1090  }
  1091  func (w *_listpairsFieldAssemblerRepr) BeginList(int64) (datamodel.ListAssembler, error) {
  1092  	return &_listpairsFieldListAssemblerRepr{parent: w.parent}, nil
  1093  }
  1094  func (w _listpairsFieldAssemblerRepr) AssignNull() error {
  1095  	return datamodel.ErrWrongKind{
  1096  		TypeName:        w.parent.schemaType.Name(),
  1097  		MethodName:      "AssignNull",
  1098  		AppropriateKind: datamodel.KindSet_JustList,
  1099  		ActualKind:      datamodel.Kind_Map,
  1100  	}
  1101  }
  1102  func (w _listpairsFieldAssemblerRepr) AssignBool(bool) error {
  1103  	return datamodel.ErrWrongKind{
  1104  		TypeName:        w.parent.schemaType.Name(),
  1105  		MethodName:      "AssignBool",
  1106  		AppropriateKind: datamodel.KindSet_JustList,
  1107  		ActualKind:      datamodel.Kind_Map,
  1108  	}
  1109  }
  1110  func (w _listpairsFieldAssemblerRepr) AssignInt(int64) error {
  1111  	return datamodel.ErrWrongKind{
  1112  		TypeName:        w.parent.schemaType.Name(),
  1113  		MethodName:      "AssignInt",
  1114  		AppropriateKind: datamodel.KindSet_JustList,
  1115  		ActualKind:      datamodel.Kind_Map,
  1116  	}
  1117  }
  1118  func (w _listpairsFieldAssemblerRepr) AssignFloat(float64) error {
  1119  	return datamodel.ErrWrongKind{
  1120  		TypeName:        w.parent.schemaType.Name(),
  1121  		MethodName:      "AssignFloat",
  1122  		AppropriateKind: datamodel.KindSet_JustList,
  1123  		ActualKind:      datamodel.Kind_Map,
  1124  	}
  1125  }
  1126  func (w _listpairsFieldAssemblerRepr) AssignString(string) error {
  1127  	return datamodel.ErrWrongKind{
  1128  		TypeName:        w.parent.schemaType.Name(),
  1129  		MethodName:      "AssignString",
  1130  		AppropriateKind: datamodel.KindSet_JustList,
  1131  		ActualKind:      datamodel.Kind_Map,
  1132  	}
  1133  }
  1134  func (w _listpairsFieldAssemblerRepr) AssignBytes([]byte) error {
  1135  	return datamodel.ErrWrongKind{
  1136  		TypeName:        w.parent.schemaType.Name(),
  1137  		MethodName:      "AssignBytes",
  1138  		AppropriateKind: datamodel.KindSet_JustList,
  1139  		ActualKind:      datamodel.Kind_Map,
  1140  	}
  1141  }
  1142  func (w _listpairsFieldAssemblerRepr) AssignLink(datamodel.Link) error {
  1143  	return datamodel.ErrWrongKind{
  1144  		TypeName:        w.parent.schemaType.Name(),
  1145  		MethodName:      "AssignLink",
  1146  		AppropriateKind: datamodel.KindSet_JustList,
  1147  		ActualKind:      datamodel.Kind_Map,
  1148  	}
  1149  }
  1150  
  1151  func (w *_listpairsFieldAssemblerRepr) AssignNode(n datamodel.Node) error {
  1152  	return datamodel.Copy(n, w)
  1153  }
  1154  
  1155  func (w _listpairsFieldAssemblerRepr) Prototype() datamodel.NodePrototype {
  1156  	panic("bindnode TODO: listpairs field Prototype")
  1157  }
  1158  
  1159  type _listpairsFieldListAssemblerRepr struct {
  1160  	parent *_structAssembler
  1161  	idx    int
  1162  }
  1163  
  1164  func (w *_listpairsFieldListAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
  1165  	w.idx++
  1166  	switch w.idx {
  1167  	case 1:
  1168  		return w.parent.AssembleKey()
  1169  	case 2:
  1170  		asm := w.parent.AssembleValue()
  1171  		return assemblerRepr(asm.(*_assembler))
  1172  	default:
  1173  		return _errorAssembler{fmt.Errorf("bindnode: too many values in listpairs field")}
  1174  	}
  1175  }
  1176  
  1177  func (w *_listpairsFieldListAssemblerRepr) Finish() error {
  1178  	return nil
  1179  }
  1180  
  1181  func (w *_listpairsFieldListAssemblerRepr) ValuePrototype(idx int64) datamodel.NodePrototype {
  1182  	panic("bindnode TODO: listpairs field ValuePrototype")
  1183  }
  1184  
  1185  // Note that lists do not have any representation strategy right now.
  1186  type _listAssemblerRepr _listAssembler
  1187  
  1188  func (w *_listAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
  1189  	asm := (*_listAssembler)(w).AssembleValue()
  1190  	return (*_assemblerRepr)(asm.(*_assembler))
  1191  }
  1192  
  1193  func (w *_listAssemblerRepr) Finish() error {
  1194  	return (*_listAssembler)(w).Finish()
  1195  }
  1196  
  1197  func (w *_listAssemblerRepr) ValuePrototype(idx int64) datamodel.NodePrototype {
  1198  	panic("bindnode TODO: list ValuePrototype")
  1199  }
  1200  
  1201  type _unionAssemblerRepr _unionAssembler
  1202  
  1203  func (w *_unionAssemblerRepr) AssembleKey() datamodel.NodeAssembler {
  1204  	switch stg := reprStrategy(w.schemaType).(type) {
  1205  	case schema.UnionRepresentation_Keyed:
  1206  		return (*_unionAssembler)(w).AssembleKey()
  1207  	default:
  1208  		return _errorAssembler{fmt.Errorf("bindnode AssembleKey TODO: %T", stg)}
  1209  	}
  1210  }
  1211  
  1212  func (w *_unionAssemblerRepr) AssembleValue() datamodel.NodeAssembler {
  1213  	switch stg := reprStrategy(w.schemaType).(type) {
  1214  	case schema.UnionRepresentation_Keyed:
  1215  		key := w.curKey.val.String()
  1216  		revKey := inboundMappedType(w.schemaType, stg, key)
  1217  		w.curKey.val.SetString(revKey)
  1218  
  1219  		valAsm := (*_unionAssembler)(w).AssembleValue()
  1220  		valAsm = assemblerRepr(valAsm)
  1221  		return valAsm
  1222  	default:
  1223  		return _errorAssembler{fmt.Errorf("bindnode AssembleValue TODO: %T", stg)}
  1224  	}
  1225  }
  1226  
  1227  func (w *_unionAssemblerRepr) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
  1228  	if err := w.AssembleKey().AssignString(k); err != nil {
  1229  		return nil, err
  1230  	}
  1231  	am := w.AssembleValue()
  1232  	return am, nil
  1233  }
  1234  
  1235  func (w *_unionAssemblerRepr) Finish() error {
  1236  	switch stg := reprStrategy(w.schemaType).(type) {
  1237  	case schema.UnionRepresentation_Keyed:
  1238  		return (*_unionAssembler)(w).Finish()
  1239  	default:
  1240  		return fmt.Errorf("bindnode Finish TODO: %T", stg)
  1241  	}
  1242  }
  1243  
  1244  func (w *_unionAssemblerRepr) KeyPrototype() datamodel.NodePrototype {
  1245  	panic("bindnode TODO")
  1246  }
  1247  
  1248  func (w *_unionAssemblerRepr) ValuePrototype(k string) datamodel.NodePrototype {
  1249  	panic("bindnode TODO: union ValuePrototype")
  1250  }
  1251  
  1252  type _structIteratorRepr _structIterator
  1253  
  1254  func (w *_structIteratorRepr) Next() (key, value datamodel.Node, _ error) {
  1255  	switch stg := reprStrategy(w.schemaType).(type) {
  1256  	case schema.StructRepresentation_Map:
  1257  		for {
  1258  			key, value, err := (*_structIterator)(w).Next()
  1259  			if err != nil {
  1260  				return nil, nil, err
  1261  			}
  1262  			if value.IsAbsent() {
  1263  				continue
  1264  			}
  1265  			keyStr, _ := key.AsString()
  1266  			mappedKey := outboundMappedKey(stg, keyStr)
  1267  			if mappedKey != keyStr {
  1268  				key = basicnode.NewString(mappedKey)
  1269  			}
  1270  			return key, reprNode(value), nil
  1271  		}
  1272  	default:
  1273  		return nil, nil, fmt.Errorf("bindnode Next TODO: %T", stg)
  1274  	}
  1275  }
  1276  
  1277  func (w *_structIteratorRepr) Done() bool {
  1278  	switch stg := reprStrategy(w.schemaType).(type) {
  1279  	case schema.StructRepresentation_Map:
  1280  		// TODO: the fact that repr map iterators skip absents should be
  1281  		// documented somewhere
  1282  		return w.nextIndex >= w.reprEnd
  1283  	default:
  1284  		panic(fmt.Sprintf("bindnode Done TODO: %T", stg))
  1285  	}
  1286  }
  1287  
  1288  type _unionIteratorRepr _unionIterator
  1289  
  1290  func (w *_unionIteratorRepr) Next() (key, value datamodel.Node, _ error) {
  1291  	switch stg := reprStrategy(w.schemaType).(type) {
  1292  	case schema.UnionRepresentation_Keyed:
  1293  		key, value, err := (*_unionIterator)(w).Next()
  1294  		if err != nil {
  1295  			return nil, nil, err
  1296  		}
  1297  		keyStr, _ := key.AsString()
  1298  		mappedKey := outboundMappedType(stg, keyStr)
  1299  		if mappedKey != keyStr {
  1300  			key = basicnode.NewString(mappedKey)
  1301  		}
  1302  		return key, reprNode(value), nil
  1303  	default:
  1304  		return nil, nil, fmt.Errorf("bindnode Next TODO: %T", stg)
  1305  	}
  1306  }
  1307  
  1308  func (w *_unionIteratorRepr) Done() bool {
  1309  	switch stg := reprStrategy(w.schemaType).(type) {
  1310  	case schema.UnionRepresentation_Keyed:
  1311  		return (*_unionIterator)(w).Done()
  1312  	default:
  1313  		panic(fmt.Sprintf("bindnode Done TODO: %T", stg))
  1314  	}
  1315  }