Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
hqc19907228 authored Sep 15, 2021
2 parents 04f36c5 + f6d85e8 commit a6ea791
Show file tree
Hide file tree
Showing 25 changed files with 1,007 additions and 1,625 deletions.
26 changes: 14 additions & 12 deletions cmd/definitions/gen_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,29 @@ func generateFunc(ns *Namespace, path string) {

nsNameP := templateutils.ToPascal(ns.Name)

for _, fn := range ns.Funcs {
for _, fn := range ns.ParsedFunctions() {
if fn.Implemented {
continue
}

fnNameC := templateutils.ToCamel(fn.Name)
fnNameP := templateutils.ToPascal(fn.Name)

if fn.Local {
op := fn.GetOperation()

if op.Local {
gfn := f.NewFunction(fnNameC).
WithReceiver("s", "*"+nsNameP)
for _, v := range fn.Params {
for _, v := range op.ParsedParams() {
// We need to remove pair from generated functions.
if v.Type() == "...Pair" {
if v.Type == "...Pair" {
continue
}
gfn.AddParameter(v.Name, v.Type())
gfn.AddParameter(v.Name, v.Type)
}
gfn.AddParameter("opt", "pair"+nsNameP+fnNameP)
for _, v := range fn.Results {
gfn.AddResult(v.Name, v.Type())
for _, v := range op.ParsedResults() {
gfn.AddResult(v.Name, v.Type)
}
gfn.AddBody(gg.S(`panic("not implemented")`))
continue
Expand All @@ -43,16 +45,16 @@ func generateFunc(ns *Namespace, path string) {
gfn := f.NewFunction(fnNameC).
WithReceiver("s", "*"+nsNameP)
gfn.AddParameter("ctx", "context.Context")
for _, v := range fn.Params {
for _, v := range op.ParsedParams() {
// We need to remove pair from generated functions.
if v.Type() == "...Pair" {
if v.Type == "...Pair" {
continue
}
gfn.AddParameter(v.Name, v.Type())
gfn.AddParameter(v.Name, v.Type)
}
gfn.AddParameter("opt", "pair"+nsNameP+fnNameP)
for _, v := range fn.Results {
gfn.AddResult(v.Name, v.Type())
for _, v := range op.ParsedResults() {
gfn.AddResult(v.Name, v.Type)
}
gfn.AddBody(`panic("not implemented")`)
continue
Expand Down
123 changes: 62 additions & 61 deletions cmd/definitions/gen_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,80 +15,81 @@ func generateInfo(data *Data, path string) {
f.AddPackage("types")
f.NewImport().AddPath("fmt")

for serviceName, infos := range data.InfosMap {
serviceNameC := templateutils.ToCamel(serviceName)
serviceNameP := templateutils.ToPascal(serviceName)
serviceNameK := templateutils.ToKebab(serviceName)
serviceName := "storage-meta"
infos := data.StorageMeta()

// Generate field bits
f.AddLineComment("Field index in %s bit", serviceNameC)
consts := f.NewConst()
for k, v := range infos {
consts.AddField(
gg.S("%sIndex%s",
serviceNameC, templateutils.ToPascal(v.Name)),
gg.S("1<<%d", k),
)
}
serviceNameC := templateutils.ToCamel(serviceName)
serviceNameP := templateutils.ToPascal(serviceName)
serviceNameK := templateutils.ToKebab(serviceName)

// Generate struct
st := f.NewStruct(serviceNameP)
for _, v := range infos {
st.AddField(v.TypeName(), v.Type())
}
st.AddLine()
st.AddLineComment("bit used as a bitmap for object value, 0 means not set, 1 means set")
st.AddField("bit", "uint64")
st.AddField("m", "map[string]interface{}")
// Generate field bits
f.AddLineComment("Field index in %s bit", serviceNameC)
consts := f.NewConst()
for k, v := range infos {
consts.AddField(
gg.S("%sIndex%s",
serviceNameC, templateutils.ToPascal(v.Name)),
gg.S("1<<%d", k),
)
}

// Generate struct
st := f.NewStruct(serviceNameP)
for _, v := range infos {
st.AddField(v.TypeName(), v.Type)
}
st.AddLine()
st.AddLineComment("bit used as a bitmap for object value, 0 means not set, 1 means set")
st.AddField("bit", "uint64")
st.AddField("m", "map[string]interface{}")

// Generate Get/Set functions.
for _, v := range infos {
// If the value is export, we don't need to generate MustGetXxxx
if v.Export {
f.NewFunction("Get"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddResult("", v.Type()).
AddBody(gg.Return("m." + v.TypeName()))
f.NewFunction("Set"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddParameter("v", v.Type()).
AddResult("", "*"+serviceNameP).
AddBody(
gg.S("m.%s = v", v.TypeName()),
gg.Return("m"),
)
continue
}
// Generate Get/Set functions.
for _, v := range infos {
// If the value is export, we don't need to generate MustGetXxxx
if v.Export {
f.NewFunction("Get"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddResult("", v.Type()).
AddResult("", "bool").
AddBody(
gg.If(gg.S("m.bit & %sIndex%s != 0",
serviceNameC, templateutils.ToPascal(v.Name))).
AddBody(gg.Return("m."+v.TypeName(), gg.Lit(true))),
gg.Return(templateutils.ZeroValue(v.Type()), gg.Lit(false)),
)
f.NewFunction("MustGet"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddResult("", v.Type()).
AddBody(
gg.If(gg.S("m.bit & %sIndex%s == 0",
serviceNameC, templateutils.ToPascal(v.Name))).
AddBody(gg.S(
`panic(fmt.Sprintf("%s %s is not set"))`,
serviceNameK, v.Name)),
gg.Return("m."+v.TypeName()))
AddResult("", v.Type).
AddBody(gg.Return("m." + v.TypeName()))
f.NewFunction("Set"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddParameter("v", v.Type()).
AddParameter("v", v.Type).
AddResult("", "*"+serviceNameP).
AddBody(
gg.S("m.%s = v", v.TypeName()),
gg.S("m.bit |= %sIndex%s", serviceNameC, templateutils.ToPascal(v.Name)),
gg.Return("m"),
)
continue
}
f.NewFunction("Get"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddResult("", v.Type).
AddResult("", "bool").
AddBody(
gg.If(gg.S("m.bit & %sIndex%s != 0",
serviceNameC, templateutils.ToPascal(v.Name))).
AddBody(gg.Return("m."+v.TypeName(), gg.Lit(true))),
gg.Return(templateutils.ZeroValue(v.Type), gg.Lit(false)),
)
f.NewFunction("MustGet"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddResult("", v.Type).
AddBody(
gg.If(gg.S("m.bit & %sIndex%s == 0",
serviceNameC, templateutils.ToPascal(v.Name))).
AddBody(gg.S(
`panic(fmt.Sprintf("%s %s is not set"))`,
serviceNameK, v.Name)),
gg.Return("m."+v.TypeName()))
f.NewFunction("Set"+v.DisplayName()).
WithReceiver("m", "*"+serviceNameP).
AddParameter("v", v.Type).
AddResult("", "*"+serviceNameP).
AddBody(
gg.S("m.%s = v", v.TypeName()),
gg.S("m.bit |= %sIndex%s", serviceNameC, templateutils.ToPascal(v.Name)),
gg.Return("m"),
)
}

err := f.WriteFile(path)
Expand Down
128 changes: 128 additions & 0 deletions cmd/definitions/gen_iterator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//go:build tools
// +build tools

package main

import (
"fmt"

"github.com/Xuanwo/gg"
log "github.com/sirupsen/logrus"
)

func generateIterator(path string) {
data := []string{
"Block",
"Object",
"Part",
"Storager",
}

f := gg.NewGroup()
f.AddLineComment("Code generated by go generate cmd/definitions; DO NOT EDIT.")
f.AddPackage("types")
f.NewImport().
AddPath("context").
AddPath("errors").
AddPath("fmt")

f.NewInterface("Continuable").
NewFunction("ContinuationToken").
AddResult("", "string")

for _, name := range data {
typ := name
// Add a `*` if the type is not an interface.
if name != "Storager" {
typ = "*" + typ
}

nextFuncName := fmt.Sprintf("Next%sFunc", name)
pageStructName := fmt.Sprintf("%sPage", name)
iteratorStructName := fmt.Sprintf("%sIterator", name)

f.AddLineComment(`%s is the func used in iterator.
Notes
- ErrDone should be return while there are no items any more.
- Input %s slice should be set every time.
`, nextFuncName, name)
f.AddType(
nextFuncName,
gg.Function("").
AddParameter("ctx", "context.Context").
AddParameter("page", "*"+pageStructName).
AddResult("", "error"))

f.NewStruct(pageStructName).
AddField("Status", "Continuable").
AddField("Data", "[]"+typ)

f.NewStruct(iteratorStructName).
AddField("ctx", "context.Context").
AddField("next", nextFuncName).
AddLine().
AddField("index", "int").
AddField("done", "bool").
AddLine().
AddField("o", pageStructName)

f.NewFunction("New"+iteratorStructName).
AddParameter("ctx", "context.Context").
AddParameter("next", nextFuncName).
AddParameter("status", "Continuable").
AddResult("", "*"+iteratorStructName).
AddBody(gg.Return(
gg.Value("&"+iteratorStructName).
AddField("ctx", "ctx").
AddField("next", "next").
AddField("o", gg.Value(pageStructName).
AddField("Status", "status"))))

f.NewFunction("ContinuationToken").
WithReceiver("it", "*"+iteratorStructName).
AddResult("", "string").
AddBody(gg.Return(
gg.Call("ContinuationToken").WithOwner("it.o.Status")))

f.NewFunction("Next").
WithReceiver("it", "*"+iteratorStructName).
AddResult("object", typ).
AddResult("err", "error").
AddBody(
gg.LineComment("Consume Data via index."),
gg.S(`// Consume Data via index.
if it.index < len(it.o.Data) {
it.index++
return it.o.Data[it.index-1], nil
}
// Return IterateDone if iterator is already done.
if it.done {
return nil, IterateDone
}
// Reset buf before call next.
it.o.Data = it.o.Data[:0]
err = it.next(it.ctx ,&it.o)
if err != nil && !errors.Is(err, IterateDone) {
return nil, fmt.Errorf("iterator next failed: %w", err)
}
// Make iterator to done so that we will not fetch from upstream anymore.
if err != nil {
it.done = true
}
// Return IterateDone directly if we don't have any data.
if len(it.o.Data) == 0 {
return nil, IterateDone
}
// Return the first object.
it.index = 1
return it.o.Data[0], nil`))
}

err := f.WriteFile(path)
if err != nil {
log.Fatalf("generate to %s: %v", path, err)
}
}
Loading

0 comments on commit a6ea791

Please sign in to comment.