Skip to content

Commit

Permalink
add binding/render by id support for gin engine
Browse files Browse the repository at this point in the history
  • Loading branch information
alimy committed Mar 10, 2024
1 parent c67a469 commit 3945866
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 92 deletions.
26 changes: 26 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ type InitOpts struct {
EngineImportAlias string
WatchCtxDone bool
UseRequestCtx bool
UseNamedBinding bool
UseNamedRender bool
NoneQuery bool
Cleanup bool
}
Expand All @@ -73,6 +75,8 @@ type ParserOpts struct {
DefaultRenderTag string
WatchCtxDone bool
UseRequestCtx bool
UseNamedBinding bool
UseNamedRender bool
NoneQuery bool
}

Expand Down Expand Up @@ -107,6 +111,8 @@ func (opts *InitOpts) ParserOpts() *ParserOpts {
DefaultRenderTag: opts.DefaultRenderTag,
WatchCtxDone: opts.WatchCtxDone,
UseRequestCtx: opts.UseRequestCtx,
UseNamedBinding: opts.UseNamedBinding,
UseNamedRender: opts.UseNamedRender,
NoneQuery: opts.NoneQuery,
EngineInfo: &EngineInfo{
PkgName: opts.EnginePkgName,
Expand Down Expand Up @@ -310,6 +316,24 @@ func UseRequestContext() Option {
})
}

// UseNamedBinding use Named Binding.
// will generate BindByName(string, *gin.Context, any) mir.Error method to binding
// object when this option is enable.
func UseNamedBinding() Option {
return optFunc(func(opts *InitOpts) {
opts.UseNamedBinding = true
})
}

// UseNamedBinding use Named Binding.
// will generate RenderByName(string, *gin.Context, any, mir.Error) method to render
// object when this option is enable.
func UseNamedRender() Option {
return optFunc(func(opts *InitOpts) {
opts.UseNamedRender = true
})
}

// Cleanup set generator cleanup out first when re-generate code
func Cleanup(enable bool) Option {
return optFunc(func(opts *InitOpts) {
Expand Down Expand Up @@ -434,6 +458,8 @@ func defaultInitOpts() *InitOpts {
DefaultRenderTag: "render",
WatchCtxDone: true,
UseRequestCtx: false,
UseNamedBinding: false,
UseNamedRender: false,
Cleanup: true,
}
}
116 changes: 112 additions & 4 deletions core/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"reflect"
"sort"
"strings"
"unicode"

"github.com/alimy/mir/v4/internal/utils"
)
Expand Down Expand Up @@ -47,6 +48,8 @@ type FieldDescriptor struct {
IsRenderOut bool
BindingName string
RenderName string
UseBindingById bool
UseRenderById bool
In reflect.Type
Out reflect.Type
InOuts []reflect.Type
Expand Down Expand Up @@ -265,21 +268,94 @@ func (d *IfaceDescriptor) BindingFields() (fields []*FieldDescriptor) {
}

func (d *IfaceDescriptor) IsUseNamedBinding() bool {
var isNamedBinding, useBindingById bool
for _, f := range d.Fields {
if f.IsUseNamedBinding() {
return true
isNamedBinding = true
break
}
}
return false
for _, f := range d.Fields {
if f.UseBindingById {
useBindingById = true
break
}
}
return isNamedBinding && !useBindingById
}

func (d *IfaceDescriptor) IsUseNamedRender() bool {
var isNamedRender, useRenderById bool
for _, f := range d.Fields {
if f.IsUseNamedRender() {
return true
isNamedRender = true
break
}
}
return false
for _, f := range d.Fields {
if f.UseRenderById {
useRenderById = true
break
}
}
return isNamedRender && !useRenderById
}

func (d *IfaceDescriptor) IsUseBindingById() bool {
var isNamedBinding, useBindingById bool
for _, f := range d.Fields {
if f.IsUseNamedBinding() {
isNamedBinding = true
break
}
}
for _, f := range d.Fields {
if f.UseBindingById {
useBindingById = true
}
}
return isNamedBinding && useBindingById
}

func (d *IfaceDescriptor) IsUseRenderById() bool {
var isNamedRender, useRenderById bool
for _, f := range d.Fields {
if f.IsUseNamedRender() {
isNamedRender = true
break
}
}
for _, f := range d.Fields {
if f.UseRenderById {
useRenderById = true
break
}
}
return isNamedRender && useRenderById
}

func (d *IfaceDescriptor) BindingIdSet() []string {
set := utils.NewStrSet()
var id string
for _, f := range d.Fields {
id = f.BindingId()
if len(id) > 0 {
set.Add(f.BindingId())
}
}
return set.List()
}

func (d *IfaceDescriptor) RenderIdSet() []string {
set := utils.NewStrSet()
var id string
for _, f := range d.Fields {
id = f.RenderId()
if len(id) > 0 {
set.Add(f.RenderId())
}
}
return set.List()
}

// HttpMethod return http method when f.NotHttpAny() is true
Expand Down Expand Up @@ -352,6 +428,38 @@ func (f *FieldDescriptor) IsUseNamedRender() bool {
return f.Out != nil && len(f.RenderName) > 0
}

func (f *FieldDescriptor) BindingId() (res string) {
b := &strings.Builder{}
b.Grow(len(f.BindingName))
for i, r := range f.BindingName {
if r == ' ' || r == '_' {
continue
}
if i == 0 {
b.WriteRune(unicode.ToUpper(r))
continue
}
b.WriteRune(r)
}
return b.String()
}

func (f FieldDescriptor) RenderId() string {
b := &strings.Builder{}
b.Grow(len(f.RenderName))
for i, r := range f.RenderName {
if r == ' ' || r == '_' {
continue
}
if i == 0 {
b.WriteRune(unicode.ToUpper(r))
continue
}
b.WriteRune(r)
}
return b.String()
}

func (f *FieldDescriptor) aliasPkgName(pkgPath string) string {
if alias := f.Imports[pkgPath]; alias != "" {
return alias
Expand Down
10 changes: 5 additions & 5 deletions examples/mirc/auto/api/site.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 11 additions & 8 deletions examples/mirc/auto/api/v2/site.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/mirc/auto/api/v3/site.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/mirc/routes/v2/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ type Site struct {
Articles func(Get) `mir:"/articles/:category/"`
NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next/" render:"json"`
PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev/" binding:"yaml"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/" binding:"json"`
Logout func(Post) `mir:"/user/logout/"`
ImageUpload func(Post, Context) `mir:"/upload/image/:name/"`
FileUpload func(Post, Chain, Context) `mir:"/upload/file/:name/"`
SimpleUpload func(Post, Chain, Context, LoginReq) LoginResp `mir:"/upload/simple/:name/"`
SimpleUpload func(Post, Chain, Context, LoginReq) LoginResp `mir:"/upload/simple/:name/" render:"Jsonp"`
Assets func(Get, Context, LoginReq) `mir:"/assets/:name/"`
AnyStaticks func(Any, Context) `mir:"/anystaticks/:name/"`
ManyResources func(Get, Head, Options, Context) `mir:"/resources/:name/"`
MultiAttachments func(Get, Head, Options, Chain, Context) `mir:"/attachments/:name/"`
MultiAttachments func(Get, Head, Options, Chain, Context) `mir:"/attachments/:name/" render:"XML"`
}
Loading

0 comments on commit 3945866

Please sign in to comment.