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() { ...@@ -94,8 +94,8 @@ func (s *Settings[C]) importStreams() {
} }
} }
//// replacePath replaces all pathInterface fields in the struct with the given path // // replacePath replaces all pathInterface fields in the struct with the given path
//func replacePath(p string, c any) { // func replacePath(p string, c any) {
// //
// if reflect.TypeOf(c).Kind() != reflect.Ptr { // if reflect.TypeOf(c).Kind() != reflect.Ptr {
// panic("c must be a pointer") // panic("c must be a pointer")
...@@ -152,21 +152,28 @@ func (s *Settings[C]) importStreams() { ...@@ -152,21 +152,28 @@ func (s *Settings[C]) importStreams() {
// //
// } // }
// //
//} // }
func replacePath(p string, c interface{}) { func replacePath(p string, c interface{}) {
cValue := reflect.ValueOf(c) cValue := reflect.ValueOf(c)
cType := cValue.Type()
if cType.Kind() != reflect.Ptr { // If c is of type PathValue (which implements pathInterface), modify the path
panic("c must be a pointer") 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 { // If c is not a struct, simply return
panic("c must be a pointer to a struct") 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 { for _, field := range fields {
r := cValue.Elem().FieldByName(field.Name) r := cValue.Elem().FieldByName(field.Name)
handleField(p, r) handleField(p, r)
...@@ -179,12 +186,34 @@ func handleField(p string, r reflect.Value) { ...@@ -179,12 +186,34 @@ func handleField(p string, r reflect.Value) {
if r.CanAddr() { if r.CanAddr() {
replacePath(p, r.Addr().Interface()) replacePath(p, r.Addr().Interface())
} }
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface: case reflect.Slice:
forEachElem(r, func(e reflect.Value) { for i := 0; i < r.Len(); i++ {
if e.CanAddr() { elem := r.Index(i)
replacePath(p, e.Addr().Interface()) 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: default:
// Check for pathInterface // Check for pathInterface
if v, ok := r.Interface().(pathInterface); ok { if v, ok := r.Interface().(pathInterface); ok {
...@@ -196,22 +225,22 @@ func handleField(p string, r reflect.Value) { ...@@ -196,22 +225,22 @@ func handleField(p string, r reflect.Value) {
} }
} }
func forEachElem(r reflect.Value, fn func(e reflect.Value)) { //func forEachElem(r reflect.Value, fn func(e reflect.Value)) {
switch r.Kind() { // switch r.Kind() {
case reflect.Slice: // case reflect.Slice:
for i := 0; i < r.Len(); i++ { // for i := 0; i < r.Len(); i++ {
fn(r.Index(i)) // fn(r.Index(i))
} // }
case reflect.Map: // case reflect.Map:
for _, k := range r.MapKeys() { // for _, k := range r.MapKeys() {
fn(r.MapIndex(k)) // fn(r.MapIndex(k))
} // }
case reflect.Ptr, reflect.Interface: // case reflect.Ptr, reflect.Interface:
if !r.IsNil() { // if !r.IsNil() {
fn(r.Elem()) // fn(r.Elem())
} // }
} // }
} //}
func (s *Settings[C]) importFiles() { func (s *Settings[C]) importFiles() {
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
type Issue7Routing struct { type Issue7Routing struct {
P PathValue `json:"p" yaml:"p"` P PathValue `json:"p" yaml:"p"`
X string `json:"x" yaml:"x"`
} }
type Issue7Server struct { type Issue7Server struct {
...@@ -49,7 +50,8 @@ func TestPathRewrite(t *testing.T) { ...@@ -49,7 +50,8 @@ func TestPathRewrite(t *testing.T) {
"server": { "server": {
"routing": [ "routing": [
{ {
"p": "./test" "p": "./test",
"x": "testX"
} }
] ]
} }
...@@ -69,5 +71,69 @@ func TestPathRewrite(t *testing.T) { ...@@ -69,5 +71,69 @@ func TestPathRewrite(t *testing.T) {
expected := path.Join(filepath.Dir(n), "test") expected := path.Join(filepath.Dir(n), "test")
assert.Equal(t, expected, c.Config().Server.Routing[0].P.String()) 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