How to use pushPos method of json Package

Best Go-testdeep code snippet using json.pushPos

codegen.go

Source:codegen.go Github

copy

Full Screen

...112}113func (g *Codegen) logSrcWarn(format string, args ...interface{}) {114 logSrcWarn(g.srcdir, g.pkg, g.pos, format, args...)115}116func (g *Codegen) pushPos(pos token.Pos) {117 g.posstack = append(g.posstack, g.pos)118 g.pos = pos119}120func (g *Codegen) popPos() {121 g.pos = g.posstack[len(g.posstack)-1]122 g.posstack = g.posstack[:len(g.posstack)-1]123}124// isMutableRefType returns true if t is a type which underlying value may be changed without125// assignment. For example a slice.126func isMutableRefType(typ types.Type) bool {127 for {128 switch t := typ.(type) {129 case *types.Array, *types.Slice, *types.Map, *types.Pointer, *types.Struct:130 return true131 case *types.Named:132 typ = t.Underlying()133 default:134 return false135 }136 }137 return false138}139// —————————————————————————————————————————————————————————————————————————————————————————140// encode141func (g *Codegen) codegenEncodeField(f *EntField) error {142 cvar := "c"143 expr, err := g.genFieldEncoder(f, cvar, "e."+f.sname)144 if err != nil {145 return err146 }147 g.f(" %s.Key(%#v)\n", cvar, f.name)148 g.f(" %s\n", expr)149 return nil150}151func (g *Codegen) genFieldEncoder(f *EntField, cvar, valexpr string) (string, error) {152 g.pushPos(f.t.pos)153 defer g.popPos()154 expr, err := g.encoderExpr(f.t.Type, cvar, valexpr)155 if err == ErrUnsupportedType {156 g.logErrUnsupportedType(f)157 }158 return expr, err159}160func (g *Codegen) encoderExpr(typ types.Type, cvar, valexpr string) (expr string, err error) {161 typ, cast := g.unwrapNamedType(typ)162 if cast != "" {163 // flip cast164 cast = g.goTypeName(typ)165 }166 switch t := typ.(type) {167 case *types.Basic:168 m, cast, advice := g.basicCodecCall(t, codecEncode, cast != "")169 if advice != "" {170 advice = ", " + advice171 }172 expr = fmt.Sprintf("%s.%s(%s%s)", cvar, m, wrapstr(valexpr, cast), advice)173 return174 case *types.Slice, *types.Array:175 if cast != "" {176 cast = ""177 }178 var elemt types.Type179 if st, ok := t.(*types.Slice); ok {180 elemt = st.Elem()181 } else {182 elemt = t.(*types.Array).Elem()183 // use slice of all arrays (even those that are not [N]byte)184 valexpr += "[:]"185 // convert to slice so that genComplexEncoder uses slice encoders instead of generating186 // array encoders.187 typ = types.NewSlice(elemt)188 }189 // special case for []byte190 if bt, ok := elemt.(*types.Basic); ok && bt.Kind() == types.Uint8 {191 expr = fmt.Sprintf("%s.Blob(%s)", cvar, wrapstr(valexpr, cast))192 return193 }194 }195 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_encode_", g.genComplexEncoder)196 expr += "(" + cvar + ", " + wrapstr(valexpr, cast) + ")"197 return198}199func (g *Codegen) genComplexEncoder(typ types.Type, cvar string, buf *bytes.Buffer) error {200 wf := func(format string, args ...interface{}) {201 fmt.Fprintf(buf, format, args...)202 }203 goType := g.goTypeName(typ)204 wf("(%s ent.Encoder, v %s) {\n", cvar, goType)205 switch t := typ.(type) {206 case *types.Slice:207 expr, err := g.encoderExpr(t.Elem(), cvar, "val")208 if err != nil {209 return err210 }211 wf(" %s.BeginList(len(v))\n", cvar)212 wf(" for _, val := range v {\n")213 wf(" %s\n", expr)214 wf(" }\n")215 wf(" %s.EndList()\n", cvar)216 case *types.Map:217 expr, err := g.encoderExpr(t.Elem(), cvar, "val")218 if err != nil {219 return err220 }221 if kt, ok := t.Key().(*types.Basic); !ok || kt.Kind() != types.String {222 g.logSrcErr("unsupported map key type %s; only string map keys are supported", t.Key())223 return ErrUnsupportedType224 }225 wf(" %s.BeginDict(len(v))\n", cvar)226 wf(" for k, val := range v {\n")227 wf(" %s.Key(k)\n", cvar)228 wf(" %s\n", expr)229 wf(" }\n")230 wf(" %s.EndDict()\n", cvar)231 default:232 return ErrUnsupportedType233 } // switch typ234 wf("}\n")235 return nil236}237// —————————————————————————————————————————————————————————————————————————————————————————238// decode239func (g *Codegen) codegenDecodeField(f *EntField) error {240 g.pushPos(f.t.pos)241 defer g.popPos()242 expr, cast, err := g.decoderExpr(f.t.Type, "c")243 if err != nil {244 if err == ErrUnsupportedType {245 g.logErrUnsupportedType(f)246 }247 return err248 }249 g.f(" e.%s = %s\n", f.sname, wrapstr(expr, cast))250 return nil251}252// decoderExpr generates & returns a "decode" expression like "c.Int(64)"253func (g *Codegen) decoderExpr(typ types.Type, cvar string) (expr, cast string, err error) {254 typ, cast = g.unwrapNamedType(typ)255 switch t := typ.(type) {256 case *types.Basic:257 m, basicCast, advice := g.basicCodecCall(t, codecDecode, false)258 if cast == "" {259 cast = basicCast260 }261 expr = fmt.Sprintf("%s.%s(%s)", cvar, m, advice)262 return263 case *types.Slice:264 // special case for []byte265 if bt, ok := t.Elem().(*types.Basic); ok && bt.Kind() == types.Uint8 {266 expr = cvar + ".Blob()"267 return268 }269 case *types.Array:270 // arrays are decoded as slices then copied into arrays via a ent_slice_to_AN_T helper271 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_slice_to_", g.genCopyHelper)272 if bt, ok := t.Elem().(*types.Basic); ok && bt.Kind() == types.Uint8 {273 // special case for [N]byte274 expr += "(" + cvar + ".Blob())"275 } else {276 slicet := types.NewSlice(t.Elem())277 expr2, err2 := g.getOrBuildTypeHelper(slicet, cvar, "ent_decode_", g.genComplexDecoder)278 err = err2279 expr += "(" + expr2 + "(" + cvar + "))"280 }281 return282 } // switch t:=typ.(type)283 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_decode_", g.genComplexDecoder)284 expr += "(" + cvar + ")"285 return286}287// genCopyHelper assumes typ is *types.Array288func (g *Codegen) genCopyHelper(typ types.Type, cvar string, buf *bytes.Buffer) error {289 wf := func(format string, args ...interface{}) {290 fmt.Fprintf(buf, format, args...)291 }292 elemt := typ.(*types.Array).Elem()293 goType := g.goTypeName(typ)294 elemGoType := g.goTypeName(elemt)295 wf("(s []%s) (r %s) {\n", elemGoType, goType)296 wf(" copy(r[:], s)\n")297 wf(" return\n" +298 "}\n")299 return nil300}301func (g *Codegen) genComplexDecoder(typ types.Type, cvar string, buf *bytes.Buffer) error {302 wf := func(format string, args ...interface{}) {303 fmt.Fprintf(buf, format, args...)304 }305 goType := g.goTypeName(typ)306 wf("(%s ent.Decoder) (r %s) {\n", cvar, goType)307 switch t := typ.(type) {308 case *types.Slice:309 expr, cast, err := g.decoderExpr(t.Elem(), cvar)310 if err != nil {311 return err312 }313 wf(" n := %s.ListHeader()\n", cvar)314 wf(" if n > -1 {\n")315 wf(" r = make(%s, 0, n)\n", goType)316 wf(" for i := 0; i < n; i++ {\n")317 wf(" r = append(r, %s)\n", wrapstr(expr, cast))318 wf(" }\n")319 wf(" } else {\n")320 wf(" for %s.More() {\n", cvar)321 wf(" r = append(r, %s)\n", wrapstr(expr, cast))322 wf(" }\n")323 wf(" }\n")324 case *types.Map:325 expr, cast, err := g.decoderExpr(t.Elem(), cvar)326 if err != nil {327 return err328 }329 // note: we don't check that key type is string since we already check for that in330 // genComplexEncoder331 valueGoType := g.goTypeName(t.Elem())332 wf(" n := %s.DictHeader()\n", cvar)333 wf(" r = make(map[string]%s, n)\n", valueGoType)334 wf(" if n > -1 {\n")335 wf(" for i := 0; i < n; i++ {\n")336 wf(" k := %s.Key()\n", cvar)337 wf(" r[k] = %s\n", wrapstr(expr, cast))338 wf(" }\n")339 wf(" } else {\n")340 wf(" for %s.More() {\n", cvar)341 wf(" k := %s.Key()\n", cvar)342 wf(" r[k] = %s\n", wrapstr(expr, cast))343 wf(" }\n")344 wf(" }\n")345 // case *types.Array:346 // expr, cast, err := g.decoderExpr(t.Elem())347 // if err != nil {348 // return err349 // }350 // wf(" n := c.ListHeader()\n")351 // wf(" if n < 0 {\n")352 // wf(" for i := 0; c.More(); i++ {\n")353 // wf(" if i < %d {\n", t.Len())354 // wf(" r[i] = %s\n", wrapstr(expr, cast))355 // wf(" } else {\n")356 // wf(" c.Discard()\n")357 // wf(" }\n")358 // wf(" }\n")359 // wf(" } else {\n")360 // wf(" if n > %d { n = %d }\n", t.Len(), t.Len())361 // wf(" for i := 0; i < n; i++ {\n")362 // wf(" r[i] = %s\n", wrapstr(expr, cast))363 // wf(" }\n")364 // wf(" }\n")365 default:366 return ErrUnsupportedType367 } // switch typ368 wf(" return\n}\n") // end of `func {fname}(cvar ent.Decoder) ...`369 return nil370}371// —————————————————————————————————————————————————————————————————————————————————————————372// both encoding & decoding373type HelperBuilder = func(t types.Type, cvar string, b *bytes.Buffer) error374func (g *Codegen) getOrBuildTypeHelper(375 typ types.Type,376 cvar, fnamePrefix string,377 builder HelperBuilder,378) (string, error) {379 fname, err := Typemangle(g.pkg.Types, typ)380 if err != nil {381 return "", err382 }383 fname = fnamePrefix + fname384 err = g.getOrBuildHelper(fname, cvar, typ, builder)385 return fname, err386}387func (g *Codegen) getOrBuildHelper(fname, cvar string, t types.Type, builder HelperBuilder) error {388 if g.helperm == nil {389 g.helperm = map[string]error{}390 } else {391 err, ok := g.helperm[fname]392 if ok {393 return err394 }395 }396 log.Debug("codegen helper %s", fname)397 var buf bytes.Buffer398 buf.WriteString("\nfunc ")399 buf.WriteString(fname)400 err := builder(t, cvar, &buf)401 g.helperm[fname] = err402 if err == nil {403 g.helperw.Write(buf.Bytes())404 }405 return err406}407func (g *Codegen) unwrapNamedType(typ types.Type) (canonical types.Type, cast string) {408 // unwrap named type (does not include aliases, which do not need casting)409 canonical = typ410 for {411 t, ok := canonical.(*types.Named)412 if !ok {413 break414 }415 canonical = t.Underlying()416 if canonical == typ {417 break418 }419 if cast == "" {420 cast = g.goTypeName(typ)421 }422 }423 return424}425func (g *Codegen) basicCodecCall(426 t *types.Basic, cdir codecDir, mustcast bool,427) (m, cast, advice string) {428 kind := t.Kind()429 var wantadvice bool430 setcast := func(enccast string) {431 if cdir == codecDecode {432 cast = g.goTypeName(t)433 } else {434 cast = enccast435 }436 }437 switch kind {438 case types.Bool, types.UntypedBool:439 m = "Bool"440 case types.Int, types.UntypedInt, types.Int8, types.Int16, types.Int32, types.Int64,441 types.UntypedRune:442 if mustcast || kind != types.Int64 {443 setcast("int64")444 }445 m = "Int"446 wantadvice = true447 case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64,448 types.Uintptr, types.UnsafePointer:449 if mustcast || kind != types.Uint64 {450 setcast("uint64")451 }452 m = "Uint"453 wantadvice = true454 case types.UntypedFloat, types.Float32, types.Float64:455 if mustcast || kind != types.Float64 {456 setcast("float64")457 }458 m = "Float"459 wantadvice = true460 case types.UntypedComplex, types.Complex64, types.Complex128:461 if mustcast || kind != types.Complex128 {462 setcast("complex128")463 }464 m = "Complex"465 wantadvice = true466 case types.String, types.UntypedString:467 m = "Str"468 }469 if wantadvice {470 advice = basicKindSizeAdvice(t.Kind())471 }472 return473}474// —————————————————————————————————————————————————————————————————————————————————————————475// ent476func (g *Codegen) codegenEnt(e *EntInfo) error {477 w := g.w478 g.pushPos(e.pos)479 defer g.popPos()480 log.Info("codegen ent %q (%s.%s)", e.name, e.pkg.Name, e.sname)481 linefeed := []byte{'\n'}482 wstr := func(s string) { w.Write([]byte(s)) }483 wline := func() { w.Write(linefeed) }484 // wbyte := func(b byte) { w.Write([]byte{b}) }485 userMethods := e.getUserMethods()486 generatedMethods := map[string]bool{}487 var err error488 // methodIsUndefined checks if user has defined "name" method489 methodIsUndefined := func(name string) bool {490 return userMethods[name] == nil && !generatedMethods[name]491 }492 // methodMustBeUndefined checks if user has defined "name" method. If not, returns true.493 // If there is a definition, logs an error and returns false.494 methodMustBeUndefined := func(name, help string) bool {495 m := userMethods[name]496 if m == nil {497 if generatedMethods[name] {498 panic("trying to generate method " + name + " twice")499 }500 return true501 }502 if help != "" {503 help = " " + help504 }505 e.logSrcErr(m.pos, "ent method %s already defined for %s.%s", name, e.sname, help)506 if err == nil {507 err = fmt.Errorf("method definition conflict")508 }509 // TODO error510 return false511 }512 methodWarnIfDefinedAlt := func(name, help string) string {513 if m := userMethods[name]; m != nil {514 lname := inverseCapitalize(name)515 if lname != name {516 if help != "" {517 help = " " + help518 }519 e.logSrcWarn(m.pos,520 "ent method %s is already defined for %s. Naming the generated method %s instead.%s",521 name, e.sname, lname, help)522 help = "" // so we don't print it twice in case there's an error next523 }524 name = lname525 methodMustBeUndefined(name, help)526 } else if generatedMethods[name] {527 panic("trying to generate method " + name + " twice")528 }529 return name530 }531 funcIsUndefined := func(name string) bool {532 // TODO user functions533 return !g.generatedFunctions[name]534 }535 // compile indexes536 fieldIndexes := g.collectFieldIndexes(e.fields)537 g.f(538 "// ----------------------------------------------------------------------------\n// %s\n\n",539 e.sname)540 // // replicate original struct documentation541 // if len(e.doc) > 0 {542 // wstr("// ")543 // wstr(strings.Join(e.doc, "\n// "))544 // wline()545 // }546 // variables & constants547 // // ent.Register548 // wline()549 // g.f("var _ = ent.Register(&%s{})\n", e.sname)550 // wline()551 // LoadTYPEById(s ent.Storage, id uint64) (*TYPE, error)552 fname := "Load" + e.sname + "ById"553 if funcIsUndefined(fname) {554 g.generatedFunctions[fname] = true555 g.f("// %s loads %s with id from storage\n"+556 "func %s(storage ent.Storage, id uint64) (*%s, error)\t{\n"+557 " e := &%s{}\n"+558 " return e, ent.LoadEntById(e, storage, id)\n"+559 "}\n\n",560 fname, e.sname,561 fname, e.sname,562 e.sname)563 }564 // FindTYPEByINDEX565 // LoadTYPEByINDEX566 for _, fx := range fieldIndexes {567 if err := g.genFindTYPEByINDEX(e, fx); err != nil {568 return err569 }570 }571 mname := "EntTypeName"572 if methodMustBeUndefined(mname, "Use tag on EntBase field instead (e.g. `typename`)") {573 generatedMethods[mname] = true574 g.f("// %s returns the ent's storage name (%q)\n"+575 "func (e %s) %s() string\t{ return %#v }\n\n",576 mname, e.name,577 e.sname, mname, e.name)578 }579 mname = "EntStorage"580 if methodIsUndefined(mname) {581 generatedMethods[mname] = true582 g.f("// %s returns the storage this ent belongs to or nil if it doesn't belong anywhere.\n"+583 "func (e *%s) %s() ent.Storage\t{ return ent.GetStorage(e) }\n\n",584 mname,585 e.sname, mname)586 }587 mname = "EntNew"588 if methodIsUndefined(mname) {589 generatedMethods[mname] = true590 g.f("// %s returns a new empty %s. Used by the ent package for loading ents.\n"+591 "func (e %s) %s() ent.Ent\t{ return &%s{} }\n\n",592 mname, e.sname,593 e.sname, mname, e.sname)594 }595 mname = "MarshalJSON"596 if methodIsUndefined(mname) {597 generatedMethods[mname] = true598 g.f("// %s returns a JSON representation of e. Conforms to json.Marshaler.\n"+599 "func (e *%s) %s() ([]byte, error) { return ent.JsonEncode(e, \"\") }\n\n",600 mname,601 e.sname, mname)602 }603 mname = "UnmarshalJSON"604 if methodIsUndefined(mname) {605 generatedMethods[mname] = true606 g.f("// %s populates the ent from JSON data. Conforms to json.Unmarshaler.\n"+607 "func (e *%s) %s(b []byte) error { return ent.JsonDecode(e, b) }\n\n",608 mname,609 e.sname, mname)610 }611 mname = "String"612 if methodIsUndefined(mname) {613 generatedMethods[mname] = true614 g.f("// %s returns a JSON representation of e.\n"+615 "func (e %s) %s() string { return ent.EntString(&e) }\n\n",616 mname,617 e.sname, mname)618 }619 mname = "Create"620 if methodIsUndefined(mname) {621 generatedMethods[mname] = true622 g.f("// %s a new %s ent in storage\n"+623 "func (e *%s) %s(storage ent.Storage) error\t{ return ent.CreateEnt(e, storage) }\n",624 mname, e.name,625 e.sname, mname)626 }627 mname = "Save"628 if methodIsUndefined(mname) {629 generatedMethods[mname] = true630 g.f("// %s pending changes to whatever storage this ent was created or loaded from\n"+631 "func (e *%s) %s() error\t{ return ent.SaveEnt(e) }\n",632 mname,633 e.sname, mname)634 }635 mname = "Reload"636 if methodIsUndefined(mname) {637 generatedMethods[mname] = true638 g.f("// %s fields to latest values from storage, discarding any unsaved changes\n"+639 "func (e *%s) %s() error\t{ return ent.ReloadEnt(e) }\n",640 mname,641 e.sname, mname)642 }643 mname = "PermanentlyDelete"644 if methodIsUndefined(mname) {645 generatedMethods[mname] = true646 g.f("// %s deletes this ent from storage. This can usually not be undone.\n"+647 "func (e *%s) %s() error\t{ return ent.DeleteEnt(e) }\n",648 mname,649 e.sname, mname)650 }651 mname = "Iterator"652 if methodIsUndefined(mname) {653 generatedMethods[mname] = true654 g.f("// %s returns an iterator over all %s ents. Order is undefined.\n"+655 "func (e %s) %s(s ent.Storage) ent.EntIterator\t{ return s.IterateEnts(&e) }\n",656 mname, e.sname,657 e.sname, mname)658 }659 wline()660 // begin field accessor methods661 if len(e.fields) > 0 {662 wstr("// ---- field accessor methods ----\n\n")663 fieldsWithTags := []*EntField{}664 // field getters665 // func (e *ENTTYPE) Field() { return e.field }666 didGenerateGetters := false667 for _, field := range e.fields {668 if len(field.tags) > 0 {669 fieldsWithTags = append(fieldsWithTags, field)670 }671 // skip gettter if the field has a public name672 if field.uname == field.sname {673 continue674 }675 // skip if user has defined a method with the same name676 if !methodIsUndefined(field.uname) {677 continue678 }679 // sname is lower case; generate getter function680 // if the field has documentation, add it to the getter for nice godoc681 if len(field.doc) > 0 {682 wstr("// ")683 wstr(strings.Join(field.doc, "\n// "))684 wline()685 }686 g.f("func (e *%s) %s() %s\t{ return e.%s }\n",687 e.sname,688 field.uname,689 g.goTypeName(field.t.Type),690 field.sname,691 )692 generatedMethods[field.uname] = true693 didGenerateGetters = true694 }695 if didGenerateGetters {696 wline()697 }698 // field setters699 // func (e *Type) SetField() { e.field }700 fieldSetterPrefix := "Set"701 if g.PrivateFieldSetters {702 fieldSetterPrefix = "set"703 }704 var genChangedSetters []*EntField705 var genConditionalSetters []*EntField706 var genConditionalSettersSetNames []string707 for _, field := range e.fields {708 mname := fieldSetterPrefix + field.uname709 if !methodIsUndefined(mname) {710 if g.PrivateFieldSetters {711 continue712 }713 // If the user has defined a method with the same name, define a private lower-case version714 //715 // This can be useful for the author to use in composition, e.g.716 // // user-defined717 // func (e *Foo) SetThing(v int) {718 // if someCondition() {719 // e.setThing() // call entgen-generated method720 // }721 // }722 //723 mname = "set" + field.uname724 if !methodIsUndefined(mname) {725 // user has defined that one too; they don't want it to be generated.726 continue727 }728 }729 if types.Comparable(field.t.Type) {730 genConditionalSetters = append(genConditionalSetters, field)731 genConditionalSettersSetNames = append(genConditionalSettersSetNames, mname)732 }733 g.f("func (e *%s) %s(v %s)\t{"+734 " e.%s = v;"+735 " e.EntBase.SetEntFieldChanged(%d)"+736 "}\n",737 e.sname, mname, g.goTypeName(field.t.Type),738 field.sname,739 field.index,740 )741 generatedMethods[mname] = true742 if isMutableRefType(field.t.Type) {743 genChangedSetters = append(genChangedSetters, field)744 }745 }746 // SetFIELDIfDifferent()747 if len(genConditionalSetters) > 0 {748 wline()749 for i, field := range genConditionalSetters {750 mname := fieldSetterPrefix + field.uname + "IfDifferent"751 if !methodIsUndefined(mname) {752 continue753 }754 generatedMethods[mname] = true755 setMname := genConditionalSettersSetNames[i]756 g.f("// %s sets %s only if v is different from the current value.\n"+757 "func (e *%s) %s(v %s) bool\t{\n"+758 " if e.%s == v {\n"+759 " return false\n"+760 " }\n"+761 " e.%s(v)\n"+762 " return true\n"+763 "}\n\n",764 mname, field.sname,765 e.sname, mname, g.goTypeName(field.t.Type),766 field.sname,767 setMname,768 )769 }770 }771 // SetFIELDChanged(bool) -- only for fields of referential mutable types772 if len(genChangedSetters) > 0 {773 wline()774 for _, field := range genChangedSetters {775 mname := fieldSetterPrefix + field.uname + "Changed"776 if !methodIsUndefined(mname) {777 continue778 }779 generatedMethods[mname] = true780 g.f("func (e *%s) %s()\t{ e.EntBase.SetEntFieldChanged(%d) }\n",781 e.sname, mname, field.index)782 }783 }784 // EntEncode & EntDecode785 wstr("// ---- encode & decode methods ----\n\n")786 // -- EntEncode --787 mname := methodWarnIfDefinedAlt(788 "EntEncode",789 "Make sure to call entEncode from your EntEncode method",790 )791 generatedMethods[mname] = true792 g.f("\nfunc (e *%s) %s(c ent.Encoder, fields ent.FieldSet) {", e.sname, mname)793 // g.f("\n\teb := &e.EntBase\n")794 for _, field := range e.fields {795 g.pushPos(field.pos)796 // Note: Rather than precomputing (1<<field.index), let the compiler apply constant797 // evaluation instead. This makes the generated code more readable.798 g.f("\tif fields.Has(%d)\t{", field.index)799 err := g.codegenEncodeField(field)800 wstr(" }\n")801 g.popPos()802 if err != nil {803 return err804 }805 }806 wstr("}\n")807 // -- EntDecode --808 mname = methodWarnIfDefinedAlt(809 "EntDecode",810 "Make sure to call entDecode from your EntDecode method",811 )812 generatedMethods[mname] = true813 if err := g.genEntDecode(e, mname); err != nil {814 return err815 }816 }817 // -- EntDecodePartial --818 mname = methodWarnIfDefinedAlt(819 "EntDecodePartial",820 "Make sure to call entDecodeIndexed from your EntDecodePartial method",821 )822 generatedMethods[mname] = true823 if err := g.genEntDecodePartial(e, mname); err != nil {824 return err825 }826 // EntFields827 if methodMustBeUndefined("EntFields", "") {828 g.genEntFields(e)829 }830 // data & methods for ents with indexes831 if len(fieldIndexes) > 0 {832 // -- EntIndexes --833 if methodIsUndefined("EntIndexes") {834 generatedMethods["EntIndexes"] = true835 g.f("\n// Indexes (Name, Fields, Flags)\n")836 g.f("var ent_%s_idx = []ent.EntIndex{\n", e.sname)837 for _, x := range fieldIndexes {838 var flags []string839 if (x.flags & fieldIndexUnique) != 0 {840 flags = append(flags, "ent.EntIndexUnique")841 }842 if len(flags) == 0 {843 flags = append(flags, "0")844 }845 fieldIndices := genFieldmap(e, x.fields)846 g.f("{ %#v, %s, %s },\n", x.name, fieldIndices, strings.Join(flags, "|"))847 }848 g.f("}\n\n")849 g.f("// EntIndexes returns information about secondary indexes\n")850 g.f("func (e *%s) EntIndexes() []ent.EntIndex { return ent_%s_idx }\n",851 e.sname, e.sname)852 }853 } // if len(fieldIndexes) > 0854 if log.RootLogger.Level <= log.LevelDebug {855 log.Debug("methods generated for %s:%s", e.sname, fmtMappedNames(generatedMethods))856 }857 g.scanImportsNeededForEnt(e)858 return err859}860// typePkgName returns the package name for a type that is from an external package.861// E.g:862// package foo863// "int" => ""864// "foo.Thing" => ""865// "bar.Thing" => "bar"866// "[]bar.Thing" => "bar"867//868func (g *Codegen) typePkgName(t types.Type) string {869 if t, ok := t.(*types.Named); ok {870 if o := t.Obj(); o != nil {871 if pkg := o.Pkg(); pkg != nil && pkg != g.pkg.Types && pkg.Path() != g.pkg.Types.Path() {872 return pkg.Name()873 }874 }875 }876 return ""877}878func (g *Codegen) scanImportsNeededForEnt(e *EntInfo) {879 // collect all unique named types which has package information880 uniqueNamedTypes := make(map[*types.Named]*types.TypeName)881 for _, field := range e.fields {882 if t, ok := field.t.Type.(*types.Named); ok {883 if o := t.Obj(); o != nil {884 if o.Pkg() != nil {885 uniqueNamedTypes[t] = o886 }887 }888 }889 }890 // for each unique named type...891 ePkgPath := g.pkg.Types.Path()892 for _, o := range uniqueNamedTypes {893 pkg := o.Pkg() // note: never nil894 // log.Debug("%v\n o.id=%v, o.name=%v, pkg.name=%s, pkg.path=%q", t,895 // o.Id(), o.Name(), pkg.Name(), pkg.Path())896 pkgPath := pkg.Path()897 if pkgPath != ePkgPath && pkgPath != g.entpkgPath {898 g.imports = append(g.imports, PkgImport{Path: pkgPath})899 }900 }901}902func (g *Codegen) genEntFields(e *EntInfo) {903 // entField* constants for symbolic field indices904 var fieldmap uint64905 if len(e.fields) > 0 {906 g.s("// Symbolic field indices, for use with ent.*FieldChanged methods\n")907 g.s("const (\n")908 for _, field := range e.fields {909 fieldmap |= (1 << field.index)910 g.f(" ent_%s_f_%s\t= %d\n", e.sname, field.sname, field.index)911 }912 g.s(")\n\n")913 }914 g.f("// EntFields returns information about %s fields\n", e.sname)915 g.f("var ent_%s_fields = ent.Fields{\n", e.sname)916 g.f(" Names: []string{\n")917 for _, field := range e.fields {918 g.f(" %#v,\n", field.name)919 }920 g.f(" },\n")921 g.f(" FieldSet:\t0b%b,\n", fieldmap)922 g.f("}\n\n")923 g.f("// EntFields returns information about %s fields\n", e.sname)924 g.f("func (e %s) EntFields() ent.Fields { return ent_%s_fields }\n", e.sname, e.sname)925}926func genFieldmap(e *EntInfo, fields []*EntField) string {927 v := make([]string, len(fields))928 for i, field := range fields {929 v[i] = fmt.Sprintf("1<<ent_%s_f_%s", e.sname, field.sname)930 }931 if len(v) == 1 {932 return v[0]933 }934 return "(" + strings.Join(v, ") | (") + ")"935}936func (g *Codegen) genFindTYPEByINDEX(e *EntInfo, fx *EntFieldIndex) error {937 svar, cvar, rvar, evar, errvar, tmpvar := "s", "c", "r", "e", "err", "v"938 limitvar, flagsarg := "limit", "fl"939 // package names940 var pkgnames map[string]struct{}941 for _, f := range fx.fields {942 if pkgname := g.typePkgName(f.t.Type); pkgname != "" {943 if pkgnames == nil {944 pkgnames = make(map[string]struct{})945 }946 pkgnames[pkgname] = struct{}{}947 }948 }949 // log.Debug("package names: %v", pkgnames)950 // args951 var prevGoType string952 argchunks := make([]string, 0, len(fx.fields))953 argnames := make([]string, 0, len(fx.fields))954 for i, f := range fx.fields {955 goType := g.goTypeName(f.t.Type)956 if prevGoType == goType {957 argchunks = append(argchunks[:i-1], inverseCapitalize(fx.fields[i-1].sname))958 }959 argname := inverseCapitalize(f.sname)960 for {961 if _, ok := pkgnames[argname]; !ok {962 break963 }964 argname = argname + "_"965 }966 argchunks = append(argchunks, argname+" "+goType)967 argnames = append(argnames, argname)968 prevGoType = goType969 if argname == svar {970 svar = "_" + svar971 } else if argname == cvar {972 cvar = "_" + cvar973 } else if argname == rvar {974 rvar = "_" + rvar975 } else if argname == evar {976 evar = "_" + evar977 } else if argname == errvar {978 errvar = "_" + errvar979 } else if argname == tmpvar {980 tmpvar = "_" + tmpvar981 } else if argname == limitvar {982 limitvar = "_" + limitvar983 } else if argname == flagsarg {984 flagsarg = "_" + flagsarg985 }986 }987 // fieldIndices := genFieldmap(e, fx.fields)988 params := strings.Join(argchunks, ", ")989 var argsComment string990 if len(fx.fields) == 1 {991 argsComment = "with " + argnames[0]992 } else {993 argsComment = "matching " + strings.Join(argnames, " AND ")994 }995 // use an optimization where the index query is a single field that is a string or byte slice996 useSingleStringKeyOpt := len(fx.fields) == 1 &&997 (isStringType(fx.fields[0].t.Type) || isByteSliceType(fx.fields[0].t.Type))998 // arg0 is used by useSingleStringKeyOpt and is argnames[0] as []byte999 var arg0 string1000 if useSingleStringKeyOpt {1001 arg0 = argnames[0]1002 if isStringType(fx.fields[0].t.Type) {1003 arg0 = "[]byte(" + arg0 + ")"1004 }1005 }1006 // both load and find needs key encoder code, so generate that up front1007 var keyEncoderCode []byte1008 if !useSingleStringKeyOpt {1009 var b bytes.Buffer1010 fmt.Fprintf(&b, "func(%s ent.Encoder) {\n", cvar)1011 for i, f := range fx.fields {1012 expr, err := g.genFieldEncoder(f, cvar, argnames[i])1013 if err != nil {1014 return err1015 }1016 if len(fx.fields) > 1 {1017 fmt.Fprintf(&b, " %s.Key(%#v)\n", cvar, f.name)1018 }1019 fmt.Fprintf(&b, " %s\n", expr)1020 }1021 b.WriteString(" }")1022 keyEncoderCode = b.Bytes()1023 }1024 //1025 // Load__By__1026 fname := "Load" + e.sname + "By" + capitalize(fx.name)1027 if fx.IsUnique() {1028 g.f("// %s loads %s %s\n", fname, e.sname, argsComment)1029 g.f("func %s(%s ent.Storage, %s, %s ...ent.LookupFlags) (*%s, error)\t{\n",1030 fname, svar, params, flagsarg, e.sname)1031 g.f(" %s := &%s{}\n", evar, e.sname)1032 if useSingleStringKeyOpt {1033 g.f(" %s := ent.LoadEntByIndexKey(%s, %s, &ent_%s_idx[%d], %s, %s)\n",1034 errvar, svar, evar, e.sname, fx.index, arg0, flagsarg)1035 } else {1036 g.f(" %s := ent.LoadEntByIndex(%s, %s, &ent_%s_idx[%d], %s, %d, %s)\n",1037 errvar, svar, evar, e.sname, fx.index, flagsarg, len(fx.fields), keyEncoderCode)1038 }1039 g.f(" return %s, %s\n", evar, errvar)1040 g.s("}\n\n")1041 } else {1042 sliceCast, err := g.getEntSliceCastHelper(e)1043 if err != nil {1044 return err1045 }1046 g.f("// %s loads all %s ents %s\n", fname, e.sname, argsComment)1047 g.f("func %s(%s ent.Storage, %s, %s int, %s ...ent.LookupFlags) ([]*%s, error)\t{\n",1048 fname, svar, params, limitvar, flagsarg, e.sname)1049 g.f(" %s := &%s{}\n", evar, e.sname)1050 if useSingleStringKeyOpt {1051 g.f(" %s, %s := ent.LoadEntsByIndexKey(%s, %s, &ent_%s_idx[%d], %s, %s, %s)\n",1052 rvar, errvar, svar, evar, e.sname, fx.index, arg0, limitvar, flagsarg)1053 } else {1054 g.f(" %s, %s := ent.LoadEntsByIndex(%s, %s, &ent_%s_idx[%d], %s, %s, %d, %s)\n",1055 rvar, errvar,1056 svar, evar, e.sname, fx.index, limitvar, flagsarg, len(fx.fields), keyEncoderCode)1057 }1058 g.f(" return %s(%s), %s\n", sliceCast, rvar, errvar)1059 g.s("}\n\n")1060 }1061 //1062 // Find__By__1063 fname = "Find" + e.sname + "By" + capitalize(fx.name)1064 if fx.IsUnique() {1065 g.f("// %s looks up %s id %s\n", fname, e.sname, argsComment)1066 g.f("func %s(%s ent.Storage, %s, %s ...ent.LookupFlags) (uint64, error)\t{\n",1067 fname, svar, params, flagsarg)1068 if useSingleStringKeyOpt {1069 g.f(" return ent.FindIdByIndexKey(%s, %#v, &ent_%s_idx[%d], %s, %s)\n",1070 svar, e.name, e.sname, fx.index, arg0, flagsarg)1071 } else {1072 g.f(" return ent.FindIdByIndex(%s, %#v, &ent_%s_idx[%d], %s, %d, %s)\n",1073 svar, e.name, e.sname, fx.index, flagsarg, len(fx.fields), keyEncoderCode)1074 }1075 g.s("}\n\n")1076 } else {1077 g.f("// %s looks up %s ids %s\n", fname, e.sname, argsComment)1078 g.f("func %s(%s ent.Storage, %s, %s int, %s ...ent.LookupFlags) ([]uint64, error)\t{\n",1079 fname, svar, params, limitvar, flagsarg)1080 if useSingleStringKeyOpt {1081 g.f(" return ent.FindIdsByIndexKey(%s, %#v, &ent_%s_idx[%d], %s, %s, %s)\n",1082 svar, e.name, e.sname, fx.index, arg0, limitvar, flagsarg)1083 } else {1084 g.f(" return ent.FindIdsByIndex(%s, %#v, &ent_%s_idx[%d], %s, %s, %d, %s)\n",1085 svar, e.name, e.sname, fx.index, limitvar, flagsarg, len(fx.fields), keyEncoderCode)1086 }1087 g.s("}\n\n")1088 }1089 return nil1090}1091func (g *Codegen) getEntSliceCastHelper(e *EntInfo) (string, error) {1092 fname := fmt.Sprintf("ent_%s_slice_cast", e.sname)1093 err := g.getOrBuildHelper(fname, "c", nil,1094 func(typ types.Type, cvar string, buf *bytes.Buffer) error {1095 wf := func(format string, args ...interface{}) {1096 fmt.Fprintf(buf, format, args...)1097 }1098 wf("(s []ent.Ent) []*%s {\n", e.sname)1099 wf(" v := make([]*%s, len(s))\n", e.sname)1100 wf(" for i := 0; i < len(s); i++ {\n")1101 wf(" v[i] = s[i].(*%s)\n", e.sname)1102 wf(" }\n")1103 wf(" return v\n")1104 wf("}\n")1105 return nil1106 })1107 return fname, err1108}1109func (g *Codegen) genEntDecode(e *EntInfo, mname string) error {1110 g.f("\n// %s populates fields from a decoder\n", mname)1111 g.f("func (e *%s) %s(c ent.Decoder) (id, version uint64) {\n", e.sname, mname)1112 g.s(" for {\n")1113 g.s(" switch string(c.Key()) {\n")1114 g.s(" case \"\": return\n")1115 g.s(" case ent.FieldNameId: id = c.Uint(64)\n")1116 g.s(" case ent.FieldNameVersion: version = c.Uint(64)\n")1117 for _, field := range e.fields {1118 g.pushPos(field.pos)1119 g.f(" case %#v:\n", field.name)1120 err := g.codegenDecodeField(field)1121 g.popPos()1122 if err != nil {1123 return err1124 }1125 }1126 g.s(" default: c.Discard()\n")1127 g.s(" }\n")1128 g.s(" }\n")1129 g.s(" return\n")1130 g.s("}\n")1131 return nil1132}1133func (g *Codegen) genEntDecodePartial(e *EntInfo, mname string) error {1134 var indexedFields []*EntField1135 for _, field := range e.fields {1136 if field.storageIndex != nil {1137 indexedFields = append(indexedFields, field)1138 }1139 }1140 g.f("\n// %s is used internally by ent.Storage during updates.\n", mname)1141 g.f("func (e *%s) %s(c ent.Decoder, fields ent.FieldSet) (version uint64) {\n", e.sname, mname)1142 g.f(" for n := %d; n > 0; {\n", len(indexedFields))1143 g.s(" switch string(c.Key()) {\n")1144 g.s(" case \"\": return\n")1145 g.s(" case ent.FieldNameVersion: version = c.Uint(64); continue\n")1146 for _, field := range indexedFields {1147 g.pushPos(field.pos)1148 g.f(" case %#v:\n", field.name)1149 g.s(" n--\n")1150 g.f(" if fields.Has(%d) {\n", field.index)1151 err := g.codegenDecodeField(field)1152 g.s(" continue\n")1153 g.s(" }\n")1154 g.popPos()1155 if err != nil {1156 return err1157 }1158 }1159 g.s(" }\n")1160 g.s(" c.Discard()\n")1161 g.s(" }\n")1162 g.s(" return\n")1163 g.s("}\n")1164 return nil1165}1166// —————————————————————————————————————————————————————————————————————————————————————————1167// collectFieldIndexes builds EntFieldIndex for all indexes defined by field tags.1168// The returned list is sorted on name1169func (g *Codegen) collectFieldIndexes(fields []*EntField) []*EntFieldIndex {1170 // check field tags and pick out fields with an index1171 m := make(map[string]*EntFieldIndex, len(fields))1172 addIndex := func(index *EntFieldIndex) *EntFieldIndex {1173 x := m[index.name]1174 if x == nil {1175 m[index.name] = index1176 x = index1177 } else {1178 x.flags |= index.flags1179 x.fields = append(x.fields, index.fields[0])1180 }1181 return x1182 }1183 for _, field := range fields {1184 if len(field.tags) == 0 {1185 continue1186 }1187 g.pushPos(field.pos)1188 for _, tag := range field.tags {1189 // tag="key=foo=bar" => key="key", val="foo=bar"1190 // tag="key" => key="key", val="fieldname"1191 key, val := tag, field.name1192 if i := strings.IndexByte(key, '='); i != -1 {1193 val = key[i+1:]1194 key = key[:i]1195 }1196 key = strings.ToLower(key)1197 var index *EntFieldIndex1198 switch key {1199 case "index":1200 index = &EntFieldIndex{name: val}1201 case "unique":...

