package param import ( "encoding" "github.com/gin-gonic/gin" "ruben/inventory2/server/response" ) // Spec is the entry point of the package. // It's typically constructed via Path() or Form(). // But it's zero value is valid. // // It's methods support a builder pattern to minimize API bloat. // // To complete gin parameter parsing, call Unmarshal(). type Spec struct { path map[string]encoding.TextUnmarshaler form map[string]encoding.TextUnmarshaler } func Path(k string, dst encoding.TextUnmarshaler) Spec { return Spec{ path: map[string]encoding.TextUnmarshaler{ k: dst, }, } } func Form(k string, dst encoding.TextUnmarshaler) Spec { return Spec{ form: map[string]encoding.TextUnmarshaler{ k: dst, }, } } func (s Spec) Path(k string, dst encoding.TextUnmarshaler) Spec { if s.path == nil { s.path = make(map[string]encoding.TextUnmarshaler, 1) } s.path[k] = dst return s } func (s Spec) Form(k string, dst encoding.TextUnmarshaler) Spec { if s.form == nil { s.form = make(map[string]encoding.TextUnmarshaler, 1) } s.form[k] = dst return s } func (s Spec) Unmarshal(c *gin.Context) error { for k, dst := range s.path { v := c.Param(k) if v == "" { return response.NotFound().Msgf("no %s provided", k) } if err := dst.UnmarshalText([]byte(v)); err != nil { return response.NotFound().Wrap(err).Msgf("invalid %s", k) } } for k, dst := range s.form { v, ok := c.GetPostForm(k) if !ok || v == "" { if v, ok = c.GetQuery(k); !ok { return response.BadRequest().Msgf("no %s provided", k) } } if err := dst.UnmarshalText([]byte(v)); err != nil { return response.BadRequest().Wrap(err).Msgf("invalid %s provided", k) } } return nil }