go-hep.org/x/hep@v0.38.1/groot/rdict/gen_type.go (about) 1 // Copyright ©2019 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 "bytes" 9 "fmt" 10 "go/format" 11 "io" 12 "log" 13 "path/filepath" 14 "sort" 15 "strings" 16 17 "go-hep.org/x/hep/groot/rbytes" 18 "go-hep.org/x/hep/groot/rmeta" 19 "go-hep.org/x/hep/groot/rtypes" 20 ) 21 22 type genGoType struct { 23 pkg string 24 buf *bytes.Buffer 25 ctx rbytes.StreamerInfoContext 26 27 verbose bool 28 29 // set of imported packages. 30 // usually: "go-hep.org/x/hep/groot/rbase", ".../rcont 31 imps map[string]int 32 33 rdict string // whether to prepend 'rdict.' 34 } 35 36 // GenCxxStreamerInfo generates the textual representation of the provided streamer info. 37 func GenCxxStreamerInfo(w io.Writer, si rbytes.StreamerInfo, verbose bool) error { 38 g, err := NewGenGoType("go-hep.org/x/hep/groot/rdict", nil, verbose) 39 if err != nil { 40 return fmt.Errorf("rdict: could not create streamer info generator: %w", err) 41 } 42 g.rdict = "" 43 44 g.printf("%sNewCxxStreamerInfo(%q, %d, 0x%x, []rbytes.StreamerElement{\n", g.rdict, si.Name(), si.ClassVersion(), si.CheckSum()) 45 for i, se := range si.Elements() { 46 g.genStreamerType(si, i, se) 47 } 48 g.printf("})") 49 50 src, err := format.Source(g.buf.Bytes()) 51 if err != nil { 52 return fmt.Errorf("rdict: could not format streamer code for %q: %w", si.Name(), err) 53 } 54 55 _, err = w.Write(src) 56 if err != nil { 57 return fmt.Errorf("rdict: could not write streamer info generated data: %w", err) 58 } 59 60 return err 61 } 62 63 // NewGenGoType generates code for Go types from a ROOT StreamerInfo. 64 func NewGenGoType(pkg string, sictx rbytes.StreamerInfoContext, verbose bool) (*genGoType, error) { 65 return &genGoType{ 66 pkg: pkg, 67 buf: new(bytes.Buffer), 68 ctx: sictx, 69 verbose: verbose, 70 imps: map[string]int{ 71 "reflect": 1, 72 "go-hep.org/x/hep/groot/rbytes": 1, 73 "go-hep.org/x/hep/groot/root": 1, 74 "go-hep.org/x/hep/groot/rtypes": 1, 75 }, 76 rdict: "rdict.", 77 }, nil 78 } 79 80 // Generate implements rdict.Generator 81 func (g *genGoType) Generate(name string) error { 82 if g.verbose { 83 log.Printf("generating type for %q...", name) 84 } 85 si, err := g.ctx.StreamerInfo(name, -1) 86 if err != nil { 87 return fmt.Errorf("rdict: could not find streamer for %q: %w", name, err) 88 } 89 90 return g.genType(si) 91 } 92 93 func (g *genGoType) genType(si rbytes.StreamerInfo) error { 94 name := si.Name() 95 if title := si.Title(); title != "" { 96 g.printf("// %s has been automatically generated.\n", name) 97 g.printf("// %s\n", title) 98 } 99 goname := name 100 goname = strings.Replace(goname, "::", "__", -1) // handle namespaces 101 goname = strings.Replace(goname, "<", "_", -1) // handle C++ templates 102 goname = strings.Replace(goname, ">", "_", -1) // handle C++ templates 103 goname = strings.Replace(goname, ",", "_", -1) // handle C++ templates 104 g.printf("type %s struct{\n", goname) 105 for i, se := range si.Elements() { 106 g.genField(si, i, se) 107 } 108 g.printf("}\n\n") 109 g.printf("func (*%s) Class() string {\nreturn %q\n}\n\n", goname, name) 110 g.printf("func (*%s) RVersion() int16 {\nreturn %d\n}\n", goname, si.ClassVersion()) 111 g.printf("\n") 112 g.genMarshal(si) 113 g.genUnmarshal(si) 114 115 g.printf(`func init() { 116 f := func() reflect.Value { 117 var o %s 118 return reflect.ValueOf(&o) 119 } 120 rtypes.Factory.Add(%q, f) 121 } 122 123 `, 124 goname, name, 125 ) 126 127 g.genStreamerInfo(si) 128 129 ifaces := []string{"root.Object", "rbytes.RVersioner", "rbytes.Marshaler", "rbytes.Unmarshaler"} 130 g.printf("var (\n") 131 for _, n := range ifaces { 132 g.printf("\t_ %s = (*%s)(nil)\n", n, goname) 133 } 134 g.printf(")\n\n") 135 136 return nil 137 } 138 139 func (g *genGoType) genField(si rbytes.StreamerInfo, i int, se rbytes.StreamerElement) { 140 const ( 141 docFmt = "\t%s\t%s\t%s\t%s\n" 142 ) 143 doc := g.doc(se.Title()) 144 if doc != "" { 145 doc = "// " + doc 146 } 147 switch se := se.(type) { 148 case *StreamerBase: 149 g.printf(docFmt, fmt.Sprintf("base%d", i), g.typename(se), g.stag(i, se), "// base class") 150 151 case *StreamerBasicPointer: 152 g.printf(docFmt, se.Name(), g.typename(se), g.stag(i, se), doc) 153 154 case *StreamerBasicType: 155 tname := g.typename(se) 156 switch se.ArrayLen() { 157 case 0: 158 default: 159 tname = fmt.Sprintf("[%d]%s", se.ArrayLen(), tname) 160 } 161 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 162 163 case *StreamerLoop: 164 tname := g.typename(se) 165 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 166 167 case *StreamerObject: 168 tname := g.typename(se) 169 switch se.ArrayLen() { 170 case 0: 171 default: 172 tname = fmt.Sprintf("[%d]%s", se.ArrayLen(), tname) 173 } 174 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 175 176 case *StreamerObjectAny: 177 tname := g.typename(se) 178 switch se.ArrayLen() { 179 case 0: 180 default: 181 tname = fmt.Sprintf("[%d]%s", se.ArrayLen(), tname) 182 } 183 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 184 185 case *StreamerObjectAnyPointer: 186 tname := g.typename(se) 187 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 188 189 case *StreamerObjectPointer: 190 tname := g.typename(se) 191 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 192 193 case *StreamerString, *StreamerSTLstring: 194 g.printf(docFmt, se.Name(), "string", g.stag(i, se), doc) 195 196 case *StreamerSTL: 197 switch se.STLType() { 198 case rmeta.STLvector, rmeta.STLmap, rmeta.STLend: 199 tname := g.typename(se) 200 g.printf(docFmt, se.Name(), tname, g.stag(i, se), doc) 201 default: 202 panic(fmt.Errorf("STL-type not implemented %#v", se)) 203 } 204 default: 205 g.printf("\t%s\t%s // %T -- %s\n", se.Name(), g.typename(se), se, doc) 206 } 207 } 208 209 func (g *genGoType) stag(i int, se rbytes.StreamerElement) string { 210 switch se := se.(type) { 211 case *StreamerBase: 212 return fmt.Sprintf("`groot:\"BASE-%s\"`", se.Name()) 213 } 214 meta, _ := g.rcomment(se.Title()) 215 if meta != "" { 216 return fmt.Sprintf("`groot:\"%s,meta=%s\"`", se.Name(), meta) 217 } 218 return fmt.Sprintf("`groot:%q`", se.Name()) 219 } 220 221 func (g *genGoType) doc(title string) string { 222 _, doc := g.rcomment(title) 223 return doc 224 } 225 226 func (g *genGoType) rcomment(s string) (meta, comment string) { 227 comment = s 228 for strings.HasPrefix(comment, "[") { 229 beg := strings.Index(comment, "[") 230 end := strings.Index(comment, "]") 231 meta += comment[beg : end+1] 232 comment = comment[end+1:] 233 } 234 if strings.HasPrefix(comment, " ") { 235 comment = strings.TrimSpace(comment) 236 } 237 return meta, comment 238 } 239 240 func (g *genGoType) typename(se rbytes.StreamerElement) string { 241 tname := se.TypeName() 242 switch se := se.(type) { 243 case *StreamerBase: 244 return g.cxx2go(se.Name(), 0) 245 246 case *StreamerBasicPointer: 247 tname = tname[:len(tname)-1] // drop last '*' 248 t, ok := rmeta.CxxBuiltins[tname] 249 if !ok { 250 panic(fmt.Errorf("gen-type: unknown C++ builtin %q", tname)) 251 } 252 switch { 253 case strings.HasPrefix(se.Title(), "["): 254 return g.cxx2go(t.Name(), qualSlice) 255 default: 256 return g.cxx2go(t.Name(), qualStar) 257 } 258 259 case *StreamerBasicType: 260 switch se.Type() { 261 case rmeta.Float16: 262 g.imps["go-hep.org/x/hep/groot/root"] = 1 263 return "root.Float16" 264 case rmeta.Double32: 265 g.imps["go-hep.org/x/hep/groot/root"] = 1 266 return "root.Double32" 267 } 268 t, ok := rmeta.CxxBuiltins[tname] 269 if !ok { 270 enum := se.Type().String() 271 switch se.Type() { 272 case rmeta.Uint8: 273 enum = "uint8_t" 274 case rmeta.Uint16: 275 enum = "uint16_t" 276 case rmeta.Uint32: 277 enum = "uint32_t" 278 case rmeta.Uint64: 279 enum = "uint64_t" 280 case rmeta.Int8: 281 enum = "int8_t" 282 case rmeta.Int16: 283 enum = "int16_t" 284 case rmeta.Int32: 285 enum = "int32_t" 286 case rmeta.Int64: 287 enum = "int64_t" 288 } 289 t, ok = rmeta.CxxBuiltins[enum] 290 } 291 if !ok { 292 panic(fmt.Errorf("gen-type: unknown C++ builtin %q", tname)) 293 } 294 return t.Name() 295 296 case *StreamerLoop: 297 tname = strings.TrimSuffix(tname, "*") 298 return "[]" + g.cxx2go(tname, qualNone) 299 300 case *StreamerObject: 301 return g.cxx2go(tname, qualNone) 302 303 case *StreamerObjectAny: 304 return g.cxx2go(tname, qualNone) 305 306 case *StreamerObjectAnyPointer: 307 tname = tname[:len(tname)-1] // drop last '*' 308 return g.cxx2go(tname, qualStar) 309 310 case *StreamerObjectPointer: 311 tname = tname[:len(tname)-1] // drop last '*' 312 return g.cxx2go(tname, qualStar) 313 314 case *StreamerString, *StreamerSTLstring: 315 return "string" 316 317 case *StreamerSTL: 318 switch se.STLType() { 319 case rmeta.STLvector, rmeta.STLend: 320 switch se.ContainedType() { 321 case rmeta.Bool: 322 return "[]bool" 323 case rmeta.Int8: 324 return "[]int8" 325 case rmeta.Int16: 326 return "[]int16" 327 case rmeta.Int32: 328 return "[]int32" 329 case rmeta.Int64, rmeta.Long64: 330 return "[]int64" 331 case rmeta.Uint8: 332 return "[]uint8" 333 case rmeta.Uint16: 334 return "[]uint16" 335 case rmeta.Uint32: 336 return "[]uint32" 337 case rmeta.Uint64, rmeta.ULong64: 338 return "[]uint64" 339 case rmeta.Float32: 340 return "[]float32" 341 case rmeta.Float64: 342 return "[]float64" 343 case rmeta.Float16: 344 return "[]root.Float16" 345 case rmeta.Double32: 346 return "[]root.Double32" 347 case rmeta.Object: 348 etn := se.ElemTypeName() 349 switch etn[0] { 350 case "string": 351 return "[]string" 352 default: 353 etname := g.cxx2go(etn[0], qualNone) 354 return "[]" + etname 355 } 356 default: 357 panic(fmt.Errorf("invalid stl-vector element type: %v -- %#v", se.ContainedType(), se)) 358 } 359 case rmeta.STLmap: 360 types := se.ElemTypeName() 361 k := g.cxx2go(types[0], qualNone) 362 v := g.cxx2go(types[1], qualNone) 363 return "map[" + k + "]" + v 364 default: 365 panic(fmt.Errorf("STL-type not implemented %#v", se)) 366 } 367 } 368 return tname 369 } 370 371 type qualKind uint8 372 373 func (q qualKind) String() string { 374 switch q { 375 case qualNone: 376 return "" 377 case qualStar: 378 return "*" 379 case qualSlice: 380 return "[]" 381 } 382 panic(fmt.Errorf("invalid qual-kind value %d", int(q))) 383 } 384 385 const ( 386 qualNone qualKind = 0 387 qualStar qualKind = 1 388 qualSlice qualKind = 2 389 ) 390 391 func (g *genGoType) cxx2go(name string, qual qualKind) string { 392 prefix := qual.String() 393 if rtypes.Factory.HasKey(name) { 394 t := rtypes.Factory.Get(name)().Type().Elem() 395 pkg := t.PkgPath() 396 g.imps[pkg]++ 397 switch t.Name() { 398 case "tgraph": 399 if qual == qualStar { 400 prefix = "" 401 } 402 return prefix + "rhist.Graph" 403 case "tgrapherrs", "tgraphasymerrs": 404 if qual == qualStar { 405 prefix = "" 406 } 407 return prefix + "rhist.GraphErrors" 408 } 409 410 return prefix + filepath.Base(pkg) + "." + t.Name() 411 } 412 var f func(name string) string 413 f = func(name string) string { 414 switch { 415 case strings.HasSuffix(name, "*"): 416 return "*" + f(name[:len(name)-1]) 417 } 418 return name 419 } 420 name = f(name) 421 name = strings.Replace(name, "::", "__", -1) // handle namespaces 422 name = strings.Replace(name, "<", "_", -1) // handle C++ templates 423 name = strings.Replace(name, ">", "_", -1) // handle C++ templates 424 name = strings.Replace(name, ",", "_", -1) // handle C++ templates 425 return prefix + name 426 } 427 428 func (g *genGoType) genMarshal(si rbytes.StreamerInfo) { 429 g.printf(`// MarshalROOT implements rbytes.Marshaler 430 func (o *%[1]s) MarshalROOT(w *rbytes.WBuffer) (int, error) { 431 if w.Err() != nil { 432 return 0, w.Err() 433 } 434 435 hdr := w.WriteHeader(o.Class(), o.RVersion()) 436 437 `, 438 g.cxx2go(si.Name(), qualNone), 439 ) 440 441 for i, se := range si.Elements() { 442 g.genMarshalField(si, i, se) 443 } 444 445 g.printf("\n\treturn w.SetHeader(hdr)\n}\n\n") 446 } 447 448 func (g *genGoType) genMarshalField(si rbytes.StreamerInfo, i int, se rbytes.StreamerElement) { 449 switch se := se.(type) { 450 case *StreamerBase: 451 g.printf("w.WriteObject(&o.%s)\n", fmt.Sprintf("base%d", i)) 452 453 case *StreamerBasicPointer: 454 title := se.Title() 455 switch { 456 case strings.HasPrefix(title, "["): 457 n := title[strings.Index(title, "[")+1 : strings.Index(title, "]")] 458 g.printf("w.WriteI8(1) // is-array\n") 459 wfunc := "" 460 switch se.Type() { 461 case rmeta.OffsetP + rmeta.Bool: 462 wfunc = "WriteArrayBool" 463 case rmeta.OffsetP + rmeta.Int8: 464 wfunc = "WriteArrayI8" 465 case rmeta.OffsetP + rmeta.Int16: 466 wfunc = "WriteArrayI16" 467 case rmeta.OffsetP + rmeta.Int32: 468 wfunc = "WriteArrayI32" 469 case rmeta.OffsetP + rmeta.Int64, rmeta.OffsetP + rmeta.Long64: 470 wfunc = "WriteArrayI64" 471 case rmeta.OffsetP + rmeta.Uint8: 472 wfunc = "WriteArrayU8" 473 case rmeta.OffsetP + rmeta.Uint16: 474 wfunc = "WriteArrayU16" 475 case rmeta.OffsetP + rmeta.Uint32: 476 wfunc = "WriteArrayU32" 477 case rmeta.OffsetP + rmeta.Uint64, rmeta.OffsetP + rmeta.ULong64: 478 wfunc = "WriteArrayU64" 479 case rmeta.OffsetP + rmeta.Float32: 480 wfunc = "WriteArrayF32" 481 case rmeta.OffsetP + rmeta.Float64: 482 wfunc = "WriteArrayF64" 483 default: 484 panic(fmt.Errorf("invalid element type: %v", se.Type())) 485 } 486 g.printf("w.%s(o.%s[:o.%s])\n", wfunc, se.Name(), n) 487 default: 488 panic("not implemented") 489 } 490 491 case *StreamerBasicType: 492 switch se.ArrayLen() { 493 case 0: 494 switch se.Type() { 495 case rmeta.Bool: 496 g.printf("w.WriteBool(o.%s)\n", se.Name()) 497 498 case rmeta.Counter: 499 switch se.Size() { 500 case 4: 501 g.printf("w.WriteI32(int32(o.%s))\n", se.Name()) 502 case 8: 503 g.printf("w.WriteI64(int64(o.%s))\n", se.Name()) 504 default: 505 panic(fmt.Errorf("invalid counter size %d for %s.%s", se.Size(), si.Name(), se.Name())) 506 } 507 508 case rmeta.Bits: 509 g.printf("w.WriteI32(int32(o.%s))\n", se.Name()) 510 511 case rmeta.Int8: 512 g.printf("w.WriteI8(o.%s)\n", se.Name()) 513 case rmeta.Int16: 514 g.printf("w.WriteI16(o.%s)\n", se.Name()) 515 case rmeta.Int32: 516 g.printf("w.WriteI32(o.%s)\n", se.Name()) 517 case rmeta.Int64, rmeta.Long64: 518 g.printf("w.WriteI64(o.%s)\n", se.Name()) 519 520 case rmeta.Uint8: 521 g.printf("w.WriteU8(o.%s)\n", se.Name()) 522 case rmeta.Uint16: 523 g.printf("w.WriteU16(o.%s)\n", se.Name()) 524 case rmeta.Uint32: 525 g.printf("w.WriteU32(o.%s)\n", se.Name()) 526 case rmeta.Uint64, rmeta.ULong64: 527 g.printf("w.WriteU64(o.%s)\n", se.Name()) 528 529 case rmeta.Float32: 530 g.printf("w.WriteF32(o.%s)\n", se.Name()) 531 case rmeta.Float64: 532 g.printf("w.WriteF64(o.%s)\n", se.Name()) 533 534 case rmeta.Float16: 535 g.printf("w.WriteF32(float32(o.%s)) // FIXME(sbinet)\n", se.Name()) // FIXME(sbinet): handle compression 536 case rmeta.Double32: 537 g.printf("w.WriteF32(float32(o.%s)) // FIXME(sbinet)\n", se.Name()) // FIXME(sbinet): handle compression 538 539 default: 540 panic(fmt.Errorf("invalid basic type %v (%d) for %s.%s", se.Type(), se.Type(), si.Name(), se.Name())) 541 } 542 default: 543 n := int(se.ArrayLen()) 544 wfunc := "" 545 switch se.Type() { 546 case rmeta.OffsetL + rmeta.Bool: 547 wfunc = "WriteArrayBool" 548 case rmeta.OffsetL + rmeta.Int8: 549 wfunc = "WriteArrayI8" 550 case rmeta.OffsetL + rmeta.Int16: 551 wfunc = "WriteArrayI16" 552 case rmeta.OffsetL + rmeta.Int32: 553 wfunc = "WriteArrayI32" 554 case rmeta.OffsetL + rmeta.Int64, rmeta.OffsetL + rmeta.Long64: 555 wfunc = "WriteArrayI64" 556 case rmeta.OffsetL + rmeta.Uint8: 557 wfunc = "WriteArrayU8" 558 case rmeta.OffsetL + rmeta.Uint16: 559 wfunc = "WriteArrayU16" 560 case rmeta.OffsetL + rmeta.Uint32: 561 wfunc = "WriteArrayU32" 562 case rmeta.OffsetL + rmeta.Uint64, rmeta.OffsetL + rmeta.ULong64: 563 wfunc = "WriteArrayU64" 564 case rmeta.OffsetL + rmeta.Float32: 565 wfunc = "WriteArrayF32" 566 case rmeta.OffsetL + rmeta.Float64: 567 wfunc = "WriteArrayF64" 568 default: 569 panic(fmt.Errorf("invalid array element type: %v", se.Type())) 570 } 571 g.printf("w.%s(o.%s[:%d])\n", wfunc, se.Name(), n) 572 } 573 574 case *StreamerLoop: 575 // FIXME(sbinet): implement. handle mbr-wise 576 g.printf("panic(\"o.%s: not implemented (TStreamerLoop)\")\n", se.Name()) 577 578 case *StreamerObject: 579 // FIXME(sbinet): check semantics 580 switch se.ArrayLen() { 581 case 0: 582 g.printf("w.WriteObject(&o.%s) // obj\n", se.Name()) 583 default: 584 g.printf("for i := range o.%s {\n", se.Name()) 585 g.printf("w.WriteObject(&o.%s[i]) // obj\n", se.Name()) 586 g.printf("}\n") 587 } 588 589 case *StreamerObjectAny: 590 // FIXME(sbinet): check semantics 591 switch se.ArrayLen() { 592 case 0: 593 g.printf("w.WriteObject(&o.%s) // obj-any\n", se.Name()) 594 default: 595 g.printf("for i := range o.%s {\n", se.Name()) 596 g.printf("w.WriteObject(&o.%s[i]) // obj-any\n", se.Name()) 597 g.printf("}\n") 598 } 599 600 case *StreamerObjectAnyPointer: 601 // FIXME(sbinet): check semantics 602 g.printf("w.WriteObjectAny(o.%s) // obj-any-ptr\n", se.Name()) 603 604 case *StreamerObjectPointer: 605 // FIXME(sbinet): check semantics 606 g.printf("w.WriteObjectAny(o.%s) // obj-ptr\n", se.Name()) 607 608 case *StreamerString: 609 g.printf("w.WriteString(o.%s)\n", se.Name()) 610 611 case *StreamerSTLstring: 612 g.printf("w.WriteStdString(o.%s)\n", se.Name()) 613 614 case *StreamerSTL: 615 switch se.STLType() { 616 case rmeta.STLvector, rmeta.STLend: 617 wfunc := "" 618 switch se.ContainedType() { 619 case rmeta.Bool: 620 wfunc = "WriteStdVectorBool" 621 case rmeta.Int8: 622 wfunc = "WriteStdVectorI8" 623 case rmeta.Int16: 624 wfunc = "WriteStdVectorI16" 625 case rmeta.Int32: 626 wfunc = "WriteStdVectorI32" 627 case rmeta.Int64, rmeta.Long64: 628 wfunc = "WriteStdVectorI64" 629 case rmeta.Uint8: 630 wfunc = "WriteStdVectorU8" 631 case rmeta.Uint16: 632 wfunc = "WriteStdVectorU16" 633 case rmeta.Uint32: 634 wfunc = "WriteStdVectorU32" 635 case rmeta.Uint64, rmeta.ULong64: 636 wfunc = "WriteStdVectorU64" 637 case rmeta.Float32: 638 wfunc = "WriteStdVectorF32" 639 case rmeta.Float64: 640 wfunc = "WriteStdVectorF64" 641 case rmeta.Object: 642 etn := se.ElemTypeName() 643 switch etn[0] { 644 case "string": 645 wfunc = "WriteStdVectorStrs" 646 default: 647 panic(fmt.Errorf("invalid stl-vector element type: %v", se.ContainedType())) 648 } 649 default: 650 panic(fmt.Errorf("invalid stl-vector element type: %v", se.ContainedType())) 651 } 652 g.printf("w.%s(o.%s)\n", wfunc, se.Name()) 653 654 default: 655 panic(fmt.Errorf("STL-type not implemented %#v", se)) 656 } 657 658 default: 659 g.printf("// %s -- %T\n", se.Name(), se) 660 } 661 } 662 663 func (g *genGoType) genUnmarshal(si rbytes.StreamerInfo) { 664 g.printf(`// UnmarshalROOT implements rbytes.Unmarshaler 665 func (o *%[1]s) UnmarshalROOT(r *rbytes.RBuffer) error { 666 if r.Err() != nil { 667 return r.Err() 668 } 669 670 hdr := r.ReadHeader(o.Class(), o.RVersion()) 671 672 `, 673 g.cxx2go(si.Name(), qualNone), 674 ) 675 676 for i, se := range si.Elements() { 677 g.genUnmarshalField(si, i, se) 678 } 679 680 g.printf("\nr.CheckHeader(hdr)\nreturn r.Err()\n}\n\n") 681 } 682 683 func (g *genGoType) genUnmarshalField(si rbytes.StreamerInfo, i int, se rbytes.StreamerElement) { 684 switch se := se.(type) { 685 case *StreamerBase: 686 g.printf("r.ReadObject(&o.%s)\n", fmt.Sprintf("base%d", i)) 687 688 case *StreamerBasicPointer: 689 title := se.Title() 690 switch { 691 case strings.HasPrefix(title, "["): 692 n := title[strings.Index(title, "[")+1 : strings.Index(title, "]")] 693 g.printf("_ = r.ReadI8() // is-array\n") 694 rfunc := "" 695 rsize := "" 696 switch se.Type() { 697 case rmeta.OffsetP + rmeta.Bool: 698 rfunc = "ReadArrayBool" 699 rsize = "ResizeBool" 700 case rmeta.OffsetP + rmeta.Int8: 701 rfunc = "ReadArrayI8" 702 rsize = "ResizeI8" 703 case rmeta.OffsetP + rmeta.Int16: 704 rfunc = "ReadArrayI16" 705 rsize = "ResizeI16" 706 case rmeta.OffsetP + rmeta.Int32: 707 rfunc = "ReadArrayI32" 708 rsize = "ResizeI32" 709 case rmeta.OffsetP + rmeta.Int64, rmeta.OffsetP + rmeta.Long64: 710 rfunc = "ReadArrayI64" 711 rsize = "ResizeI64" 712 case rmeta.OffsetP + rmeta.Uint8: 713 rfunc = "ReadArrayU8" 714 rsize = "ResizeU8" 715 case rmeta.OffsetP + rmeta.Uint16: 716 rfunc = "ReadArrayU16" 717 rsize = "ResizeU16" 718 case rmeta.OffsetP + rmeta.Uint32: 719 rfunc = "ReadArrayU32" 720 rsize = "ResizeU32" 721 case rmeta.OffsetP + rmeta.Uint64, rmeta.OffsetP + rmeta.ULong64: 722 rfunc = "ReadArrayU64" 723 rsize = "ResizeU64" 724 case rmeta.OffsetP + rmeta.Float32: 725 rfunc = "ReadArrayF32" 726 rsize = "ResizeF32" 727 case rmeta.OffsetP + rmeta.Float64: 728 rfunc = "ReadArrayF64" 729 rsize = "ResizeF64" 730 default: 731 panic(fmt.Errorf("invalid element type: %v", se.Type())) 732 } 733 g.printf("o.%s = rbytes.%s(nil, int(o.%s))\n", se.Name(), rsize, n) 734 g.printf("r.%s(o.%s)\n", rfunc, se.Name()) 735 default: 736 panic("not implemented") 737 } 738 739 case *StreamerBasicType: 740 switch se.ArrayLen() { 741 case 0: 742 switch se.Type() { 743 case rmeta.Bool: 744 g.printf("o.%s = r.ReadBool()\n", se.Name()) 745 746 case rmeta.Counter: 747 switch se.Size() { 748 case 4: 749 g.printf("o.%s = r.ReadI32()\n", se.Name()) 750 case 8: 751 g.printf("o.%s = r.ReadI64()\n", se.Name()) 752 default: 753 panic(fmt.Errorf("invalid counter size %d for %s.%s", se.Size(), si.Name(), se.Name())) 754 } 755 756 case rmeta.Bits: 757 g.printf("o.%s = r.ReadI32()\n", se.Name()) 758 759 case rmeta.Int8: 760 g.printf("o.%s = r.ReadI8()\n", se.Name()) 761 case rmeta.Int16: 762 g.printf("o.%s = r.ReadI16()\n", se.Name()) 763 case rmeta.Int32: 764 g.printf("o.%s = r.ReadI32()\n", se.Name()) 765 case rmeta.Int64, rmeta.Long64: 766 g.printf("o.%s = r.ReadI64()\n", se.Name()) 767 768 case rmeta.Uint8: 769 g.printf("o.%s = r.ReadU8()\n", se.Name()) 770 case rmeta.Uint16: 771 g.printf("o.%s = r.ReadU16()\n", se.Name()) 772 case rmeta.Uint32: 773 g.printf("o.%s = r.ReadU32()\n", se.Name()) 774 case rmeta.Uint64, rmeta.ULong64: 775 g.printf("o.%s = r.ReadU64()\n", se.Name()) 776 777 case rmeta.Float32: 778 g.printf("o.%s = r.ReadF32()\n", se.Name()) 779 case rmeta.Float64: 780 g.printf("o.%s = r.ReadF64()\n", se.Name()) 781 782 case rmeta.Float16: 783 g.printf("o.%s = root.Float16(r.ReadF32()) // FIXME(sbinet)\n", se.Name()) // FIXME(sbinet): handle compression,factor 784 case rmeta.Double32: 785 g.printf("o.%s = root.Double32(r.ReadF32()) // FIXME(sbinet)\n", se.Name()) // FIXME(sbinet): handle compression,factor 786 787 default: 788 panic(fmt.Errorf("invalid basic type %v (%d) for %s.%s", se.Type(), se.Type(), si.Name(), se.Name())) 789 } 790 default: 791 rfunc := "" 792 switch se.Type() { 793 case rmeta.OffsetL + rmeta.Bool: 794 rfunc = "ReadArrayBool" 795 case rmeta.OffsetL + rmeta.Int8: 796 rfunc = "ReadArrayI8" 797 case rmeta.OffsetL + rmeta.Int16: 798 rfunc = "ReadArrayI16" 799 case rmeta.OffsetL + rmeta.Int32: 800 rfunc = "ReadArrayI32" 801 case rmeta.OffsetL + rmeta.Int64, rmeta.OffsetL + rmeta.Long64: 802 rfunc = "ReadArrayI64" 803 case rmeta.OffsetL + rmeta.Uint8: 804 rfunc = "ReadArrayU8" 805 case rmeta.OffsetL + rmeta.Uint16: 806 rfunc = "ReadArrayU16" 807 case rmeta.OffsetL + rmeta.Uint32: 808 rfunc = "ReadArrayU32" 809 case rmeta.OffsetL + rmeta.Uint64, rmeta.OffsetL + rmeta.ULong64: 810 rfunc = "ReadArrayU64" 811 case rmeta.OffsetL + rmeta.Float32: 812 rfunc = "ReadArrayF32" 813 case rmeta.OffsetL + rmeta.Float64: 814 rfunc = "ReadArrayF64" 815 default: 816 panic(fmt.Errorf("invalid array element type: %v", se.Type())) 817 } 818 g.printf("r.%s(o.%s[:])\n", rfunc, se.Name()) 819 } 820 821 case *StreamerLoop: 822 // FIXME(sbinet): implement. handle mbr-wise 823 g.printf("panic(\"o.%s: not implemented (TStreamerLoop)\")\n", se.Name()) 824 825 case *StreamerObject: 826 // FIXME(sbinet): check semantics 827 switch se.ArrayLen() { 828 case 0: 829 g.printf("r.ReadObject(&o.%s) // obj\n", se.Name()) 830 default: 831 g.printf("for i := range o.%s {\n", se.Name()) 832 g.printf("r.ReadObject(&o.%s[i]) // obj\n", se.Name()) 833 g.printf("}\n") 834 } 835 836 case *StreamerObjectAny: 837 // FIXME(sbinet): check semantics 838 switch se.ArrayLen() { 839 case 0: 840 g.printf("r.ReadObject(&o.%s) // obj-any\n", se.Name()) 841 default: 842 g.printf("for i := range o.%s {\n", se.Name()) 843 g.printf("r.ReadObject(&o.%s[i]) // obj-any\n", se.Name()) 844 g.printf("}\n") 845 } 846 847 case *StreamerObjectAnyPointer: 848 // FIXME(sbinet): check semantics 849 g.printf("{\n") 850 g.printf("o.%s = nil\n", se.Name()) 851 g.printf("if oo := r.ReadObjectAny(); oo != nil { // obj-any-ptr\n") 852 g.printf("o.%s = oo.(%s)\n", se.Name(), g.typename(se)) 853 g.printf("}\n}\n") 854 855 case *StreamerObjectPointer: 856 // FIXME(sbinet): check semantics 857 g.printf("{\n") 858 g.printf("o.%s = nil\n", se.Name()) 859 g.printf("if oo := r.ReadObjectAny(); oo != nil { // obj-ptr\n") 860 g.printf("o.%s = oo.(%s)\n", se.Name(), g.typename(se)) 861 g.printf("}\n}\n") 862 863 case *StreamerString: 864 g.printf("o.%s = r.ReadString()\n", se.Name()) 865 866 case *StreamerSTLstring: 867 g.printf("o.%s = r.ReadStdString()\n", se.Name()) 868 869 case *StreamerSTL: 870 switch se.STLType() { 871 case rmeta.STLvector, rmeta.STLend: 872 rfunc := "" 873 switch se.ContainedType() { 874 case rmeta.Bool: 875 rfunc = "ReadStdVectorBool" 876 case rmeta.Int8: 877 rfunc = "ReadStdVectorI8" 878 case rmeta.Int16: 879 rfunc = "ReadStdVectorI16" 880 case rmeta.Int32: 881 rfunc = "ReadStdVectorI32" 882 case rmeta.Int64, rmeta.Long64: 883 rfunc = "ReadStdVectorI64" 884 case rmeta.Uint8: 885 rfunc = "ReadStdVectorU8" 886 case rmeta.Uint16: 887 rfunc = "ReadStdVectorU16" 888 case rmeta.Uint32: 889 rfunc = "ReadStdVectorU32" 890 case rmeta.Uint64, rmeta.ULong64: 891 rfunc = "ReadStdVectorU64" 892 case rmeta.Float32: 893 rfunc = "ReadStdVectorF32" 894 case rmeta.Float64: 895 rfunc = "ReadStdVectorF64" 896 case rmeta.Object: 897 etn := se.ElemTypeName() 898 switch etn[0] { 899 case "string": 900 rfunc = "ReadStdVectorStrs" 901 default: 902 panic(fmt.Errorf("invalid stl-vector element type: %v", se.ContainedType())) 903 } 904 default: 905 panic(fmt.Errorf("invalid stl-vector element type: %v", se.ContainedType())) 906 } 907 g.printf("r.%s(&o.%s)\n", rfunc, se.Name()) 908 909 default: 910 panic(fmt.Errorf("STL-type not implemented %#v", se)) 911 } 912 913 default: 914 g.printf("// %s -- %T\n", se.Name(), se) 915 } 916 } 917 918 func (g *genGoType) genStreamerInfo(si rbytes.StreamerInfo) { 919 g.printf(`func init() { 920 // Streamer for %[1]s. 921 %[4]sStreamerInfos.Add(%[4]sNewCxxStreamerInfo(%[1]q, %[2]d, 0x%[3]x, []rbytes.StreamerElement{ 922 `, 923 si.Name(), si.ClassVersion(), si.CheckSum(), 924 g.rdict, 925 ) 926 927 for i, se := range si.Elements() { 928 g.genStreamerType(si, i, se) 929 } 930 931 g.printf("}))\n}\n\n") 932 } 933 934 func (g *genGoType) genStreamerType(si rbytes.StreamerInfo, i int, se rbytes.StreamerElement) { 935 maxidx := func(v [5]int32) string { 936 return fmt.Sprintf("[5]int32{%d, %d, %d, %d, %d}", v[0], v[1], v[2], v[3], v[4]) 937 } 938 939 g.imps["go-hep.org/x/hep/groot/rbase"] = 1 940 if g.rdict != "" { 941 g.imps["go-hep.org/x/hep/groot/rdict"] = 1 942 } 943 g.imps["go-hep.org/x/hep/groot/rmeta"] = 1 944 945 switch se := se.(type) { 946 case *StreamerBase: 947 g.printf(`%[13]sNewStreamerBase(%[13]sElement{ 948 Name: *rbase.NewNamed(%[1]q, %[2]q), 949 Type: rmeta.Base, 950 Size: %[3]d, 951 ArrLen: %[4]d, 952 ArrDim: %[5]d, 953 MaxIdx: %[6]s, 954 Offset: %[7]d, 955 EName: %[8]q, 956 XMin: %[9]f, 957 XMax: %[10]f, 958 Factor: %[11]f, 959 }.New(), %[12]d), 960 `, 961 se.Name(), se.Title(), 962 se.esize, 963 se.arrlen, 964 se.arrdim, 965 maxidx(se.maxidx), 966 se.offset, 967 se.ename, 968 se.xmin, se.xmax, se.factor, 969 se.vbase, 970 g.rdict, 971 ) 972 973 case *StreamerBasicType: 974 g.printf(`&%[13]sStreamerBasicType{StreamerElement: %[13]sElement{ 975 Name: *rbase.NewNamed(%[1]q, %[2]q), 976 Type: rmeta.%[3]v, 977 Size: %[4]d, 978 ArrLen: %[5]d, 979 ArrDim: %[6]d, 980 MaxIdx: %[7]s, 981 Offset: %[8]d, 982 EName: %[9]q, 983 XMin: %[10]f, 984 XMax: %[11]f, 985 Factor: %[12]f, 986 }.New()}, 987 `, 988 se.Name(), se.Title(), 989 se.etype, 990 se.esize, 991 se.arrlen, 992 se.arrdim, 993 maxidx(se.maxidx), 994 se.offset, 995 se.ename, 996 se.xmin, se.xmax, se.factor, 997 g.rdict, 998 ) 999 1000 case *StreamerBasicPointer: 1001 g.printf(`%[16]sNewStreamerBasicPointer(%[16]sElement{ 1002 Name: *rbase.NewNamed(%[1]q, %[2]q), 1003 Type: %[3]d, 1004 Size: %[4]d, 1005 ArrLen: %[5]d, 1006 ArrDim: %[6]d, 1007 MaxIdx: %[7]s, 1008 Offset: %[8]d, 1009 EName: %[9]q, 1010 XMin: %[10]f, 1011 XMax: %[11]f, 1012 Factor: %[12]f, 1013 }.New(), %[13]d, %[14]q, %[15]q), 1014 `, 1015 se.Name(), se.Title(), 1016 se.etype, 1017 se.esize, 1018 se.arrlen, 1019 se.arrdim, 1020 maxidx(se.maxidx), 1021 se.offset, 1022 se.ename, 1023 se.xmin, se.xmax, se.factor, 1024 se.cvers, se.cname, se.ccls, 1025 g.rdict, 1026 ) 1027 1028 case *StreamerLoop: 1029 g.printf(`%[15]sNewStreamerLoop(%[15]sElement{ 1030 Name: *rbase.NewNamed(%[1]q, %[2]q), 1031 Type: rmeta.StreamLoop, 1032 Size: %[3]d, 1033 ArrLen: %[4]d, 1034 ArrDim: %[5]d, 1035 MaxIdx: %[6]s, 1036 Offset: %[7]d, 1037 EName: %[8]q, 1038 XMin: %[9]f, 1039 XMax: %[10]f, 1040 Factor: %[11]f, 1041 }.New(), %[12]d, %[13]q, %[14]q), 1042 `, 1043 se.Name(), se.Title(), 1044 se.esize, 1045 se.arrlen, 1046 se.arrdim, 1047 maxidx(se.maxidx), 1048 se.offset, 1049 se.ename, 1050 se.xmin, se.xmax, se.factor, 1051 se.cvers, se.cname, se.cclass, 1052 g.rdict, 1053 ) 1054 1055 case *StreamerObject: 1056 g.printf(`&%[13]sStreamerObject{StreamerElement: %[13]sElement{ 1057 Name: *rbase.NewNamed(%[1]q, %[2]q), 1058 Type: rmeta.%[3]v, 1059 Size: %[4]d, 1060 ArrLen: %[5]d, 1061 ArrDim: %[6]d, 1062 MaxIdx: %[7]s, 1063 Offset: %[8]d, 1064 EName: %[9]q, 1065 XMin: %[10]f, 1066 XMax: %[11]f, 1067 Factor: %[12]f, 1068 }.New()}, 1069 `, 1070 se.Name(), se.Title(), 1071 se.etype, 1072 se.esize, 1073 se.arrlen, 1074 se.arrdim, 1075 maxidx(se.maxidx), 1076 se.offset, 1077 se.ename, 1078 se.xmin, se.xmax, se.factor, 1079 g.rdict, 1080 ) 1081 1082 case *StreamerObjectPointer: 1083 g.printf(`&%[13]sStreamerObjectPointer{StreamerElement: %[13]sElement{ 1084 Name: *rbase.NewNamed(%[1]q, %[2]q), 1085 Type: rmeta.%[3]v, 1086 Size: %[4]d, 1087 ArrLen: %[5]d, 1088 ArrDim: %[6]d, 1089 MaxIdx: %[7]s, 1090 Offset: %[8]d, 1091 EName: %[9]q, 1092 XMin: %[10]f, 1093 XMax: %[11]f, 1094 Factor: %[12]f, 1095 }.New()}, 1096 `, 1097 se.Name(), se.Title(), 1098 se.etype, 1099 se.esize, 1100 se.arrlen, 1101 se.arrdim, 1102 maxidx(se.maxidx), 1103 se.offset, 1104 se.ename, 1105 se.xmin, se.xmax, se.factor, 1106 g.rdict, 1107 ) 1108 1109 case *StreamerObjectAny: 1110 g.printf(`&%[13]sStreamerObjectAny{StreamerElement: %[13]sElement{ 1111 Name: *rbase.NewNamed(%[1]q, %[2]q), 1112 Type: rmeta.%[3]v, 1113 Size: %[4]d, 1114 ArrLen: %[5]d, 1115 ArrDim: %[6]d, 1116 MaxIdx: %[7]s, 1117 Offset: %[8]d, 1118 EName: %[9]q, 1119 XMin: %[10]f, 1120 XMax: %[11]f, 1121 Factor: %[12]f, 1122 }.New()}, 1123 `, 1124 se.Name(), se.Title(), 1125 se.etype, 1126 se.esize, 1127 se.arrlen, 1128 se.arrdim, 1129 maxidx(se.maxidx), 1130 se.offset, 1131 se.ename, 1132 se.xmin, se.xmax, se.factor, 1133 g.rdict, 1134 ) 1135 1136 case *StreamerObjectAnyPointer: 1137 g.printf(`&%[13]sStreamerObjectAnyPointer{StreamerElement: %[13]sElement{ 1138 Name: *rbase.NewNamed(%[1]q, %[2]q), 1139 Type: rmeta.%[3]v, 1140 Size: %[4]d, 1141 ArrLen: %[5]d, 1142 ArrDim: %[6]d, 1143 MaxIdx: %[7]s, 1144 Offset: %[8]d, 1145 EName: %[9]q, 1146 XMin: %[10]f, 1147 XMax: %[11]f, 1148 Factor: %[12]f, 1149 }.New()}, 1150 `, 1151 se.Name(), se.Title(), 1152 se.etype, 1153 se.esize, 1154 se.arrlen, 1155 se.arrdim, 1156 maxidx(se.maxidx), 1157 se.offset, 1158 se.ename, 1159 se.xmin, se.xmax, se.factor, 1160 g.rdict, 1161 ) 1162 1163 case *StreamerString: 1164 g.printf(`&%[13]sStreamerString{StreamerElement: %[13]sElement{ 1165 Name: *rbase.NewNamed(%[1]q, %[2]q), 1166 Type: rmeta.%[3]v, 1167 Size: %[4]d, 1168 ArrLen: %[5]d, 1169 ArrDim: %[6]d, 1170 MaxIdx: %[7]s, 1171 Offset: %[8]d, 1172 EName: %[9]q, 1173 XMin: %[10]f, 1174 XMax: %[11]f, 1175 Factor: %[12]f, 1176 }.New()}, 1177 `, 1178 se.Name(), se.Title(), 1179 se.etype, 1180 se.esize, 1181 se.arrlen, 1182 se.arrdim, 1183 maxidx(se.maxidx), 1184 se.offset, 1185 se.ename, 1186 se.xmin, se.xmax, se.factor, 1187 g.rdict, 1188 ) 1189 1190 case *StreamerSTL: 1191 g.printf(`%[15]sNewCxxStreamerSTL(%[15]sElement{ 1192 Name: *rbase.NewNamed(%[1]q, %[2]q), 1193 Type: rmeta.%[3]v, 1194 Size: %[4]d, 1195 ArrLen: %[5]d, 1196 ArrDim: %[6]d, 1197 MaxIdx: %[7]s, 1198 Offset: %[8]d, 1199 EName: %[9]q, 1200 XMin: %[10]f, 1201 XMax: %[11]f, 1202 Factor: %[12]f, 1203 }.New(), %[13]d, %[14]d), 1204 `, 1205 se.Name(), se.Title(), 1206 se.etype, 1207 se.esize, 1208 se.arrlen, 1209 se.arrdim, 1210 maxidx(se.maxidx), 1211 se.offset, 1212 se.ename, 1213 se.xmin, se.xmax, se.factor, 1214 se.vtype, se.ctype, 1215 g.rdict, 1216 ) 1217 1218 case *StreamerSTLstring: 1219 g.printf(`&%[15]sStreamerSTLstring{*%[15]sNewCxxStreamerSTL(%[15]sElement{ 1220 Name: *rbase.NewNamed(%[1]q, %[2]q), 1221 Type: rmeta.%[3]v, 1222 Size: %[4]d, 1223 ArrLen: %[5]d, 1224 ArrDim: %[6]d, 1225 MaxIdx: %[7]s, 1226 Offset: %[8]d, 1227 EName: %[9]q, 1228 XMin: %[10]f, 1229 XMax: %[11]f, 1230 Factor: %[12]f, 1231 }.New(), %[13]d, %[14]d)}, 1232 `, 1233 se.Name(), se.Title(), 1234 se.etype, 1235 se.esize, 1236 se.arrlen, 1237 se.arrdim, 1238 maxidx(se.maxidx), 1239 se.offset, 1240 se.ename, 1241 se.xmin, se.xmax, se.factor, 1242 se.vtype, se.ctype, 1243 g.rdict, 1244 ) 1245 1246 case *StreamerArtificial: 1247 g.printf(`&%[13]sStreamerArtificial{StreamerElement: %[13]sElement{ 1248 Name: *rbase.NewNamed(%[1]q, %[2]q), 1249 Type: rmeta.%[3]v, 1250 Size: %[4]d, 1251 ArrLen: %[5]d, 1252 ArrDim: %[6]d, 1253 MaxIdx: %[7]s, 1254 Offset: %[8]d, 1255 EName: %[9]q, 1256 XMin: %[10]f, 1257 XMax: %[11]f, 1258 Factor: %[12]f, 1259 }.New()}, 1260 `, 1261 se.Name(), se.Title(), 1262 se.etype, 1263 se.esize, 1264 se.arrlen, 1265 se.arrdim, 1266 maxidx(se.maxidx), 1267 se.offset, 1268 se.ename, 1269 se.xmin, se.xmax, se.factor, 1270 g.rdict, 1271 ) 1272 1273 default: 1274 g.printf("// %s -- %T\n", se.Name(), se) 1275 panic(fmt.Errorf("rdict: unknown streamer type %T (%#v)", se, se)) 1276 } 1277 } 1278 1279 func (g *genGoType) printf(format string, args ...any) { 1280 fmt.Fprintf(g.buf, format, args...) 1281 } 1282 1283 // Generate implements rdict.Generator 1284 func (g *genGoType) Format() ([]byte, error) { 1285 buf := new(bytes.Buffer) 1286 1287 buf.WriteString(fmt.Sprintf(`// DO NOT EDIT; automatically generated by %[1]s 1288 1289 package %[2]s 1290 1291 import ( 1292 `, 1293 "root-gen-type", 1294 g.pkg, 1295 )) 1296 1297 var ( 1298 stdlib []string 1299 imps []string 1300 ) 1301 1302 for k := range g.imps { 1303 switch { 1304 case !strings.Contains(k, "."): // stdlib 1305 stdlib = append(stdlib, k) 1306 default: 1307 imps = append(imps, k) 1308 } 1309 } 1310 1311 sort.Strings(stdlib) 1312 for _, pkg := range stdlib { 1313 fmt.Fprintf(buf, "%q\n", pkg) 1314 } 1315 fmt.Fprintf(buf, "\n") 1316 1317 sort.Strings(imps) 1318 for _, pkg := range imps { 1319 fmt.Fprintf(buf, "%q\n", pkg) 1320 } 1321 fmt.Fprintf(buf, ")\n\n") 1322 1323 buf.Write(g.buf.Bytes()) 1324 1325 src, err := format.Source(buf.Bytes()) 1326 if err != nil { 1327 log.Printf("=== error ===\n%s\n", buf.Bytes()) 1328 } 1329 return src, err 1330 } 1331 1332 var ( 1333 _ Generator = (*genGoType)(nil) 1334 )