go-hep.org/x/hep@v0.38.1/groot/rdict/streamer.go (about) 1 // Copyright ©2018 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rdict 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 12 "go-hep.org/x/hep/groot/rbase" 13 "go-hep.org/x/hep/groot/rbytes" 14 "go-hep.org/x/hep/groot/rcont" 15 "go-hep.org/x/hep/groot/rmeta" 16 "go-hep.org/x/hep/groot/root" 17 "go-hep.org/x/hep/groot/rvers" 18 ) 19 20 // StreamerOf generates a StreamerInfo from a reflect.Type. 21 // 22 // StreamerOf panics if the provided type contains non-ROOT compatible types 23 // such as chan, int, uint or func. 24 func StreamerOf(ctx rbytes.StreamerInfoContext, typ reflect.Type) rbytes.StreamerInfo { 25 if isTObject(typ) { 26 name := reflect.New(typ).Elem().Interface().(root.Object).Class() 27 si, err := ctx.StreamerInfo(name, -1) 28 if err == nil { 29 return si 30 } 31 } 32 33 bldr := newStreamerBuilder(ctx, typ) 34 return bldr.genStreamer(typ) 35 } 36 37 type streamerStore interface { 38 rbytes.StreamerInfoContext 39 addStreamer(si rbytes.StreamerInfo) 40 } 41 42 type streamerBuilder struct { 43 ctx streamerStore 44 typ reflect.Type 45 } 46 47 func newStreamerBuilder(ctx rbytes.StreamerInfoContext, typ reflect.Type) *streamerBuilder { 48 return &streamerBuilder{ctx: newStreamerStore(ctx), typ: typ} 49 } 50 51 func (bld *streamerBuilder) genStreamer(typ reflect.Type) rbytes.StreamerInfo { 52 name := typenameOf(typ) 53 si := &StreamerInfo{ 54 named: *rbase.NewNamed(name, name), 55 objarr: rcont.NewObjArray(), 56 clsver: 1, 57 } 58 switch typ.Kind() { 59 case reflect.Struct: 60 si.elems = make([]rbytes.StreamerElement, 0, typ.NumField()) 61 for i := range typ.NumField() { 62 ft := typ.Field(i) 63 si.elems = append(si.elems, bld.genField(typ, ft)) 64 } 65 case reflect.Slice: 66 si.clsver = rvers.StreamerBaseSTL 67 si.elems = []rbytes.StreamerElement{ 68 bld.genStdVectorOf(typ.Elem(), "This", 0), 69 } 70 } 71 return si 72 } 73 74 func (bld *streamerBuilder) genStdVectorOf(typ reflect.Type, name string, offset int32) rbytes.StreamerElement { 75 const esize = 3 * diskPtrSize 76 var ( 77 ename = "" 78 etype rmeta.Enum 79 ) 80 switch typ.Kind() { 81 case reflect.Bool: 82 ename = "vector<bool>" 83 etype = rmeta.Bool 84 case reflect.Int8: 85 ename = "vector<int8_t>" 86 etype = rmeta.Int8 87 case reflect.Int16: 88 ename = "vector<int16_t>" 89 etype = rmeta.Int16 90 case reflect.Int32: 91 ename = "vector<int32_t>" 92 etype = rmeta.Int32 93 case reflect.Int64: 94 ename = "vector<int64_t>" 95 etype = rmeta.Int64 96 case reflect.Uint8: 97 ename = "vector<uint8_t>" 98 etype = rmeta.Uint8 99 case reflect.Uint16: 100 ename = "vector<uint16_t>" 101 etype = rmeta.Uint16 102 case reflect.Uint32: 103 ename = "vector<uint32_t>" 104 etype = rmeta.Uint32 105 case reflect.Uint64: 106 ename = "vector<uint64_t>" 107 etype = rmeta.Uint64 108 case reflect.Float32: 109 switch typ { 110 case reflect.TypeOf(root.Float16(0)): 111 ename = "vector<Float16_t>" 112 etype = rmeta.Float16 113 default: 114 ename = "vector<float>" 115 etype = rmeta.Float32 116 } 117 case reflect.Float64: 118 switch typ { 119 case reflect.TypeOf(root.Double32(0)): 120 ename = "vector<Double32_t>" 121 etype = rmeta.Double32 122 default: 123 ename = "vector<double>" 124 etype = rmeta.Float64 125 } 126 case reflect.String: 127 ename = "vector<string>" 128 etype = rmeta.STLstring 129 case reflect.Struct: 130 ename = fmt.Sprintf("vector<%s>", typenameOf(typ)) 131 etype = rmeta.Any 132 if isTObject(typ) || isTObject(reflect.PointerTo(typ)) { 133 etype = rmeta.Object 134 } 135 case reflect.Slice: 136 ename = typenameOf(typ) 137 if strings.HasSuffix(ename, ">") { 138 ename += " " 139 } 140 ename = fmt.Sprintf("vector<%s>", ename) 141 etype = rmeta.Any 142 default: 143 panic(fmt.Errorf("rdict: invalid slice type %v", typ)) 144 } 145 146 return NewCxxStreamerSTL( 147 StreamerElement{ 148 named: *rbase.NewNamed(name, ""), 149 etype: rmeta.Streamer, 150 esize: esize, 151 offset: offset, 152 ename: ename, 153 }, rmeta.STLvector, etype, 154 ) 155 } 156 157 func (bld *streamerBuilder) genPtr(typ reflect.Type, name string, offset int32) rbytes.StreamerElement { 158 // FIXME(sbinet): is typ always a struct? 159 // switch typ.Kind() { 160 // case reflect.Struct: 161 // default: 162 // panic(fmt.Errorf("rdict: invalid ptr-to type %v", typ)) 163 // } 164 165 ptr := reflect.PointerTo(typ) 166 se := StreamerElement{ 167 named: *rbase.NewNamed(name, ""), 168 etype: rmeta.AnyP, 169 esize: int32(ptrSize), 170 offset: offset, 171 ename: typenameOf(ptr), 172 } 173 174 if isTObject(ptr) { 175 se.etype = rmeta.ObjectP 176 return &StreamerObjectPointer{se} 177 } 178 179 return &StreamerObjectAnyPointer{se} 180 } 181 182 func (bld *streamerBuilder) genArrayOf(n int, typ reflect.Type, name string, offset int32) rbytes.StreamerElement { 183 var ( 184 arrlen = int32(n) 185 dims = []int32{arrlen} 186 maxidx [5]int32 187 esize = arrlen 188 etype rmeta.Enum 189 ename = "" 190 ) 191 192 for typ.Kind() == reflect.Array && len(dims) < 5 { 193 dim := int32(typ.Len()) 194 dims = append(dims, dim) 195 typ = typ.Elem() 196 esize *= dim 197 } 198 copy(maxidx[:], dims) 199 arrdim := int32(len(dims)) 200 201 switch typ.Kind() { 202 case reflect.Bool: 203 esize *= 1 204 ename = "bool" 205 etype = rmeta.Bool 206 207 case reflect.Int8: 208 esize *= 1 209 ename = "int8_t" 210 etype = rmeta.Int8 211 212 case reflect.Int16: 213 esize *= 2 214 ename = "int16_t" 215 etype = rmeta.Int16 216 217 case reflect.Int32: 218 esize *= 4 219 ename = "int32_t" 220 etype = rmeta.Int32 221 222 case reflect.Int64: 223 esize *= 8 224 ename = "int64_t" 225 etype = rmeta.Int64 226 227 case reflect.Uint8: 228 esize *= 1 229 ename = "uint8_t" 230 etype = rmeta.Uint8 231 232 case reflect.Uint16: 233 esize *= 2 234 ename = "uint16_t" 235 etype = rmeta.Uint16 236 237 case reflect.Uint32: 238 esize *= 4 239 ename = "uint32_t" 240 etype = rmeta.Uint32 241 242 case reflect.Uint64: 243 esize *= 8 244 ename = "uint64_t" 245 etype = rmeta.Uint64 246 247 case reflect.Float32: 248 switch typ { 249 case reflect.TypeOf(root.Float16(0)): 250 esize *= 4 251 ename = "Float16_t" 252 etype = rmeta.Float16 253 default: 254 esize *= 4 255 ename = "float" 256 etype = rmeta.Float32 257 } 258 259 case reflect.Float64: 260 switch typ { 261 case reflect.TypeOf(root.Double32(0)): 262 esize *= 8 263 ename = "Double32_t" 264 etype = rmeta.Double32 265 default: 266 esize *= 8 267 ename = "double" 268 etype = rmeta.Float64 269 } 270 271 case reflect.String: 272 return &StreamerString{ 273 StreamerElement{ 274 named: *rbase.NewNamed(name, ""), 275 etype: rmeta.OffsetL + rmeta.TString, 276 esize: esize * sizeOfTString, 277 arrlen: arrlen, 278 arrdim: arrdim, 279 maxidx: maxidx, 280 offset: offset, 281 ename: "TString", 282 }, 283 } 284 case reflect.Struct: 285 if isTObject(typ) || isTObject(reflect.PointerTo(typ)) { 286 return &StreamerObject{ 287 StreamerElement{ 288 named: *rbase.NewNamed(name, ""), 289 etype: rmeta.OffsetL + rmeta.Object, 290 esize: esize * bld.sizeOf(typ), 291 arrlen: arrlen, 292 arrdim: arrdim, 293 maxidx: maxidx, 294 offset: offset, 295 ename: typenameOf(typ), 296 }, 297 } 298 } 299 return &StreamerObjectAny{ 300 StreamerElement{ 301 named: *rbase.NewNamed(name, ""), 302 etype: rmeta.OffsetL + rmeta.Any, 303 esize: esize * bld.sizeOf(typ), 304 arrlen: arrlen, 305 arrdim: arrdim, 306 maxidx: maxidx, 307 offset: offset, 308 ename: typenameOf(typ), 309 }, 310 } 311 default: 312 panic(fmt.Errorf("rdict: invalid array element type %v", typ)) 313 } 314 315 return &StreamerBasicType{ 316 StreamerElement{ 317 named: *rbase.NewNamed(name, ""), 318 etype: rmeta.OffsetL + etype, 319 esize: esize, 320 offset: offset, 321 arrlen: arrlen, 322 arrdim: arrdim, 323 maxidx: maxidx, 324 ename: ename, 325 }, 326 } 327 } 328 329 func (bld *streamerBuilder) genVarLenArrayOf(typ reflect.Type, class, count, name string, offset int32) rbytes.StreamerElement { 330 var ( 331 esize = 0 332 ename = "" 333 etype rmeta.Enum 334 ) 335 switch typ.Kind() { 336 case reflect.Bool: 337 esize = 1 338 ename = "bool" 339 etype = rmeta.Bool 340 case reflect.Int8: 341 esize = 1 342 ename = "int8_t" 343 etype = rmeta.Int8 344 case reflect.Int16: 345 esize = 2 346 ename = "int16_t" 347 etype = rmeta.Int16 348 case reflect.Int32: 349 esize = 4 350 ename = "int32_t" 351 etype = rmeta.Int32 352 case reflect.Int64: 353 esize = 8 354 ename = "int64_t" 355 etype = rmeta.Int64 356 case reflect.Uint8: 357 esize = 1 358 ename = "uint8_t" 359 etype = rmeta.Uint8 360 case reflect.Uint16: 361 esize = 2 362 ename = "uint16_t" 363 etype = rmeta.Uint16 364 case reflect.Uint32: 365 esize = 4 366 ename = "uint32_t" 367 etype = rmeta.Uint32 368 case reflect.Uint64: 369 esize = 8 370 ename = "uint64_t" 371 etype = rmeta.Uint64 372 case reflect.Float32: 373 esize = 4 374 switch typ { 375 case reflect.TypeOf(root.Float16(0)): 376 ename = "Float16_t" 377 etype = rmeta.Float16 378 default: 379 ename = "float" 380 etype = rmeta.Float32 381 } 382 case reflect.Float64: 383 esize = 8 384 switch typ { 385 case reflect.TypeOf(root.Double32(0)): 386 ename = "Double32_t" 387 etype = rmeta.Double32 388 default: 389 ename = "double" 390 etype = rmeta.Float64 391 } 392 case reflect.String: 393 return NewStreamerLoop( 394 StreamerElement{ 395 named: *rbase.NewNamed(name, "["+count+"]"), 396 esize: 4, 397 offset: offset, 398 ename: "TString*", 399 }, 400 1, count, class, 401 ) 402 case reflect.Struct: 403 ename = typenameOf(typ) 404 return NewStreamerLoop( 405 StreamerElement{ 406 named: *rbase.NewNamed(name, "["+count+"]"), 407 esize: diskPtrSize, 408 offset: offset, 409 ename: ename + "*", 410 }, 411 1, count, class, 412 ) 413 default: 414 panic(fmt.Errorf("rdict: invalid c-var-len-array type %v", typ)) 415 } 416 417 return NewStreamerBasicPointer( 418 StreamerElement{ 419 named: *rbase.NewNamed(name, "["+count+"]"), 420 etype: rmeta.OffsetP + etype, 421 esize: int32(esize), 422 offset: offset, 423 ename: ename + "*", 424 }, 1, count, class, 425 ) 426 } 427 428 func (bld *streamerBuilder) genField(typ reflect.Type, field reflect.StructField) rbytes.StreamerElement { 429 430 offset := offsetOf(field) 431 432 switch field.Type.Kind() { 433 case reflect.Bool: 434 return &StreamerBasicType{ 435 StreamerElement{ 436 named: *rbase.NewNamed(nameOf(field), ""), 437 etype: rmeta.GoType2ROOTEnum[field.Type], 438 esize: 1, 439 offset: offset, 440 ename: "bool", 441 }, 442 } 443 case reflect.Int8: 444 return &StreamerBasicType{ 445 StreamerElement{ 446 named: *rbase.NewNamed(nameOf(field), ""), 447 etype: rmeta.GoType2ROOTEnum[field.Type], 448 esize: 1, 449 offset: offset, 450 ename: "int8_t", 451 }, 452 } 453 case reflect.Int16: 454 return &StreamerBasicType{ 455 StreamerElement{ 456 named: *rbase.NewNamed(nameOf(field), ""), 457 etype: rmeta.GoType2ROOTEnum[field.Type], 458 esize: 2, 459 offset: offset, 460 ename: "int16_t", 461 }, 462 } 463 case reflect.Int32: 464 return &StreamerBasicType{ 465 StreamerElement{ 466 named: *rbase.NewNamed(nameOf(field), ""), 467 etype: rmeta.GoType2ROOTEnum[field.Type], 468 esize: 4, 469 offset: offset, 470 ename: "int32_t", 471 }, 472 } 473 case reflect.Int64: 474 return &StreamerBasicType{ 475 StreamerElement{ 476 named: *rbase.NewNamed(nameOf(field), ""), 477 etype: rmeta.GoType2ROOTEnum[field.Type], 478 esize: 8, 479 offset: offset, 480 ename: "int64_t", 481 }, 482 } 483 case reflect.Uint8: 484 return &StreamerBasicType{ 485 StreamerElement{ 486 named: *rbase.NewNamed(nameOf(field), ""), 487 etype: rmeta.GoType2ROOTEnum[field.Type], 488 esize: 1, 489 offset: offset, 490 ename: "uint8_t", 491 }, 492 } 493 case reflect.Uint16: 494 return &StreamerBasicType{ 495 StreamerElement{ 496 named: *rbase.NewNamed(nameOf(field), ""), 497 etype: rmeta.GoType2ROOTEnum[field.Type], 498 esize: 2, 499 offset: offset, 500 ename: "uint16_t", 501 }, 502 } 503 case reflect.Uint32: 504 return &StreamerBasicType{ 505 StreamerElement{ 506 named: *rbase.NewNamed(nameOf(field), ""), 507 etype: rmeta.GoType2ROOTEnum[field.Type], 508 esize: 4, 509 offset: offset, 510 ename: "uint32_t", 511 }, 512 } 513 case reflect.Uint64: 514 return &StreamerBasicType{ 515 StreamerElement{ 516 named: *rbase.NewNamed(nameOf(field), ""), 517 etype: rmeta.GoType2ROOTEnum[field.Type], 518 esize: 8, 519 offset: offset, 520 ename: "uint64_t", 521 }, 522 } 523 case reflect.Float32: 524 switch field.Type { 525 case reflect.TypeOf(root.Float16(0)): 526 return &StreamerBasicType{ 527 StreamerElement{ 528 named: *rbase.NewNamed(nameOf(field), ""), 529 etype: rmeta.Float16, 530 esize: 4, 531 offset: offset, 532 ename: "Float16_t", 533 }, 534 } 535 default: 536 return &StreamerBasicType{ 537 StreamerElement{ 538 named: *rbase.NewNamed(nameOf(field), ""), 539 etype: rmeta.GoType2ROOTEnum[field.Type], 540 esize: 4, 541 offset: offset, 542 ename: "float", 543 }, 544 } 545 } 546 case reflect.Float64: 547 switch field.Type { 548 case reflect.TypeOf(root.Double32(0)): 549 return &StreamerBasicType{ 550 StreamerElement{ 551 named: *rbase.NewNamed(nameOf(field), ""), 552 etype: rmeta.Double32, 553 esize: 8, 554 offset: offset, 555 ename: "Double32_t", 556 }, 557 } 558 default: 559 return &StreamerBasicType{ 560 StreamerElement{ 561 named: *rbase.NewNamed(nameOf(field), ""), 562 etype: rmeta.GoType2ROOTEnum[field.Type], 563 esize: 8, 564 offset: offset, 565 ename: "double", 566 }, 567 } 568 } 569 case reflect.String: 570 return &StreamerSTLstring{ 571 StreamerSTL: StreamerSTL{ 572 StreamerElement: StreamerElement{ 573 named: *rbase.NewNamed(nameOf(field), ""), 574 etype: rmeta.Streamer, 575 esize: sizeOfStdString, 576 offset: offset, 577 ename: "string", 578 }, 579 }, 580 } 581 case reflect.Struct: 582 return &StreamerObjectAny{ 583 StreamerElement{ 584 named: *rbase.NewNamed(nameOf(field), ""), 585 etype: rmeta.Any, 586 esize: bld.sizeOf(field.Type), 587 offset: offset, 588 ename: typenameOf(field.Type), 589 }, 590 } 591 592 case reflect.Array: 593 var ( 594 et = field.Type.Elem() 595 n = field.Type.Len() 596 name = nameOf(field) 597 ) 598 return bld.genArrayOf(n, et, name, offsetOf(field)) 599 600 case reflect.Slice: 601 et := field.Type.Elem() 602 count, ok := hasCount(field) 603 if ok { 604 class := typenameOf(typ) 605 return bld.genVarLenArrayOf(et, class, count, nameOf(field), offsetOf(field)) 606 } 607 return bld.genStdVectorOf(et, nameOf(field), offsetOf(field)) 608 609 case reflect.Ptr: 610 et := field.Type.Elem() 611 return bld.genPtr(et, nameOf(field), offsetOf(field)) 612 613 default: 614 panic(fmt.Errorf( 615 "rdict: invalid struct field (name=%v, type=%v, kind=%v)", 616 field.Name, field.Type, field.Type.Kind(), 617 )) 618 } 619 } 620 621 type streamerStoreImpl struct { 622 ctx rbytes.StreamerInfoContext 623 db map[string]rbytes.StreamerInfo 624 } 625 626 func newStreamerStore(ctx rbytes.StreamerInfoContext) streamerStore { 627 if ctx, ok := ctx.(streamerStore); ok { 628 return ctx 629 } 630 631 return &streamerStoreImpl{ 632 ctx: ctx, 633 db: make(map[string]rbytes.StreamerInfo), 634 } 635 } 636 637 // StreamerInfo returns the named StreamerInfo. 638 // If version is negative, the latest version should be returned. 639 func (store *streamerStoreImpl) StreamerInfo(name string, version int) (rbytes.StreamerInfo, error) { 640 return store.ctx.StreamerInfo(name, version) 641 } 642 643 func (store *streamerStoreImpl) addStreamer(si rbytes.StreamerInfo) { 644 store.db[si.Name()] = si 645 } 646 647 func nameOf(field reflect.StructField) string { 648 tag, ok := field.Tag.Lookup("groot") 649 if ok { 650 i := strings.Index(tag, "[") 651 if i < 0 { 652 return tag 653 } 654 return tag[:i] 655 } 656 return field.Name 657 } 658 659 func hasCount(field reflect.StructField) (string, bool) { 660 tag, ok := field.Tag.Lookup("groot") 661 if !ok || !strings.Contains(tag, "[") { 662 return "", false 663 } 664 var ( 665 count = new(strings.Builder) 666 brack bool 667 ) 668 for _, v := range tag { 669 switch v { 670 case '[': 671 brack = true 672 case ']': 673 name := strings.TrimSpace(count.String()) 674 if !isIdent(name) { 675 return "", false 676 } 677 return name, true 678 default: 679 if brack { 680 _, _ = count.WriteString(string(v)) 681 } 682 } 683 } 684 return "", false 685 } 686 687 func isIdent(name string) bool { 688 if len(name) == 0 { 689 return false 690 } 691 692 ok := func(c rune) bool { 693 return 'A' <= c && c <= 'Z' || 694 'a' <= c && c <= 'z' || 695 '0' <= c && c <= '9' || 696 c == '_' 697 } 698 699 for i, c := range name { 700 if i == 0 && ('0' <= c && c <= '9') { 701 return false 702 } 703 if !ok(c) { 704 return false 705 } 706 } 707 return true 708 } 709 710 func offsetOf(field reflect.StructField) int32 { 711 // return int32(field.Offset) 712 // FIXME(sbinet): it seems ROOT expects 0 here... 713 return 0 714 } 715 716 func (bld *streamerBuilder) sizeOf(typ reflect.Type) int32 { 717 // FIXME(sbinet): compute ROOT-compatible size. 718 if ptr := reflect.PointerTo(typ); isTObject(ptr) || isTObject(typ) { 719 name := typenameOf(typ) 720 switch name { 721 case "TObjString": 722 return sizeOfTObjString 723 } 724 } 725 return int32(typ.Size()) 726 } 727 728 func isTObject(typ reflect.Type) bool { 729 return typ.Implements(rootObjectIface) 730 } 731 732 func typenameOf(typ reflect.Type) string { 733 if isTObject(typ) { 734 switch typ.Kind() { 735 case reflect.Ptr: 736 name := reflect.New(typ.Elem()).Interface().(root.Object).Class() 737 return name + "*" 738 default: 739 name := reflect.New(typ).Elem().Interface().(root.Object).Class() 740 return name 741 } 742 } 743 if ptr := reflect.PointerTo(typ); isTObject(ptr) { 744 name := reflect.New(typ).Interface().(root.Object).Class() 745 return name 746 } 747 748 switch typ.Kind() { 749 case reflect.Slice: 750 ename := typenameOf(typ.Elem()) 751 if strings.HasSuffix(ename, ">") { 752 ename += " " 753 } 754 return "vector<" + ename + ">" 755 case reflect.Array: 756 var ( 757 dims []int 758 et = typ 759 ) 760 for range 10 { 761 dims = append(dims, et.Len()) 762 et = et.Elem() 763 if et.Kind() != reflect.Array { 764 break 765 } 766 767 } 768 o := new(strings.Builder) 769 ename := typenameOf(et) 770 _, _ = o.WriteString(ename) 771 for _, v := range dims { 772 fmt.Fprintf(o, "[%d]", v) 773 } 774 return o.String() 775 case reflect.Bool: 776 return "bool" 777 case reflect.Int8: 778 return "int8_t" 779 case reflect.Int16: 780 return "int16_t" 781 case reflect.Int32: 782 return "int32_t" 783 case reflect.Int64: 784 return "int64_t" 785 case reflect.Uint8: 786 return "uint8_t" 787 case reflect.Uint16: 788 return "uint16_t" 789 case reflect.Uint32: 790 return "uint32_t" 791 case reflect.Uint64: 792 return "uint64_t" 793 case reflect.Float32: 794 switch typ { 795 case reflect.TypeOf(root.Float16(0)): 796 return "Float16_t" 797 default: 798 return "float" 799 } 800 case reflect.Float64: 801 switch typ { 802 case reflect.TypeOf(root.Double32(0)): 803 return "Double32_t" 804 default: 805 return "double" 806 } 807 case reflect.String: 808 return "string" 809 case reflect.Ptr: 810 return typenameOf(typ.Elem()) + "*" 811 812 default: 813 name := typ.Name() 814 if name == "" { 815 panic(fmt.Errorf("rdict: invalid reflect type %v", typ)) 816 } 817 return name 818 } 819 } 820 821 const ( 822 diskPtrSize = 8 823 sizeOfTObjString = 40 824 sizeOfTString = 3 * diskPtrSize 825 sizeOfStdString = 4 * diskPtrSize 826 ) 827 828 var ( 829 rootObjectIface = reflect.TypeOf((*root.Object)(nil)).Elem() 830 ) 831 832 var ( 833 _ streamerStore = (*streamerStoreImpl)(nil) 834 _ rbytes.StreamerInfoContext = (*streamerStoreImpl)(nil) 835 )