From b5e9a534901354a52405fd707f0645b560267211 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Sat, 17 Dec 2022 16:27:12 +0100
Subject: [PATCH] feat: support maps

---
 get.go      | 20 ++++++++++++-
 get_test.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 get_test.go

diff --git a/get.go b/get.go
index 9fbd303..a49d985 100644
--- a/get.go
+++ b/get.go
@@ -21,7 +21,16 @@ func GetValue[D any](obj D, keyWithDots string) (any, error) {
 			v = v.Elem()
 		}
 
-		if v.Kind() != reflect.Struct {
+		if v.Kind() == reflect.Map {
+			switch v.Type().Key().Kind() {
+			case reflect.String:
+				v = v.MapIndex(reflect.ValueOf(key)).Elem()
+		
+				continue
+			default:
+				return nil, newUnsupportedTypePathError(keyWithDots, v.Type())
+			}
+		} else if v.Kind() != reflect.Struct {
 			return nil, newUnsupportedTypePathError(keyWithDots, v.Type())
 		}
 
@@ -36,6 +45,15 @@ func GetValue[D any](obj D, keyWithDots string) (any, error) {
 		v = v.Elem()
 	}
 
+	if v.Kind() == reflect.Map {
+		switch v.Type().Key().Kind() {
+		case reflect.String:
+			return v.MapIndex(reflect.ValueOf(keySlice[len(keySlice)-1])).Interface(), nil
+		default:
+			return nil, newUnsupportedTypePathError(keyWithDots, v.Type())
+		}
+	}
+
 	// non-supporter type at the top of the path
 	if v.Kind() != reflect.Struct {
 		return nil, newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
diff --git a/get_test.go b/get_test.go
new file mode 100644
index 0000000..d079fa3
--- /dev/null
+++ b/get_test.go
@@ -0,0 +1,81 @@
+// Copyright 2022 schukai GmbH
+// SPDX-License-Identifier: AGPL-3.0
+
+package pathfinder
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestGetValueFrom(t *testing.T) {
+
+	m := map[string]string{
+		"KeyA": "true",
+		"KeyB": "2",
+		"KeyC": "3",
+		"KeyD": "4.0",
+	}
+
+	v, err := GetValue[map[string]string](m, "KeyA")
+	if err != nil {
+		t.Error(err)
+	}
+
+	assert.Equal(t, v, "true")
+
+}
+
+func TestPathGetValueFromX(t *testing.T) {
+	m := map[string]any{
+		"A": "true",
+		"B": map[string]any{
+			"C": 2,
+			"D": map[string]any{
+				"E": "3",
+			},
+		},
+		"X": "3",
+		"Y": "4.0",
+	}
+
+	v, err := GetValue[map[string]any](m, "B.D.E")
+	if err != nil {
+		t.Error(err)
+	}
+
+	assert.Equal(t, "3", v)
+
+	v, err = GetValue[map[string]any](m, "B.C")
+	if err != nil {
+		t.Error(err)
+	}
+
+	assert.Equal(t, 2, v)
+
+}
+
+func TestPathGetValueFrom(t *testing.T) {
+
+	type PathfindTestStruct1 struct {
+		A    bool
+		Sub1 struct {
+			B    int
+			Sub2 struct {
+				C bool
+			}
+			D int
+		}
+	}
+
+	var testData PathfindTestStruct1
+	testData.A = true
+	testData.Sub1.B = 2
+	testData.Sub1.Sub2.C = true
+	testData.Sub1.D = 4
+
+	GetValue[PathfindTestStruct1](testData, "Sub1.B")
+	GetValue[PathfindTestStruct1](testData, "Sub1.Sub2.C")
+	GetValue[PathfindTestStruct1](testData, "Sub1.D")
+
+}
-- 
GitLab