diff --git a/get.go b/get.go new file mode 100644 index 0000000000000000000000000000000000000000..9fbd303858c2f2f8300002ccd0b4ed5a84f65cb8 --- /dev/null +++ b/get.go @@ -0,0 +1,51 @@ +// Copyright 2022 schukai GmbH +// SPDX-License-Identifier: AGPL-3.0 + +package pathfinder + +import ( + "reflect" + "strings" +) + +// This function returns the value of a field in a struct, given a path to the field. +func GetValue[D any](obj D, keyWithDots string) (any, error) { + keySlice := strings.Split(keyWithDots, ".") + v := reflect.ValueOf(obj) + + for _, key := range keySlice[0 : len(keySlice)-1] { + for v.Kind() == reflect.Ptr { + if v.Kind() == reflect.Invalid { + return nil, newInvalidPathError(keyWithDots) + } + v = v.Elem() + } + + if v.Kind() != reflect.Struct { + return nil, newUnsupportedTypePathError(keyWithDots, v.Type()) + } + + v = v.FieldByName(key) + } + + if v.Kind() == reflect.Invalid { + return nil, newInvalidPathError(keyWithDots) + } + + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + + // non-supporter type at the top of the path + if v.Kind() != reflect.Struct { + return nil, newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type()) + } + + v = v.FieldByName(keySlice[len(keySlice)-1]) + if !v.IsValid() { + return nil, newInvalidPathError(keyWithDots) + } + + return v.Interface(), nil + +} diff --git a/pathfind.go b/set.go similarity index 75% rename from pathfind.go rename to set.go index 28adede2ac502ba6efe9a196dd916cec3ab4a44a..124f9fad40f052afc877d19f87ae3205a3da1f9f 100644 --- a/pathfind.go +++ b/set.go @@ -10,45 +10,6 @@ import ( "strings" ) -// This function returns the value of a field in a struct, given a path to the field. -func GetValue[D any](obj D, keyWithDots string) (any, error) { - keySlice := strings.Split(keyWithDots, ".") - v := reflect.ValueOf(obj) - - for _, key := range keySlice[0 : len(keySlice)-1] { - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - - if v.Kind() != reflect.Struct { - return nil, newUnsupportedTypePathError(keyWithDots, v.Type()) - } - - v = v.FieldByName(key) - } - - if v.Kind() == reflect.Invalid { - return nil, newInvalidPathError(keyWithDots) - } - - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - - // non-supporter type at the top of the path - if v.Kind() != reflect.Struct { - return nil, newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type()) - } - - v = v.FieldByName(keySlice[len(keySlice)-1]) - if !v.IsValid() { - return nil, newInvalidPathError(keyWithDots) - } - - return v.Interface(), nil - -} - // This function sets the value of a field in a struct, given a path to the field. func SetValue[D any](obj D, keyWithDots string, newValue any) error { @@ -57,6 +18,9 @@ func SetValue[D any](obj D, keyWithDots string, newValue any) error { for _, key := range keySlice[0 : len(keySlice)-1] { for v.Kind() != reflect.Ptr { + if v.Kind() == reflect.Invalid { + return newInvalidPathError(keyWithDots) + } v = v.Addr() } diff --git a/pathfind_test.go b/set_test.go similarity index 100% rename from pathfind_test.go rename to set_test.go