Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions modifiers/modifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ func New() *mold.Transformer {
mod.Register("strip_punctuation", stripPunctuation)
mod.Register("camel", camelCase)
mod.Register("default", defaultValue)
mod.Register("substr", subStr)
return mod
}
40 changes: 40 additions & 0 deletions modifiers/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"reflect"
"regexp"
"strconv"
"strings"
"unicode"
"unicode/utf8"
Expand Down Expand Up @@ -210,3 +211,42 @@ func camelCase(ctx context.Context, fl mold.FieldLevel) error {
}
return nil
}

func subStr(ctx context.Context, fl mold.FieldLevel) error {
switch fl.Field().Kind() {
case reflect.String:
val := fl.Field().String()
params := strings.SplitN(fl.Param(), "-", 2)
if len(params) == 0 || len(params[0]) == 0 {
return nil
}

start, err := strconv.Atoi(params[0])
if err != nil {
return err
}

end := len(val)
if len(params) >= 2 {
end, err = strconv.Atoi(params[1])
if err != nil {
return err
}
}

if len(val) < start {
fl.Field().SetString("")
return nil
}
if len(val) < end {
end = len(val)
}
if start > end {
fl.Field().SetString("")
return nil
}

fl.Field().SetString(val[start:end])
}
return nil
}
106 changes: 106 additions & 0 deletions modifiers/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -938,3 +938,109 @@ var (
reflect.TypeOf(sql.NullString{}): true,
}
)

func TestSubStr(t *testing.T) {
conform := New()

s := "123"
expected := "123"

type Test struct {
String string `mod:"substr=0-3"`
}

tt := Test{String: s}
err := conform.Struct(context.Background(), &tt)
if err != nil {
log.Fatal(err)
}
if tt.String != expected {
t.Fatalf("Unexpected value '%s'\n", tt.String)
}

tag := "substr=f-3"
err = conform.Field(context.Background(), &s, tag)
if err == nil {
t.Fatalf("Unexpected value '%s' instead of error for tag %s\n", s, tag)
}
tag = "substr=2-f"
err = conform.Field(context.Background(), &s, tag)
if err == nil {
t.Fatalf("Unexpected value '%s' instead of error for tag %s\n", s, tag)
}

tests := []struct {
tag string
expected string
}{
{
tag: "substr",
expected: "123",
},
{
tag: "substr=0-1",
expected: "1",
},
{
tag: "substr=0-3",
expected: "123",
},
{
tag: "substr=0-2",
expected: "12",
},
{
tag: "substr=1-2",
expected: "2",
},
{
tag: "substr=3-3",
expected: "",
},
{
tag: "substr=4-5",
expected: "",
},
{
tag: "substr=2-1",
expected: "",
},
{
tag: "substr=2-5",
expected: "3",
},
{
tag: "substr=2",
expected: "3",
},
}
for _, test := range tests {
st := s

err = conform.Field(context.Background(), &st, test.tag)
if err != nil {
log.Fatal(err)
}
if st != test.expected {
t.Fatalf("Unexpected value '%s' for tag %s\n", st, test.tag)
}

var iface interface{}
err = conform.Field(context.Background(), &iface, test.tag)
if err != nil {
log.Fatal(err)
}
if iface != nil {
t.Fatalf("Unexpected value '%v'\n", nil)
}

iface = s
err = conform.Field(context.Background(), &iface, test.tag)
if err != nil {
log.Fatal(err)
}
if iface != test.expected {
t.Fatalf("Unexpected value '%v'\n", iface)
}
}
}