diff --git a/pattern_load.go b/pattern_load.go index a4c226a..3f4c3f8 100644 --- a/pattern_load.go +++ b/pattern_load.go @@ -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 { return false, errNilReceiver } @@ -39,12 +45,56 @@ func (pattern *Pattern) FindAndLoad(path string, strct interface{}) (bool, error return false, nil } - reflectedValue := reflect.ValueOf(strct) + reflectedValue := reflect.ValueOf(dest) if reflect.Ptr != reflectedValue.Kind() { +//@TODO: change error return doesNotMatter, errExpectedAPointerToAStruct } 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() { return doesNotMatter, errExpectedAPointerToAStruct } diff --git a/pattern_load_test.go b/pattern_load_test.go index 016f39d..c7ae0b1 100644 --- a/pattern_load_test.go +++ b/pattern_load_test.go @@ -4,11 +4,13 @@ package pathmatch import ( "github.com/fatih/structs" + "reflect" + "testing" ) -func TestFindAndLoad(t *testing.T) { +func TestFindAndLoadStrucs(t *testing.T) { tests := []struct{ 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 + } + } +}