package urlenc import "fmt" import "net/url" type Values = url.Values type Builder interface { BuildQueryValues() Values } type Value[V any] struct { Name string Value V } func (value Value[V]) BuildQueryValues() Values { values := Values{} values.Add( value.Name, fmt.Sprintf("%v", value.Value), ) return values } func (value Value[V]) String() string { unesc, err := url.QueryUnescape( value.BuildQueryValues().Encode(), ) if err != nil { panic(err) } return unesc } type Array[V any] struct { Name string Values []V } func (a Array[V]) BuildQueryValues() Values { values := Values{} for i, v := range a.Values { values.Add( fmt.Sprintf("%s[%d]", a.Name, i), fmt.Sprintf("%v", v), ) } return values } func (a Array[V]) String() string { unesc, err := url.QueryUnescape( a.BuildQueryValues().Encode(), ) if err != nil { panic(err) } return unesc } func Join(builders ...Builder) Values { ret := Values{} for _, builder := range builders { for k, v := range builder.BuildQueryValues() { for _, jv := range v { ret.Add(k, jv) } } } return ret } type FnArray[V any] struct { Values []V Fn func([]V, int) (string, string) } func (a FnArray[V]) BuildQueryValues() Values { values := Values{} for i := range a.Values { k, v := a.Fn(a.Values, i) values.Add(k, v) } return values } func (a FnArray[V]) String() string { unesc, err := url.QueryUnescape( a.BuildQueryValues().Encode(), ) if err != nil { panic(err) } return unesc }