Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 23 additions & 29 deletions urlpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,51 +75,45 @@ type Parser interface {
Parse(string) error
}

type stringParser struct {
destination *string
type StringType interface {
~string
}

// String creates a parser that will parse a path element into s.
func String(s *string) Parser {
return &stringParser{destination: s}
type stringParser[T StringType] struct {
destination *T
}

func (p *stringParser) Parse(s string) error {
*p.destination = s
func (p *stringParser[T]) Parse(s string) error {
*p.destination = T(s)
return nil
}

type intParser struct {
destination *int
// String creates a parser that will parse a path element into s.
func String[T StringType](s *T) Parser {
return &stringParser[T]{destination: s}
}

// Int creates a Parser that will parse a path element into i.
func Int(i *int) Parser {
return &intParser{destination: i}
// IntType represents any type compatible with the Go integer built-in types,
// to be used as a destination for writing the value of an url path element.
type IntType interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

func (p *intParser) Parse(s string) error {
type intParser[T IntType] struct {
destination *T
}

func (p *intParser[T]) Parse(s string) error {
i, err := strconv.Atoi(s)
if err != nil {
return err
}
*p.destination = i
*p.destination = T(i)
return nil
}

type uint64Parser struct {
destination *uint64
}

func UInt64(i *uint64) Parser {
return &uint64Parser{destination: i}
}

func (u uint64Parser) Parse(s string) error {
i, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return err
}
*u.destination = i
return nil
// Int creates a Parser that will parse a path element into i.
func Int[T IntType](i *T) Parser {
return &intParser[T]{destination: i}
}
40 changes: 36 additions & 4 deletions urlpath_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,20 @@ func Test_ParseValues(t *testing.T) {

var foo string
var bar int
var id uint64

values := map[string]string{
"foo": "blah",
"bar": "21",
"id": "42",
}

err := ParseValues(values, Schema{
"foo": String(&foo),
"bar": Int(&bar),
"id": UInt64(&id),
})

must.NoError(t, err)
must.EqOp(t, "blah", foo)
must.EqOp(t, 21, bar)
must.EqOp(t, 42, id)
}

func Test_ParseValues_incompatible(t *testing.T) {
Expand Down Expand Up @@ -112,3 +108,39 @@ func Test_Parameter_String(t *testing.T) {
s := p.String()
must.EqOp(t, "{foo}", s)
}

func Test_ParseValues_StringType_Parse(t *testing.T) {
t.Parallel()

values := map[string]string{
"KEY": "value",
}

type ident string

var id ident

err := ParseValues(values, Schema{
"KEY": String(&id),
})
must.NoError(t, err)
must.Eq(t, "value", id)
}

func Test_ParseValues_IntType_Parse(t *testing.T) {
t.Parallel()

type years int
var age years

values := map[string]string{
"age": "51",
}

err := ParseValues(values, Schema{
"age": Int(&age),
})

must.NoError(t, err)
must.Eq(t, 51, age)
}