made it so .FindAndLoad() can load to a *[]string too.

master
Charles Iliya Krempeaux 2019-07-11 08:42:02 -07:00
parent cd58524dc0
commit 4e99dd5057
2 changed files with 125 additions and 3 deletions

View File

@ -14,7 +14,13 @@ var (
) )
func (pattern *Pattern) FindAndLoad(path string, strct interface{}) (bool, error) { // FindAndLoad compares path against its (compiled) pattern template; if it matches
// it loads the matches into dest, and then returns true.
//
// dest can be a pointer struct, or a pointer to a []string.
//
// Find may set some, or all of the items or fields in dest even if it returns false, and even if it returns an error.
func (pattern *Pattern) FindAndLoad(path string, dest interface{}) (bool, error) {
if nil == pattern { if nil == pattern {
return false, errNilReceiver return false, errNilReceiver
} }
@ -39,12 +45,56 @@ func (pattern *Pattern) FindAndLoad(path string, strct interface{}) (bool, error
return false, nil return false, nil
} }
reflectedValue := reflect.ValueOf(strct) reflectedValue := reflect.ValueOf(dest)
if reflect.Ptr != reflectedValue.Kind() { if reflect.Ptr != reflectedValue.Kind() {
//@TODO: change error
return doesNotMatter, errExpectedAPointerToAStruct return doesNotMatter, errExpectedAPointerToAStruct
} }
reflectedValueElem := reflectedValue.Elem() reflectedValueElem := reflectedValue.Elem()
switch reflectedValueElem.Kind() {
case reflect.Slice:
var a []string = make([]string, len(args))
for i, arg := range args {
a[i] = *(arg.(*string))
}
return loadSlice(dest, a...)
case reflect.Struct:
return pattern.loadStruct(reflectedValueElem, args)
default:
//@TODO: change error
return doesNotMatter, errExpectedAPointerToAStruct
}
}
func loadSlice(dest interface{}, matches ...string) (bool, error) {
if nil == dest {
return false, errNilTarget
}
target, casted := dest.(*[]string)
if !casted {
//@TODO: CHANGE ERROR! ============================
return false, errExpectedAPointerToAStruct
}
if nil == target {
return false, errNilTarget
}
*target = (*target)[:0]
for _, match := range matches {
*target = append(*target, match)
}
return true, nil
}
func (pattern *Pattern) loadStruct(reflectedValueElem reflect.Value, args []interface{}) (bool, error) {
if nil == pattern {
return false, errNilReceiver
}
if reflect.Struct != reflectedValueElem.Kind() { if reflect.Struct != reflectedValueElem.Kind() {
return doesNotMatter, errExpectedAPointerToAStruct return doesNotMatter, errExpectedAPointerToAStruct
} }

View File

@ -4,11 +4,13 @@ package pathmatch
import ( import (
"github.com/fatih/structs" "github.com/fatih/structs"
"reflect"
"testing" "testing"
) )
func TestFindAndLoad(t *testing.T) { func TestFindAndLoadStrucs(t *testing.T) {
tests := []struct{ tests := []struct{
Pattern *Pattern Pattern *Pattern
@ -166,3 +168,73 @@ func TestFindAndLoad(t *testing.T) {
} }
} }
} }
func TestFindAndLoadStrings(t *testing.T) {
tests := []struct{
Pattern *Pattern
Path string
Expected []string
}{
{
Pattern: MustCompile("/user/{sessionKey}"),
Path: "/user/76M6.mXQfgiGSC_YJ5uXSnWUmELbe8OgOm5n.iZ98Ij",
Expected: []string{"76M6.mXQfgiGSC_YJ5uXSnWUmELbe8OgOm5n.iZ98Ij"},
},
{
Pattern: MustCompile("/user/{sessionKey}/vehicle/{vehicleIdcode}/"),
Path: "/user/76M6.mXQfgiGSC_YJ5uXSnWUmELbe8OgOm5n.iZ98Ij/vehicle/DEFAULT/",
Expected: []string{
"76M6.mXQfgiGSC_YJ5uXSnWUmELbe8OgOm5n.iZ98Ij",
"DEFAULT",
},
},
{
Pattern: MustCompile("/{this}/{that}/{these}/{those}"),
Path: "/apple/banana/cherry/grape",
Expected: []string{
"apple",
"banana",
"cherry",
"grape",
},
},
}
for testNumber, test := range tests {
var actual []string
matched, err := test.Pattern.FindAndLoad(test.Path, &actual)
if nil != err {
t.Errorf("For test #%d, did not expect an error, but actually got one: (%T) %q", testNumber, err, err)
t.Logf("\tPATTERN: %q", test.Pattern)
t.Logf("\tPATH: %q", test.Path)
continue
}
if !matched {
t.Errorf("For test #%d, expected a match, but it didn't.", testNumber)
t.Logf("\tPATTERN: %q", test.Pattern)
t.Logf("\tPATH: %q", test.Path)
t.Log("\t--")
t.Logf("\tMATCHED: %t", matched)
continue
}
if expected := test.Expected; !reflect.DeepEqual(expected, actual) {
t.Errorf("For test #%d, did not get what was expected.", testNumber)
t.Logf("\tPATTERN: %q", test.Pattern)
t.Logf("\tPATH: %q", test.Path)
t.Log("\t--")
t.Logf("\tEXPECTED: %#v", expected)
t.Logf("\tACTUAL: %#v", actual)
continue
}
}
}