func printStructDefinition(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error { if typ.Description != "" { g.Println("// ", typ.Description) } g.Println("type ", system.GoName(typ.Id.Name), " struct {") { if !typ.Basic { g.Println("*", g.SprintRef("kego.io/system", system.GoName("object"))) } embedsSortable := system.SortableReferences(typ.Embed) sort.Sort(embedsSortable) embeds := []*system.Reference(embedsSortable) for _, embed := range embeds { g.Println("*", builder.Reference(embed.Package, system.GoName(embed.Name), env.Path, g.Imports.Add)) } for _, nf := range typ.SortedFields() { b := nf.Rule.(system.ObjectInterface).GetObject(nil) if b.Description != "" { g.Println("// ", b.Description) } descriptor, err := builder.FieldTypeDefinition(ctx, nf.Name, nf.Rule, env.Path, g.Imports.Add) if err != nil { return kerr.Wrap("GDSKJDEKQD", err) } g.Println(system.GoName(nf.Name), " ", descriptor) } } g.Println("}") return nil }
func (n *Node) setType(ctx context.Context, t *system.Type) error { if t == nil { n.Type = nil n.JsonType = system.J_NULL n.UnderlyingRule = nil n.UnderlyingInnerType = nil return nil } if t.Interface { return kerr.New("VHOSYBMDQL", "Can't set type to an interface - must be concrete type.") } n.Type = t n.JsonType = t.NativeJsonType(ctx) if t.Alias != nil { rw := system.WrapRule(ctx, t.Alias) n.UnderlyingRule = rw uit := rw.InnerType(ctx) for uit.Alias != nil { uit = system.WrapRule(ctx, uit.Alias).InnerType(ctx) } n.UnderlyingInnerType = uit } else { n.UnderlyingRule = system.WrapEmptyRule(ctx, t) n.UnderlyingInnerType = t } return nil }
func printValueMethod(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error { name := system.GoName(typ.Id.Name) gotype, err := typ.NativeValueGolangType() if err != nil { return kerr.Wrap("LUHQRVBQRT", err) } g.Println("func (o *", name, ") Value() ", gotype, "{") { g.Println("return ", gotype, "(*o)") } g.Println("}") return nil }
func printInterfaceDefinition(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) { g.Println("type ", system.GoInterfaceName(typ.Id.Name), " interface {") { g.Println("Get", system.GoName(typ.Id.Name), "(ctx ", builder.Reference("context", "Context", env.Path, g.Imports.Add), ") ", typ.PassedAsPointerString(ctx), system.GoName(typ.Id.Name)) } g.Println("}") }
func printInterfaceImplementation(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) { g.Println("func (o ", typ.PassedAsPointerString(ctx), system.GoName(typ.Id.Name), ") Get", system.GoName(typ.Id.Name), "(ctx ", builder.Reference("context", "Context", env.Path, g.Imports.Add), ") ", typ.PassedAsPointerString(ctx), system.GoName(typ.Id.Name), " {") { g.Println("return o") } g.Println("}") }
func printInterfaceUnpacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) { // if type kind is native, also accept bare json native // if type kind is array, also accept bare json array typeName := system.GoName(typ.Id.Name) var interfaceName string if typ.Interface { interfaceName = system.GoName(typ.Id.Name) } else { interfaceName = system.GoInterfaceName(typ.Id.Name) } fmtPkg := g.Imports.Add("fmt") g.Println("func Unpack", interfaceName, "(ctx ", g.SprintRef("context", "Context"), ", in ", g.SprintRef("kego.io/system", "Packed"), ") (", interfaceName, ", error) {") { g.Println("switch in.Type() {") { g.Println("case ", g.SprintRef("kego.io/system", "J_MAP"), ":") { unknownTypeFunc := g.SprintFunctionCall("kego.io/system", "UnpackUnknownType", "ctx", "in", "true", strconv.Quote(typ.Id.Package), strconv.Quote(typ.Id.Name)) g.Println("i, err := ", unknownTypeFunc) g.Println("if err != nil {") { g.Println("return nil, err") } g.Println("}") g.Println("ob, ok := i.(", interfaceName, ")") g.Println("if !ok {") { g.Println("return nil, ", fmtPkg, `.Errorf("%T does not implement `, interfaceName, `", i)`) } g.Println("}") g.Println("return ob, nil") } switch typ.NativeJsonType(ctx) { // We don't include J_MAP in here. case system.J_STRING, system.J_NUMBER, system.J_BOOL, system.J_ARRAY: switch typ.NativeJsonType(ctx) { case system.J_STRING: g.Println("case ", g.SprintRef("kego.io/system", "J_STRING"), ":") case system.J_NUMBER: g.Println("case ", g.SprintRef("kego.io/system", "J_NUMBER"), ":") case system.J_BOOL: g.Println("case ", g.SprintRef("kego.io/system", "J_BOOL"), ":") case system.J_ARRAY: g.Println("case ", g.SprintRef("kego.io/system", "J_ARRAY"), ":") } g.Println("ob := new(", typeName, ")") g.Println("if err := ob.Unpack(ctx, in, false); err != nil {") { g.Println("return nil, err") } g.Println("}") g.Println("return ob, nil") } g.Println("default:") { g.Println("return nil, ", fmtPkg, `.Errorf("Unsupported json type %s when unpacking into `, interfaceName, `.", in.Type())`) } } g.Println("}") } g.Println("}") }
func printUnpacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error { name := system.GoName(typ.Id.Name) fmtPkg := g.Imports.Add("fmt") g.Println("func (v *", name, ") Unpack(ctx ", g.SprintRef("context", "Context"), ", in ", g.SprintRef("kego.io/system", "Packed"), ", iface bool) error {") { g.Println("if in == nil || in.Type() == ", g.SprintRef("kego.io/system", "J_NULL"), " {") { g.Println("return nil") } g.Println("}") kind, _ := typ.Kind(ctx) switch kind { case system.KindStruct: structType := typ if typ.Alias != nil { structType = system.WrapRule(ctx, typ.Alias).Parent } for _, embedRef := range structType.AllEmbeds() { embedType, ok := system.GetTypeFromCache(ctx, embedRef.Package, embedRef.Name) if !ok { return kerr.New("IOEEVJCDPU", "Type %s not found", embedRef.String()) } embedName := system.GoName(embedRef.Name) embedTypeName := builder.Reference(embedType.Id.Package, system.GoName(embedType.Id.Name), env.Path, g.Imports.Add) g.Println("if v.", embedName, " == nil {") { g.Println("v.", embedName, " = new(", embedTypeName, ")") } g.Println("}") g.Println("if err := v.", embedName, ".Unpack(ctx, in, false); err != nil {") { g.Println("return err") } g.Println("}") if embedRef.Package == "kego.io/system" && embedRef.Name == "object" { g.Println("if err := v.Object.InitializeType(", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), "); err != nil {") { g.Println("return err") } g.Println("}") } } for _, f := range structType.SortedFields() { g.Println("if field, ok := in.Map()[", strconv.Quote(f.Name), "]; ok && field.Type() != ", g.SprintRef("kego.io/system", "J_NULL"), " {") { in := "field" out := "ob0" depth := 0 if err := printUnpackCode(ctx, env, g, in, out, depth, f.Rule); err != nil { return kerr.Wrap("QLARKEBDBJ", err) } g.Println("v.", system.GoName(f.Name), " = ", out) } if dr, ok := f.Rule.(system.DefaultRule); ok && dr.GetDefault() != nil { g.Println("} else {") { b, err := json.Marshal(dr.GetDefault()) if err != nil { return kerr.Wrap("DLOUEHXVJF", err) } in := g.SprintFunctionCall("kego.io/system", "Pack", string(b)) out := "ob0" depth := 0 if err := printUnpackCode(ctx, env, g, in, out, depth, f.Rule); err != nil { return kerr.Wrap("UOWRFWSTNT", err) } g.Println("v.", system.GoName(f.Name), " = ", out) } g.Println("}") } else { g.Println("}") } } case system.KindValue: g.Println("if in.Type() == ", g.SprintRef("kego.io/system", "J_MAP"), " {") { g.Println("in = in.Map()[\"value\"]") } g.Println("}") switch typ.NativeJsonType(ctx) { case system.J_BOOL: g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_BOOL"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a bool.", in.Type())`) } g.Println("}") g.Println("*v = ", name, "(in.Bool())") case system.J_STRING: g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_STRING"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a string.", in.Type())`) } g.Println("}") g.Println("*v = ", name, "(in.String())") case system.J_NUMBER: g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_NUMBER"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a number.", in.Type())`) } g.Println("}") g.Println("*v = ", name, "(in.Number())") default: panic(fmt.Sprintf("invalid type kind: %s, json native: %s", kind, typ.NativeJsonType(ctx))) } case system.KindArray: g.Println("if in.Type() == ", g.SprintRef("kego.io/system", "J_MAP"), " {") { g.Println("in = in.Map()[\"value\"]") } g.Println("}") g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_ARRAY"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking an array.", in.Type())`) } g.Println("}") in := "in" out := "ob0" depth := 0 if err := printUnpackCode(ctx, env, g, in, out, depth, typ.Alias); err != nil { return kerr.Wrap("VELYRXXGMC", err) } g.Println("*v = ", out) case system.KindMap: g.Println("if iface {") { g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_MAP"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a map.", in.Type())`) } g.Println("}") g.Println("in = in.Map()[\"value\"]") } g.Println("}") g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_MAP"), " {") { g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking an array.", in.Type())`) } g.Println("}") in := "in" out := "ob0" depth := 0 if err := printUnpackCode(ctx, env, g, in, out, depth, typ.Alias); err != nil { return kerr.Wrap("TNEIUAFUNY", err) } g.Println("*v = ", out) } } g.Println("return nil") g.Println("}") return nil }
func printRepacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error { name := system.GoName(typ.Id.Name) context_Context := g.SprintRef("context", "Context") system_JsonType := g.SprintRef("kego.io/system", "JsonType") ptr := typ.PassedAsPointerString(ctx) v := "v" if typ.PassedAsPointer(ctx) { v = "(*v)" } g.Println("func (v ", ptr, name, ") Repack(ctx ", context_Context, ") (data interface{}, typePackage string, typeName string, jsonType ", system_JsonType, ", err error) {") { g.Println("if v == nil {") { system_J_NULL := g.SprintRef("kego.io/system", "J_NULL") g.Println("return nil, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", system_J_NULL, ", nil") } g.Println("}") jtype := typ.NativeJsonType(ctx) var jsonType string switch jtype { case system.J_NUMBER: jsonType = g.SprintRef("kego.io/system", "J_NUMBER") case system.J_STRING: jsonType = g.SprintRef("kego.io/system", "J_STRING") case system.J_BOOL: jsonType = g.SprintRef("kego.io/system", "J_BOOL") case system.J_MAP: jsonType = g.SprintRef("kego.io/system", "J_MAP") case system.J_OBJECT: jsonType = g.SprintRef("kego.io/system", "J_OBJECT") case system.J_ARRAY: jsonType = g.SprintRef("kego.io/system", "J_ARRAY") case system.J_NULL: jsonType = g.SprintRef("kego.io/system", "J_NULL") } kind, _ := typ.Kind(ctx) switch kind { case system.KindStruct: g.Println("m := map[string]interface{}{}") structType := typ if typ.Alias != nil { structType = system.WrapRule(ctx, typ.Alias).Parent } for _, embedRef := range structType.AllEmbeds() { embedName := system.GoName(embedRef.Name) g.Println("if v.", embedName, " != nil {") { g.Println("ob, _, _, _, err := v.", embedName, ".Repack(ctx)") g.Println("if err != nil {") { g.Println(`return nil, "", "", "", err`) } g.Println("}") g.Println("for key, val := range ob.(map[string]interface{}) {") { g.Println("m[key] = val") } g.Println("}") } g.Println("}") } for _, f := range structType.SortedFields() { fieldRule := system.WrapRule(ctx, f.Rule) fieldName := system.GoName(f.Name) fieldType := fieldRule.Parent kind, alias := fieldRule.Kind(ctx) switch { case kind == system.KindStruct || alias: g.Println("if v.", fieldName, " != nil {") { if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil { return kerr.Wrap("WSARHJIFHS", err) } g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0") } g.Println("}") case kind == system.KindValue: switch fieldType.NativeJsonType(ctx) { case system.J_STRING: g.Println("if v.", fieldName, " != \"\" {") case system.J_NUMBER: g.Println("if v.", fieldName, " != 0.0 {") case system.J_BOOL: g.Println("if v.", fieldName, " != false {") } { if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil { return kerr.Wrap("YYDYVIMXPM", err) } g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0") } g.Println("}") case kind == system.KindArray || kind == system.KindMap || kind == system.KindInterface: g.Println("if v.", fieldName, " != nil {") { if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil { return kerr.Wrap("YSFPHQTBNA", err) } g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0") } g.Println("}") } } g.Println("return m, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil") case system.KindValue: outer := typ inner := typ if typ.Alias != nil { inner = system.WrapRule(ctx, typ.Alias).Parent } switch inner.NativeJsonType(ctx) { case system.J_STRING: g.Println("if v != nil {") { g.Println("return string(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") } g.Println("}") g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") case system.J_NUMBER: g.Println("if v != nil {") { g.Println("return float64(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") } g.Println("}") g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") case system.J_BOOL: g.Println("if v != nil {") { g.Println("return bool(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") } g.Println("}") g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil") } case system.KindArray: if err := printRepackCode(ctx, env, g, v, "ob0", 0, typ.Alias, false); err != nil { return kerr.Wrap("SYKLQKLCEO", err) } g.Println("return ob0, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil") case system.KindMap: if err := printRepackCode(ctx, env, g, v, "ob0", 0, typ.Alias, false); err != nil { return kerr.Wrap("HBSGXLGKCD", err) } g.Println("return ob0, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil") } } g.Println("}") return nil }