Full Screen

Full Screen

lex.go

Source:lex.go Github

copy

Full Screen

...112 return nil113 }114 return op115}116func (j *json) pushPos(pos Position) {117 j.stackPos = append(j.stackPos, pos)118}119func (j *json) popPos() Position {120 last := len(j.stackPos) - 1121 pos := j.stackPos[last]122 j.stackPos = j.stackPos[:last]123 return pos124}125func (j *json) moveHoriz(bytes int, runes ...int) {126 j.pos = j.pos.incHoriz(bytes, runes...)127 j.curSize = 0128}129func (j *json) getOperator(operator Operator, opPos Position) (any, error) {130 if j.opts.OpFn == nil {131 return nil, fmt.Errorf("unknown operator %q", operator.Name)132 }133 return j.opts.OpFn(operator, opPos)134}135func (j *json) nextToken(lval *yySymType) int {136 if !j.skipWs() {137 return 0138 }139 j.lastTokenPos = j.pos140 r, _ := j.getRune()141 switch r {142 case '"':143 firstPos := j.pos.incHoriz(1)144 s, ok := j.parseString()145 if !ok {146 return 0147 }148 return j.analyzeStringContent(s, firstPos, lval)149 case 'r': // raw string, aka r!str! or r<str> (ws possible bw r & start delim)150 if !j.skipWs() {151 j.fatal("cannot find r start delimiter")152 return 0153 }154 firstPos := j.pos.incHoriz(1)155 s, ok := j.parseRawString()156 if !ok {157 return 0158 }159 return j.analyzeStringContent(s, firstPos, lval)160 case 'n': // null161 if j.remain() >= 4 && bytes.Equal(j.buf[j.pos.bpos+1:j.pos.bpos+4], []byte(`ull`)) {162 j.skip(3)163 lval.value = nil164 return NULL165 }166 case 't': // true167 if j.remain() >= 4 && bytes.Equal(j.buf[j.pos.bpos+1:j.pos.bpos+4], []byte(`rue`)) {168 j.skip(3)169 lval.value = true170 return TRUE171 }172 case 'f': // false173 if j.remain() >= 5 && bytes.Equal(j.buf[j.pos.bpos+1:j.pos.bpos+5], []byte(`alse`)) { //nolint: misspell174 j.skip(4)175 lval.value = false176 return FALSE177 }178 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',179 '+', '.': // '+' & '.' are not normally accepted by JSON spec180 n, ok := j.parseNumber()181 if !ok {182 return 0183 }184 lval.value = n185 return NUMBER186 case '$':187 var dollarToken string188 end := bytes.IndexAny(j.buf[j.pos.bpos+1:], delimiters)189 if end >= 0 {190 dollarToken = string(j.buf[j.pos.bpos+1 : j.pos.bpos+1+end])191 } else {192 dollarToken = string(j.buf[j.pos.bpos+1:])193 }194 if dollarToken == "" {195 return '$'196 }197 token, value := j.parseDollarToken(dollarToken, j.pos, false)198 if token == OPERATOR {199 lval.string = value.(string)200 return OPERATOR201 }202 lval.value = value203 j.moveHoriz(1+len(dollarToken), 1+utf8.RuneCountInString(dollarToken))204 return token205 default:206 if r >= 'A' && r <= 'Z' {207 operator, ok := j.parseOperator()208 if !ok {209 return 0210 }211 j.pushPos(j.lastTokenPos)212 lval.string = operator213 return OPERATOR214 }215 }216 return int(r)217}218func hex(b []byte) (rune, bool) {219 var r rune220 for i := 0; i < 4; i++ {221 r <<= 4222 switch {223 case b[i] >= '0' && b[i] <= '9':224 r += rune(b[i]) - '0'225 case b[i] >= 'a' && b[i] <= 'f':226 r += rune(b[i]) - 'a' + 10227 case b[i] >= 'A' && b[i] <= 'F':228 r += rune(b[i]) - 'A' + 10229 default:230 return 0, false231 }232 }233 return r, true234}235func (j *json) parseString() (string, bool) {236 // j.buf[j.pos.bpos] == '"' → caller responsibility237 var b *strings.Builder238 from := j.pos.bpos + 1239 savePos := j.pos240 appendBuffer := func(r rune) {241 if b == nil {242 b = &strings.Builder{}243 b.Write(j.buf[from : j.pos.bpos-1])244 }245 b.WriteRune(r)246 }247str:248 for {249 r, ok := j.getRune()250 if !ok {251 break252 }253 switch r {254 case '"':255 if b == nil {256 return string(j.buf[from:j.pos.bpos]), true257 }258 return b.String(), true259 case '\\':260 r, ok := j.getRune()261 if !ok {262 break str263 }264 switch r {265 case '"', '\\', '/':266 appendBuffer(r)267 case 'b':268 appendBuffer('\b')269 case 'f':270 appendBuffer('\f')271 case 'n':272 appendBuffer('\n')273 case 'r':274 appendBuffer('\r')275 case 't':276 appendBuffer('\t')277 case 'u':278 if j.remain() >= 5 {279 r, ok = hex(j.buf[j.pos.bpos+1 : j.pos.bpos+5])280 if ok {281 appendBuffer(r)282 j.pos = j.pos.incHoriz(4)283 break284 }285 }286 fallthrough287 default:288 j.fatal("invalid escape sequence")289 return "", false290 }291 default: //nolint: gocritic292 if r < ' ' || r > utf8.MaxRune {293 j.fatal("invalid character in string")294 return "", false295 }296 fallthrough297 case '\n', '\r', '\t': // not normally accepted by JSON spec298 if b != nil {299 b.WriteRune(r)300 }301 }302 }303 j.fatal("unterminated string", savePos)304 return "", false305}306func (j *json) parseRawString() (string, bool) {307 // j.buf[j.pos.bpos] == first non-ws rune after 'r' → caller responsibility308 savePos := j.pos309 startDelim, _ := j.getRune() // cannot fail, caller called j.skipWs()310 var endDelim rune311 switch startDelim {312 case '(':313 endDelim = ')'314 case '{':315 endDelim = '}'316 case '[':317 endDelim = ']'318 case '<':319 endDelim = '>'320 default:321 if startDelim == '_' ||322 (!unicode.IsPunct(startDelim) && !unicode.IsSymbol(startDelim)) {323 j.fatal(fmt.Sprintf("invalid r delimiter %q, should be either a punctuation or a symbol rune, excluding '_'",324 startDelim))325 return "", false326 }327 endDelim = startDelim328 }329 from := j.pos.bpos + j.curSize330 for innerDelim := 0; ; {331 r, ok := j.getRune()332 if !ok {333 break334 }335 switch r {336 case startDelim:337 if startDelim == endDelim {338 return string(j.buf[from:j.pos.bpos]), true339 }340 innerDelim++341 case endDelim:342 if innerDelim == 0 {343 return string(j.buf[from:j.pos.bpos]), true344 }345 innerDelim--346 case '\n', '\r', '\t': // accept these raw bytes347 default:348 if r < ' ' || r > utf8.MaxRune {349 j.fatal("invalid character in raw string")350 return "", false351 }352 }353 }354 j.fatal("unterminated raw string", savePos)355 return "", false356}357// analyzeStringContent checks whether s contains $ prefix or not. If358// yes, it tries to parse it.359func (j *json) analyzeStringContent(s string, strPos Position, lval *yySymType) int {360 if len(s) <= 1 || !strings.HasPrefix(s, "$") {361 lval.string = s362 return STRING363 }364 // Double $$ at start of strings escape a $365 if strings.HasPrefix(s[1:], "$") {366 lval.string = s[1:]367 return STRING368 }369 // Check for placeholder ($1 or $name) or operator call as $^Empty370 // or $^Re(q<\d+>)371 token, value := j.parseDollarToken(s[1:], strPos, true)372 // in string, j.parseDollarToken can never return an OPERATOR373 // token. In case an operator is embedded in string, a SUB_PARSER is374 // returned instead.375 lval.value = value376 return token377}378const (379 numInt = 1 << iota380 numFloat381 numGoExt382)383var numBytes = [...]uint8{384 '+': numInt, '-': numInt,385 '0': numInt,386 '1': numInt,387 '2': numInt,388 '3': numInt,389 '4': numInt,390 '5': numInt,391 '6': numInt,392 '7': numInt,393 '8': numInt,394 '9': numInt,395 '_': numGoExt,396 // bases 2, 8, 16397 'b': numInt, 'B': numInt, 'o': numInt, 'O': numInt, 'x': numInt, 'X': numInt,398 'a': numInt, 'A': numInt,399 'c': numInt, 'C': numInt,400 'd': numInt, 'D': numInt,401 'e': numInt | numFloat, 'E': numInt | numFloat,402 'f': numInt, 'F': numInt,403 // floats404 '.': numFloat, 'p': numFloat, 'P': numFloat,405}406func (j *json) parseNumber() (float64, bool) {407 // j.buf[j.pos.bpos] == '[-+0-9.]' → caller responsibility408 numKind := numBytes[j.buf[j.pos.bpos]]409 i := j.pos.bpos + 1410 for l := len(j.buf); i < l; i++ {411 b := int(j.buf[i])412 if b >= len(numBytes) || numBytes[b] == 0 {413 break414 }415 numKind |= numBytes[b]416 }417 s := string(j.buf[j.pos.bpos:i])418 var (419 f float64420 err error421 )422 // Differentiate float/int parsing to accept old octal notation:423 // 0600 → 384 as int64, but 600 as float64424 if (numKind & numFloat) != 0 {425 // strconv.ParseFloat does not handle "_"426 var bf *big.Float427 bf, _, err = new(big.Float).Parse(s, 0)428 if err == nil {429 f, _ = bf.Float64()430 }431 } else { // numInt and/or numGoExt432 var int int64433 int, err = strconv.ParseInt(s, 0, 64)434 if err == nil {435 f = float64(int)436 }437 }438 if err != nil {439 j.fatal("invalid number")440 return 0, false441 }442 j.curSize = 0443 j.pos = j.pos.incHoriz(i - j.pos.bpos)444 return f, true445}446// parseDollarToken parses a $123 or $tag or $^Operator or447// $^Operator(PARAMS…) token. dollarToken is never empty, does not448// contain '$' and dollarPos is the '$' position.449func (j *json) parseDollarToken(dollarToken string, dollarPos Position, inString bool) (int, any) {450 firstRune, _ := utf8.DecodeRuneInString(dollarToken)451 // Test for $123452 if firstRune >= '0' && firstRune <= '9' {453 np, err := strconv.ParseUint(dollarToken, 10, 64)454 if err != nil {455 j.error("invalid numeric placeholder", dollarPos)456 return PLACEHOLDER, nil // continue parsing457 }458 if np == 0 {459 j.error(460 fmt.Sprintf(`invalid numeric placeholder "$%s", it should start at "$1"`, dollarToken),461 dollarPos)462 return PLACEHOLDER, nil // continue parsing463 }464 if numParams := len(j.opts.Placeholders); np > uint64(numParams) {465 switch numParams {466 case 0:467 j.error(468 fmt.Sprintf(`numeric placeholder "$%s", but no params given`, dollarToken),469 dollarPos)470 case 1:471 j.error(472 fmt.Sprintf(`numeric placeholder "$%s", but only one param given`, dollarToken),473 dollarPos)474 default:475 j.error(476 fmt.Sprintf(`numeric placeholder "$%s", but only %d params given`,477 dollarToken, numParams),478 dollarPos)479 }480 return PLACEHOLDER, nil // continue parsing481 }482 return PLACEHOLDER, j.opts.Placeholders[np-1]483 }484 // Test for operator call $^Operator or $^Operator(…)485 if firstRune == '^' {486 nextRune, _ := utf8.DecodeRuneInString(dollarToken[1:])487 if nextRune < 'A' || nextRune > 'Z' {488 j.error(`$^ must be followed by an operator name`, dollarPos)489 if inString {490 return SUB_PARSER, nil // continue parsing491 }492 return OPERATOR, "" // continue parsing493 }494 if inString {495 jr := json{496 buf: []byte(dollarToken[1:]),497 pos: Position{498 Pos: dollarPos.Pos + 2,499 Line: dollarPos.Line,500 Col: dollarPos.Col + 2,501 },502 opts: j.opts,503 }504 if !jr.parse() {505 j.errs = append(j.errs, jr.errs...)506 return SUB_PARSER, nil // continue parsing507 }508 return SUB_PARSER, jr.value509 }510 j.moveHoriz(2)511 j.lastTokenPos = j.pos512 operator, ok := j.parseOperator()513 if !ok {514 return OPERATOR, ""515 }516 j.pushPos(j.lastTokenPos)517 return OPERATOR, operator518 }519 // Test for $tag520 err := util.CheckTag(dollarToken)521 if err != nil {522 j.error(523 fmt.Sprintf(`bad placeholder "$%s"`, dollarToken),524 dollarPos)525 return PLACEHOLDER, nil // continue parsing526 }527 op, ok := j.opts.PlaceholdersByName[dollarToken]528 if !ok {529 j.error(530 fmt.Sprintf(`unknown placeholder "$%s"`, dollarToken),...

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 var jsonBlob = []byte(`[4 {"Name": "Platypus", "Order": "Monotremata"},5 {"Name": "Quoll", "Order": "Dasyuromorphia"}6 type Animal struct {7 }8 err := json.Unmarshal(jsonBlob, &animals)9 if err != nil {10 fmt.Println("error:", err)11 }12 fmt.Printf("%+v", animals)13}14[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]15import (16func main() {17 var jsonBlob = []byte(`[18 {"Name": "Platypus", "Order": "Monotremata"},19 {"Name": "Quoll", "Order": "Dasyuromorphia"}20 type Animal struct {21 }22 var animals []map[string]interface{}23 err := json.Unmarshal(jsonBlob, &animals)24 if err != nil {25 fmt.Println("error:", err)26 }27 fmt.Printf("%+v", animals)28}29[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]30import (31func main() {32 var jsonBlob = []byte(`[33 {"Name": "Platypus", "Order": "Monotremata"},34 {"Name": "Quoll", "Order": "Dasyuromorphia"}35 type Animal struct {36 }37 var animals []interface{}38 err := json.Unmarshal(jsonBlob, &animals)39 if err != nil {40 fmt.Println("error:", err)41 }

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 var jsonBlob = []byte(`[4 {"Name": "Platypus", "Order": "Monotremata"},5 {"Name": "Quoll", "Order": "Dasyuromorphia"}6 var data []interface{}7 err := json.Unmarshal(jsonBlob, &data)8 if err != nil {9 fmt.Println("error:", err)10 }11 fmt.Printf("%+v12}13[{map[Name:Platypus Order:Monotremata]} {map[Name:Quoll Order:Dasyuromorphia]}]14fmt.Println(data[0]["Order"])15cannot use data[0]["Order"] (type interface {}) as type string in argument to fmt.Println

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 enc := json.NewEncoder(os.Stdout)4 enc.SetIndent("", " ")5 enc.Encode(map[string]string{6 })7}8import (9func main() {10 enc := json.NewEncoder(os.Stdout)11 enc.SetIndent("", " ")12 enc.Encode(map[string]string{13 })14}15import (16func main() {17 enc := json.NewEncoder(os.Stdout)18 enc.SetIndent("", " ")19 enc.Encode(map[string]string{20 })21}22import (23func main() {24 enc := json.NewEncoder(os.Stdout)25 enc.SetIndent("", " ")26 enc.Encode(map[string]string{27 })28}29import (30func main() {31 enc := json.NewEncoder(os.Stdout)32 enc.SetIndent("", " ")33 enc.Encode(map[string]string{34 })35}36import (37func main() {38 enc := json.NewEncoder(os.Stdout)39 enc.SetIndent("", " ")40 enc.Encode(map[string]string{41 })42}

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 json := json.NewEncoder(os.Stdout)4 json.Encode([]string{"foo", "bar"})5 json.Encode(map[string]int{"foo": 1, "bar": 2})6 json.Encode(map[string]int{"foo": 1, "bar": 2})7}8import (9func main() {10 json := json.NewEncoder(os.Stdout)11 json.Encode([]string{"foo", "bar"})12 json.Encode(map[string]int{"foo": 1, "bar": 2})13 json.Encode(map[string]int{"foo": 1, "bar": 2})14}15import (16func main() {17 json := json.NewEncoder(os.Stdout)18 json.Encode([]string{"foo", "bar"})19 json.Encode(map[string]int{"foo": 1, "bar": 2})20 json.Encode(map[string]int{"foo": 1, "bar": 2})21}22import (23func main() {24 json := json.NewEncoder(os.Stdout)25 json.Encode([]string{"foo", "bar"})26 json.Encode(map[string]int{"foo": 1, "bar": 2})27 json.Encode(map[string]int{"foo": 1, "bar": 2})28}29import (30func main() {31 json := json.NewEncoder(os.Stdout)32 json.Encode([]string{"foo", "bar"})33 json.Encode(map[string]int{"foo": 1, "bar": 2})34 json.Encode(map[string]int{"foo": 1, "bar": 2})35}36import (37func main() {38 json := json.NewEncoder(os.Stdout)39 json.Encode([]string{"foo", "bar"})40 json.Encode(map[string]int{"foo": 1, "bar": 2})41 json.Encode(map[string]int{"

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2type Person struct {3}4func main() {5 people := []Person{6 Person{"James", "Bond", 20},7 Person{"Miss", "Moneypenny", 18},8 }9 fmt.Println(people)10 err := json.NewEncoder(os.Stdout).Encode(people)11 if err != nil {12 fmt.Println(err)13 }14}15[{"First":"James","Last":"Bond","Age":20},{"First":"Miss","Last":"Moneypenny","Age":18}]16[{"First":"James","Last":"Bond","Age":20},{"First":"Miss","Last":"Moneypenny","Age":18}]17import (18type Person struct {19}20func main() {21 people := []Person{22 Person{"James", "Bond", 20},23 Person{"Miss", "Moneypenny", 18},24 }25 fmt.Println(people)26 jsonFile, err := os.Create("people.json")27 if err != nil {28 fmt.Println(err)29 }30 defer jsonFile.Close()31 err = json.NewEncoder(jsonFile).Encode(people)32 if err != nil {33 fmt.Println(err)34 }35}36[{"First":"James","Last":"Bond","Age":20},{"First":"Miss","Last":"Moneyp

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 js, err := simplejson.NewJson([]byte(`{"key": "value"}`))4 if err != nil {5 panic(err)6 }7 js.Get("key").PushPos(1, 2)8 fmt.Println(js)9}10{"key":[1,2,"value"]}11PushPath() method12import (13func main() {14 js, err := simplejson.NewJson([]byte(`{"key": "value"}`))15 if err != nil {16 panic(err)17 }18 js.Get("key").PushPath([]string{"path", "to", "array"}, 2)19 fmt.Println(js)20}21{"key":{"path":{"to":{"array":[2]}},"value"}}22Set() method23import (24func main() {25 js, err := simplejson.NewJson([]byte(`{"key": "value"}`))26 if err != nil {27 panic(err)28 }29 js.Get("key").Set("path.to.array", 2)30 fmt.Println(js)31}32{"key":{"path":{"to":{"array":2}},"value"}}33Set() method sets the value at the

Full Screen

Full Screen

pushPos

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 j := json.NewEncoder(nil)4 j.PushPos(s, 'o')5 fmt.Println(j.Pos())6}7Golang | json.MarshalIndent() method with Example8Golang | json.Unmarshal() method with Example9Golang | json.UnmarshalIndent() method with Example10Golang | json.NewEncoder() method with Example11Golang | json.NewDecoder() method with Example12Golang | json.Compact() method with Example13Golang | json.Indent() method with Example14Golang | json.Valid() method with Example15Golang | json.ValidIndent() method with Example16Golang | json.NewEncoder() method with Example17Golang | json.NewDecoder() method with Example18Golang | json.Compact() method with Example19Golang | json.Indent() method with Example20Golang | json.Valid() method with Example21Golang | json.ValidIndent() method with Example22Golang | json.RawMessage() method with Example23Golang | json.Marshal() method with Example24Golang | json.MarshalIndent() method with Example25Golang | json.Unmarshal() method with Example

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful