github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/marshal/decode.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package marshal 23 24 import ( 25 "context" 26 "fmt" 27 "reflect" 28 "sync" 29 30 "github.com/dolthub/dolt/go/store/types" 31 ) 32 33 // Unmarshal converts a Noms value into a Go value. It decodes v and stores the 34 // result in the value pointed to by out. 35 // 36 // Unmarshal uses the inverse of the encodings that Marshal uses with the 37 // following additional rules: 38 // 39 // To unmarshal a Noms struct into a Go struct, Unmarshal matches incoming 40 // object fields to the fields used by Marshal (either the struct field name or 41 // its tag). Unmarshal will only set exported fields of the struct. The name 42 // of the Go struct must match (ignoring case) the name of the Noms struct. All 43 // exported fields on the Go struct must be present in the Noms struct, unless 44 // the field on the Go struct is marked with the "omitempty" tag. Go struct 45 // fields also support the "original" tag which causes the Go field to receive 46 // the entire original unmarshaled Noms struct. 47 // 48 // To unmarshal a Noms list or set into a slice, Unmarshal resets the slice 49 // length to zero and then appends each element to the slice. If the Go slice 50 // was nil a new slice is created when an element is added. 51 // 52 // To unmarshal a Noms list into a Go array, Unmarshal decodes Noms list 53 // elements into corresponding Go array elements. 54 // 55 // To unmarshal a Noms map into a Go map, Unmarshal decodes Noms key and values 56 // into corresponding Go array elements. If the Go map was nil a new map is 57 // created if any value is set. 58 // 59 // To unmarshal a Noms set into a Go map, the field must be tagged with `noms:",set"`, 60 // and it must have a type of map[<value-type>]struct{}. Unmarshal decodes into 61 // Go map keys corresponding to the set values and assigns each key a value of struct{}{}. 62 // 63 // When unmarshalling onto interface{} the following rules are used: 64 // - types.Bool -> bool 65 // - types.List -> []T, where T is determined recursively using the same rules. 66 // - types.Set -> depends on `noms:",set"` annotation and field type: 67 // - without the annotation, same as types.List 68 // - with the annotation, same as types.Map for map[T]struct{} fields and same as types.List for slice fields 69 // - types.Map -> map[T]V, where T and V is determined recursively using the 70 // same rules. 71 // - types.Float -> float64 72 // - types.String -> string 73 // - *types.Type -> *types.Type 74 // - types.Union -> interface 75 // - Everything else an error 76 // 77 // Unmarshal returns an UnmarshalTypeMismatchError if: 78 // - a Noms value is not appropriate for a given target type 79 // - a Noms number overflows the target type 80 // - a Noms list is decoded into a Go array of a different length 81 func Unmarshal(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, out interface{}) (err error) { 82 return UnmarshalOpt(ctx, nbf, v, Opt{}, out) 83 } 84 85 // UnmarshalOpt is like Unmarshal but provides additional options. 86 func UnmarshalOpt(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, opt Opt, out interface{}) (err error) { 87 rv := reflect.ValueOf(out) 88 if rv.Kind() != reflect.Ptr || rv.IsNil() { 89 return &InvalidUnmarshalError{reflect.TypeOf(out)} 90 } 91 rv = rv.Elem() 92 nt := nomsTags{ 93 set: opt.Set, 94 } 95 d, err := typeDecoder(rv.Type(), nt) 96 97 if err != nil { 98 return err 99 } 100 101 err = d(ctx, nbf, v, rv) 102 103 if err != nil { 104 return err 105 } 106 107 return err 108 } 109 110 // Unmarshaler is an interface types can implement to provide their own 111 // decoding. 112 // 113 // You probably want to implement this on a pointer to a type, otherwise 114 // calling UnmarshalNoms will effectively do nothing. For example, to unmarshal 115 // a MyType you would define: 116 // 117 // func (t *MyType) UnmarshalNoms(v types.Value) error {} 118 type Unmarshaler interface { 119 // UnmarshalNoms decodes v, or returns an error. 120 UnmarshalNoms(ctx context.Context, nbf *types.NomsBinFormat, v types.Value) error 121 } 122 123 var unmarshalerInterface = reflect.TypeOf((*Unmarshaler)(nil)).Elem() 124 125 // InvalidUnmarshalError describes an invalid argument passed to Unmarshal. (The 126 // argument to Unmarshal must be a non-nil pointer.) 127 type InvalidUnmarshalError struct { 128 Type reflect.Type 129 } 130 131 func (e *InvalidUnmarshalError) Error() string { 132 if e.Type == nil { 133 return "Cannot unmarshal into Go nil value" 134 } 135 136 if e.Type.Kind() != reflect.Ptr { 137 return "Cannot unmarshal into Go non pointer of type " + e.Type.String() 138 } 139 return "Cannot unmarshal into Go nil pointer of type " + e.Type.String() 140 } 141 142 // UnmarshalTypeMismatchError describes a Noms value that was not appropriate 143 // for a value of a specific Go type. 144 type UnmarshalTypeMismatchError struct { 145 Value types.Value 146 Type reflect.Type // type of Go value it could not be assigned to 147 details string 148 nbf *types.NomsBinFormat 149 } 150 151 func (e *UnmarshalTypeMismatchError) Error() string { 152 var tStr string 153 if e.Type != nil { 154 tStr = "to: " + e.Type.String() 155 } 156 157 valType, err := types.TypeOf(e.Value) 158 159 var valTStr string 160 if err == nil { 161 valTStr, err = valType.Describe(context.Background()) 162 163 if err == nil { 164 valTStr = "from: " + valTStr 165 } 166 } 167 168 return fmt.Sprintf("Cannot unmarshal %s %s details: %s", valTStr, tStr, e.details) 169 } 170 171 func overflowError(nbf *types.NomsBinFormat, v types.Float, t reflect.Type) *UnmarshalTypeMismatchError { 172 return &UnmarshalTypeMismatchError{v, t, fmt.Sprintf("(%g does not fit in %s)", v, t), nbf} 173 } 174 175 type decoderFunc func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error 176 177 func typeDecoder(t reflect.Type, tags nomsTags) (decoderFunc, error) { 178 if reflect.PtrTo(t).Implements(unmarshalerInterface) { 179 return marshalerDecoder(t), nil 180 } 181 182 switch t.Kind() { 183 case reflect.Bool: 184 return boolDecoder, nil 185 case reflect.Float32, reflect.Float64: 186 return floatDecoder, nil 187 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 188 return intDecoder, nil 189 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 190 return uintDecoder, nil 191 case reflect.String: 192 return stringDecoder, nil 193 case reflect.Struct: 194 return structDecoder(t) 195 case reflect.Interface: 196 return interfaceDecoder(t) 197 case reflect.Slice: 198 return sliceDecoder(t) 199 case reflect.Array: 200 return arrayDecoder(t) 201 case reflect.Map: 202 if shouldMapDecodeFromSet(t, tags) { 203 return mapFromSetDecoder(t) 204 } 205 return mapDecoder(t, tags) 206 case reflect.Ptr: 207 // Allow implementations of types.Value (like *types.Type) 208 if t.Implements(nomsValueInterface) { 209 return nomsValueDecoder, nil 210 } 211 fallthrough 212 default: 213 return nil, &UnsupportedTypeError{Type: t} 214 } 215 } 216 217 func boolDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 218 if b, ok := v.(types.Bool); ok { 219 rv.SetBool(bool(b)) 220 } else { 221 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 222 } 223 224 return nil 225 } 226 227 func stringDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 228 if s, ok := v.(types.String); ok { 229 rv.SetString(string(s)) 230 } else { 231 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 232 } 233 234 return nil 235 } 236 237 func floatDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 238 if n, ok := v.(types.Float); ok { 239 rv.SetFloat(float64(n)) 240 } else { 241 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 242 } 243 244 return nil 245 } 246 247 func intDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 248 if n, ok := v.(types.Float); ok { 249 i := int64(n) 250 if rv.OverflowInt(i) { 251 return overflowError(nbf, n, rv.Type()) 252 } 253 rv.SetInt(i) 254 return nil 255 } 256 257 // types.Int is currently encoded as types.Float during marshalling 258 // the block below exists to prepare for a compatibility breaking change 259 // todo: update comment after breaking change is made 260 if n, ok := v.(types.Int); ok { 261 rv.SetInt(int64(n)) 262 return nil 263 } 264 265 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 266 } 267 268 func uintDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 269 if n, ok := v.(types.Float); ok { 270 u := uint64(n) 271 if rv.OverflowUint(u) { 272 return overflowError(nbf, n, rv.Type()) 273 } 274 rv.SetUint(u) 275 return nil 276 } 277 278 // types.Uint is currently encoded as types.Float during marshalling 279 // the block below exists to prepare for a compatibility breaking change 280 // todo: update comment after breaking change is made 281 if n, ok := v.(types.Uint); ok { 282 rv.SetUint(uint64(n)) 283 return nil 284 } 285 286 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 287 } 288 289 type decoderCacheT struct { 290 sync.RWMutex 291 m map[reflect.Type]decoderFunc 292 } 293 294 var decoderCache = &decoderCacheT{} 295 296 // Separate Set decoder cache because the same type with and without the 297 // `noms:",set"` tag decode differently (Set vs Map). 298 var setDecoderCache = &decoderCacheT{} 299 300 func (c *decoderCacheT) get(t reflect.Type) decoderFunc { 301 c.RLock() 302 defer c.RUnlock() 303 return c.m[t] 304 } 305 306 func (c *decoderCacheT) set(t reflect.Type, d decoderFunc) { 307 c.Lock() 308 defer c.Unlock() 309 if c.m == nil { 310 c.m = map[reflect.Type]decoderFunc{} 311 } 312 c.m[t] = d 313 } 314 315 type decField struct { 316 name string 317 decoder decoderFunc 318 index []int 319 omitEmpty bool 320 original bool 321 } 322 323 func structDecoderFields(t reflect.Type) ([]decField, error) { 324 fields := make([]decField, 0, t.NumField()) 325 for i := 0; i < t.NumField(); i++ { 326 index := make([]int, 1) 327 index[0] = i 328 f := t.Field(i) 329 tags, err := getTags(f) 330 331 if err != nil { 332 return nil, err 333 } 334 335 if tags.skip { 336 continue 337 } 338 339 if f.Anonymous && f.PkgPath == "" && !tags.hasName { 340 embeddedFields, err := structDecoderFields(f.Type) 341 342 if err != nil { 343 return nil, err 344 } 345 346 for _, ef := range embeddedFields { 347 ef.index = append(index, ef.index...) 348 fields = append(fields, ef) 349 } 350 continue 351 } 352 353 err = validateField(f, t) 354 355 if err != nil { 356 return nil, err 357 } 358 359 decFunc, err := typeDecoder(f.Type, tags) 360 361 if err != nil { 362 return nil, err 363 } 364 365 fields = append(fields, decField{ 366 name: tags.name, 367 decoder: decFunc, 368 index: index, 369 omitEmpty: tags.omitEmpty, 370 original: tags.original, 371 }) 372 } 373 return fields, nil 374 } 375 376 func structDecoder(t reflect.Type) (decoderFunc, error) { 377 if t.Implements(nomsValueInterface) { 378 return nomsValueDecoder, nil 379 } 380 381 d := decoderCache.get(t) 382 if d != nil { 383 return d, nil 384 } 385 386 fields, err := structDecoderFields(t) 387 388 if err != nil { 389 return nil, err 390 } 391 392 d = func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 393 s, ok := v.(types.Struct) 394 if !ok { 395 return &UnmarshalTypeMismatchError{v, rv.Type(), "expected struct", nbf} 396 } 397 398 for _, f := range fields { 399 sf := rv.FieldByIndex(f.index) 400 if f.original { 401 if sf.Type() != reflect.TypeOf(s) { 402 return &UnmarshalTypeMismatchError{v, rv.Type(), "field with tag \"original\" must have type Struct", nbf} 403 } 404 sf.Set(reflect.ValueOf(s)) 405 continue 406 } 407 fv, ok, err := s.MaybeGet(f.name) 408 409 if err != nil { 410 return err 411 } 412 413 if ok { 414 err = f.decoder(ctx, nbf, fv, sf) 415 416 if err != nil { 417 return err 418 } 419 } else if !f.omitEmpty { 420 return &UnmarshalTypeMismatchError{v, rv.Type(), "missing field \"" + f.name + "\"", nbf} 421 } 422 } 423 424 return nil 425 } 426 427 decoderCache.set(t, d) 428 return d, nil 429 } 430 431 func nomsValueDecoder(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 432 if !reflect.TypeOf(v).AssignableTo(rv.Type()) { 433 return &UnmarshalTypeMismatchError{v, rv.Type(), "", nbf} 434 } 435 rv.Set(reflect.ValueOf(v)) 436 437 return nil 438 } 439 440 func marshalerDecoder(t reflect.Type) decoderFunc { 441 return func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 442 ptr := reflect.New(t) 443 err := ptr.Interface().(Unmarshaler).UnmarshalNoms(ctx, nbf, v) 444 if err != nil { 445 return err 446 } 447 rv.Set(ptr.Elem()) 448 return nil 449 } 450 } 451 452 func iterListOrSlice(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, t reflect.Type, f func(c types.Value, i uint64) error) error { 453 switch v := v.(type) { 454 case types.List: 455 err := v.Iter(ctx, func(v types.Value, idx uint64) (stop bool, err error) { 456 err = f(v, idx) 457 return 458 }) 459 if err != nil { 460 return err 461 } 462 463 case types.Set: 464 i := uint64(0) 465 err := v.IterAll(ctx, func(cv types.Value) error { 466 err := f(cv, i) 467 i++ 468 469 return err 470 }) 471 472 if err != nil { 473 return err 474 } 475 default: 476 return &UnmarshalTypeMismatchError{v, t, "", nbf} 477 } 478 479 return nil 480 } 481 482 func sliceDecoder(t reflect.Type) (decoderFunc, error) { 483 d := decoderCache.get(t) 484 if d != nil { 485 return d, nil 486 } 487 488 var decoder decoderFunc 489 var init sync.RWMutex 490 init.Lock() 491 defer init.Unlock() 492 d = func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 493 var slice reflect.Value 494 if rv.IsNil() { 495 slice = rv 496 } else { 497 slice = rv.Slice(0, 0) 498 } 499 init.RLock() 500 defer init.RUnlock() 501 err := iterListOrSlice(ctx, nbf, v, t, func(v types.Value, _ uint64) error { 502 elemRv := reflect.New(t.Elem()).Elem() 503 err := decoder(ctx, nbf, v, elemRv) 504 505 if err != nil { 506 return err 507 } 508 509 slice = reflect.Append(slice, elemRv) 510 return nil 511 }) 512 513 if err != nil { 514 return err 515 } 516 517 rv.Set(slice) 518 519 return nil 520 } 521 522 decoderCache.set(t, d) 523 524 var err error 525 decoder, err = typeDecoder(t.Elem(), nomsTags{}) 526 527 if err != nil { 528 return nil, err 529 } 530 531 return d, nil 532 } 533 534 func arrayDecoder(t reflect.Type) (decoderFunc, error) { 535 d := decoderCache.get(t) 536 if d != nil { 537 return d, nil 538 } 539 540 var decoder decoderFunc 541 var init sync.RWMutex 542 init.Lock() 543 defer init.Unlock() 544 d = func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 545 size := t.Len() 546 list, ok := v.(types.Collection) 547 if !ok { 548 return &UnmarshalTypeMismatchError{v, t, "", nbf} 549 } 550 551 l := int(list.Len()) 552 if l != size { 553 return &UnmarshalTypeMismatchError{v, t, "length does not match", nbf} 554 } 555 init.RLock() 556 defer init.RUnlock() 557 return iterListOrSlice(ctx, nbf, list, t, func(v types.Value, i uint64) error { 558 return decoder(ctx, nbf, v, rv.Index(int(i))) 559 }) 560 } 561 562 decoderCache.set(t, d) 563 564 var err error 565 decoder, err = typeDecoder(t.Elem(), nomsTags{}) 566 567 if err != nil { 568 return nil, err 569 } 570 571 return d, nil 572 } 573 574 func mapFromSetDecoder(t reflect.Type) (decoderFunc, error) { 575 d := setDecoderCache.get(t) 576 if d != nil { 577 return d, nil 578 } 579 580 var decoder decoderFunc 581 var init sync.RWMutex 582 init.Lock() 583 defer init.Unlock() 584 d = func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 585 m := rv 586 587 nomsSet, ok := v.(types.Set) 588 if !ok { 589 return &UnmarshalTypeMismatchError{v, t, `field has "set" tag`, nbf} 590 } 591 592 init.RLock() 593 defer init.RUnlock() 594 err := nomsSet.IterAll(ctx, func(v types.Value) error { 595 keyRv := reflect.New(t.Key()).Elem() 596 err := decoder(ctx, nbf, v, keyRv) 597 598 if err != nil { 599 return err 600 } 601 602 if m.IsNil() { 603 m = reflect.MakeMap(t) 604 } 605 606 m.SetMapIndex(keyRv, reflect.New(t.Elem()).Elem()) 607 return nil 608 }) 609 610 if err != nil { 611 return err 612 } 613 614 rv.Set(m) 615 return nil 616 } 617 618 setDecoderCache.set(t, d) 619 620 var err error 621 decoder, err = typeDecoder(t.Key(), nomsTags{}) 622 623 if err != nil { 624 return nil, err 625 } 626 627 return d, nil 628 } 629 630 func mapDecoder(t reflect.Type, tags nomsTags) (decoderFunc, error) { 631 d := decoderCache.get(t) 632 if d != nil { 633 return d, nil 634 } 635 636 var keyDecoder decoderFunc 637 var valueDecoder decoderFunc 638 var init sync.RWMutex 639 init.Lock() 640 defer init.Unlock() 641 d = func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 642 m := rv 643 644 // Special case decoding failure if it looks like the "set" tag is missing, 645 // because it's helpful. 646 if _, ok := v.(types.Set); ok && !tags.set { 647 return &UnmarshalTypeMismatchError{v, t, `field missing "set" tag`, nbf} 648 } 649 650 nomsMap, ok := v.(types.Map) 651 if !ok { 652 return &UnmarshalTypeMismatchError{v, t, "", nbf} 653 } 654 655 init.RLock() 656 defer init.RUnlock() 657 err := nomsMap.Iter(ctx, func(k, v types.Value) (stop bool, err error) { 658 keyRv := reflect.New(t.Key()).Elem() 659 err = keyDecoder(ctx, nbf, k, keyRv) 660 661 if err != nil { 662 return 663 } 664 665 valueRv := reflect.New(t.Elem()).Elem() 666 err = valueDecoder(ctx, nbf, v, valueRv) 667 668 if err != nil { 669 return 670 } 671 672 if m.IsNil() { 673 m = reflect.MakeMap(t) 674 } 675 676 m.SetMapIndex(keyRv, valueRv) 677 return 678 }) 679 680 if err != nil { 681 return err 682 } 683 684 rv.Set(m) 685 return nil 686 } 687 688 decoderCache.set(t, d) 689 690 var err error 691 keyDecoder, err = typeDecoder(t.Key(), nomsTags{}) 692 693 if err != nil { 694 return nil, err 695 } 696 697 valueDecoder, err = typeDecoder(t.Elem(), nomsTags{}) 698 699 if err != nil { 700 return nil, err 701 } 702 703 return d, nil 704 } 705 706 func interfaceDecoder(t reflect.Type) (decoderFunc, error) { 707 if t.Implements(nomsValueInterface) { 708 return nomsValueDecoder, nil 709 } 710 711 if t != emptyInterface { 712 return nil, &UnsupportedTypeError{Type: t} 713 } 714 715 return func(ctx context.Context, nbf *types.NomsBinFormat, v types.Value, rv reflect.Value) error { 716 // TODO: Go directly from value to go type 717 vt, err := types.TypeOf(v) 718 719 if err != nil { 720 return err 721 } 722 723 t, err := getGoTypeForNomsType(vt, rv.Type(), v) 724 725 if err != nil { 726 return err 727 } 728 729 i := reflect.New(t).Elem() 730 tdec, err := typeDecoder(t, nomsTags{}) 731 732 if err != nil { 733 return err 734 } 735 736 err = tdec(ctx, nbf, v, i) 737 738 if err != nil { 739 return err 740 } 741 742 rv.Set(i) 743 return nil 744 }, nil 745 } 746 747 func getGoTypeForNomsType(nt *types.Type, rt reflect.Type, v types.Value) (reflect.Type, error) { 748 switch nt.TargetKind() { 749 case types.BoolKind: 750 return reflect.TypeOf(false), nil 751 case types.FloatKind: 752 return reflect.TypeOf(float64(0)), nil 753 case types.StringKind: 754 return reflect.TypeOf(""), nil 755 case types.ListKind, types.SetKind: 756 et, err := getGoTypeForNomsType(nt.Desc.(types.CompoundDesc).ElemTypes[0], rt, v) 757 758 if err != nil { 759 return nil, err 760 } 761 762 return reflect.SliceOf(et), nil 763 case types.MapKind: 764 kt, err := getGoTypeForNomsType(nt.Desc.(types.CompoundDesc).ElemTypes[0], rt, v) 765 766 if err != nil { 767 return nil, err 768 } 769 770 vt, err := getGoTypeForNomsType(nt.Desc.(types.CompoundDesc).ElemTypes[1], rt, v) 771 772 if err != nil { 773 return nil, err 774 } 775 776 return reflect.MapOf(kt, vt), nil 777 case types.UnionKind: 778 // Visit union types to raise potential errors 779 for _, ut := range nt.Desc.(types.CompoundDesc).ElemTypes { 780 getGoTypeForNomsType(ut, rt, v) 781 } 782 return emptyInterface, nil 783 // case types.StructKind: 784 // reflect.StructOf was not added until Go 1.7 785 default: 786 return nil, &UnmarshalTypeMismatchError{Value: v, Type: rt} 787 } 788 } 789 790 func shouldMapDecodeFromSet(rt reflect.Type, tags nomsTags) bool { 791 // map[T]struct{} `noms:,"set"` 792 return tags.set && 793 rt.Elem().Kind() == reflect.Struct && 794 rt.Elem().NumField() == 0 795 }