Skip to content
Snippets Groups Projects
Verified Commit 049f2876 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

fix: parse path values #2 #7

parent f0987f43
No related branches found
No related tags found
No related merge requests found
......@@ -94,8 +94,8 @@ func (s *Settings[C]) importStreams() {
}
}
//// replacePath replaces all pathInterface fields in the struct with the given path
//func replacePath(p string, c any) {
// // replacePath replaces all pathInterface fields in the struct with the given path
// func replacePath(p string, c any) {
//
// if reflect.TypeOf(c).Kind() != reflect.Ptr {
// panic("c must be a pointer")
......@@ -152,21 +152,28 @@ func (s *Settings[C]) importStreams() {
//
// }
//
//}
// }
func replacePath(p string, c interface{}) {
cValue := reflect.ValueOf(c)
cType := cValue.Type()
if cType.Kind() != reflect.Ptr {
panic("c must be a pointer")
// If c is of type PathValue (which implements pathInterface), modify the path
if cValue.Type().ConvertibleTo(reflect.TypeOf(PathValue(""))) {
pathVal := cValue.Convert(reflect.TypeOf(PathValue(""))).Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
if cValue.CanSet() {
cValue.Set(reflect.ValueOf(newPath))
}
}
return
}
if cType.Elem().Kind() != reflect.Struct {
panic("c must be a pointer to a struct")
// If c is not a struct, simply return
if cValue.Kind() != reflect.Ptr || cValue.Elem().Kind() != reflect.Struct {
return
}
fields := reflect.VisibleFields(cType.Elem())
fields := reflect.VisibleFields(cValue.Elem().Type())
for _, field := range fields {
r := cValue.Elem().FieldByName(field.Name)
handleField(p, r)
......@@ -179,12 +186,34 @@ func handleField(p string, r reflect.Value) {
if r.CanAddr() {
replacePath(p, r.Addr().Interface())
}
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface:
forEachElem(r, func(e reflect.Value) {
if e.CanAddr() {
replacePath(p, e.Addr().Interface())
case reflect.Slice:
for i := 0; i < r.Len(); i++ {
elem := r.Index(i)
if elem.Type().ConvertibleTo(reflect.TypeOf(PathValue(""))) {
pathVal := elem.Convert(reflect.TypeOf(PathValue(""))).Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
if elem.CanSet() {
elem.Set(reflect.ValueOf(newPath))
}
}
} else if elem.CanAddr() {
replacePath(p, elem.Addr().Interface())
}
})
}
case reflect.Map:
for _, k := range r.MapKeys() {
elem := r.MapIndex(k)
if elem.Type().ConvertibleTo(reflect.TypeOf(PathValue(""))) {
pathVal := elem.Convert(reflect.TypeOf(PathValue(""))).Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
r.SetMapIndex(k, reflect.ValueOf(newPath))
}
} else if elem.CanAddr() {
replacePath(p, elem.Addr().Interface())
}
}
default:
// Check for pathInterface
if v, ok := r.Interface().(pathInterface); ok {
......@@ -196,22 +225,22 @@ func handleField(p string, r reflect.Value) {
}
}
func forEachElem(r reflect.Value, fn func(e reflect.Value)) {
switch r.Kind() {
case reflect.Slice:
for i := 0; i < r.Len(); i++ {
fn(r.Index(i))
}
case reflect.Map:
for _, k := range r.MapKeys() {
fn(r.MapIndex(k))
}
case reflect.Ptr, reflect.Interface:
if !r.IsNil() {
fn(r.Elem())
}
}
}
//func forEachElem(r reflect.Value, fn func(e reflect.Value)) {
// switch r.Kind() {
// case reflect.Slice:
// for i := 0; i < r.Len(); i++ {
// fn(r.Index(i))
// }
// case reflect.Map:
// for _, k := range r.MapKeys() {
// fn(r.MapIndex(k))
// }
// case reflect.Ptr, reflect.Interface:
// if !r.IsNil() {
// fn(r.Elem())
// }
// }
//}
func (s *Settings[C]) importFiles() {
......
......@@ -14,6 +14,7 @@ import (
type Issue7Routing struct {
P PathValue `json:"p" yaml:"p"`
X string `json:"x" yaml:"x"`
}
type Issue7Server struct {
......@@ -49,7 +50,8 @@ func TestPathRewrite(t *testing.T) {
"server": {
"routing": [
{
"p": "./test"
"p": "./test",
"x": "testX"
}
]
}
......@@ -69,5 +71,69 @@ func TestPathRewrite(t *testing.T) {
expected := path.Join(filepath.Dir(n), "test")
assert.Equal(t, expected, c.Config().Server.Routing[0].P.String())
assert.Equal(t, "testX", c.Config().Server.Routing[0].X)
}
// Test data structs
type Issue7TestStruct1 struct {
A PathValue
B string
C int
}
type Issue7TestStruct2 struct {
A PathValue
B Issue7TestStruct1
C []PathValue
D map[string]PathValue
}
func TestIssue7ReplacePath(t *testing.T) {
basePath := "/basepath"
// Test case 1
ts1 := Issue7TestStruct1{
A: "relative/path",
B: "justastring",
C: 42,
}
replacePath(basePath, &ts1)
if ts1.A != PathValue(path.Join(basePath, "relative/path")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "relative/path"), ts1.A)
}
// Test case 2
ts2 := Issue7TestStruct2{
A: "another/relative/path",
B: ts1,
C: []PathValue{"rel1", "rel2"},
D: map[string]PathValue{
"key1": "relkey1",
"key2": "relkey2",
},
}
replacePath(basePath, &ts2)
if ts2.A != PathValue(path.Join(basePath, "another/relative/path")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "another/relative/path"), ts2.A)
}
if ts2.B.A != PathValue(path.Join(basePath, "relative/path")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "relative/path"), ts2.B.A)
}
if ts2.C[0] != PathValue(path.Join(basePath, "rel1")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "rel1"), ts2.C[0])
}
if ts2.C[1] != PathValue(path.Join(basePath, "rel2")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "rel2"), ts2.C[1])
}
if ts2.D["key1"] != PathValue(path.Join(basePath, "relkey1")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "relkey1"), ts2.D["key1"])
}
if ts2.D["key2"] != PathValue(path.Join(basePath, "relkey2")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "relkey2"), ts2.D["key2"])
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment