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 }