From 52a1f1900e8a800e610e70c24f4e70d683d47578 Mon Sep 17 00:00:00 2001 From: Alejandro Lazarte Date: Thu, 14 Oct 2021 16:22:35 -0300 Subject: [PATCH] Initial commit Unmarshall of simple config file, just to practice Go's reflect lib --- test | 5 ++++ unmarshaler.go | 71 +++++++++++++++++++++++++++++++++++++++++++++ unmarshaler_test.go | 36 +++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 test create mode 100644 unmarshaler.go create mode 100644 unmarshaler_test.go diff --git a/test b/test new file mode 100644 index 0000000..f900f3b --- /dev/null +++ b/test @@ -0,0 +1,5 @@ +Pem=fullchainfile.pem +Sk=privkeyfile.pem +Handler.Name=someName +Handler.Path=/tmp +Handler.Type=type diff --git a/unmarshaler.go b/unmarshaler.go new file mode 100644 index 0000000..9609ead --- /dev/null +++ b/unmarshaler.go @@ -0,0 +1,71 @@ +package cfgreader + +import ( + "bufio" + "io" + "os" + "reflect" + "regexp" +) + +type unmarshalError string + +func (e unmarshalError) Error() string { + return string(e) +} + +func unmarshalKeyValue(m map[string]interface{}, v *reflect.Value) { + for key, ival := range m { + if reflect.ValueOf(ival).Kind() == reflect.Map { + v2 := v.FieldByName(key) + unmarshalKeyValue(ival.(map[string]interface{}), &v2) + } + switch v.FieldByName(key).Type().Kind() { + case reflect.String: + v.FieldByName(key).SetString(ival.(string)) + } + } +} + +func unmarshalCfg(m map[string]interface{}, v interface{}) error { + vt := reflect.ValueOf(v).Elem() + if !vt.CanSet() { + return unmarshalError("cannot set interface") + } + unmarshalKeyValue(m, &vt) + return nil +} + +func FromFile(filepath string, v interface{}) error { + f, err := os.Open(filepath) + if err != nil { + return err + } + buf := bufio.NewReader(f) + group := regexp.MustCompile(`(?:([A-Z][a-z]+)\.)?([A-Z][a-z]+)=([A-Za-z0-9\./]+)\n`) + m := make(map[string]interface{}) + for { + l, err := buf.ReadString('\n') + if err != nil { + if err == io.EOF { + break + } + continue + } + ss := group.FindAllStringSubmatch(l, -1) + if len(ss) == 0 { + continue + } + if ss[0][1] == "" { + // "" "Key" "Value" + m[ss[0][2]] = ss[0][3] + continue + } + if m[ss[0][1]] == nil { + m[ss[0][1]] = make(map[string]interface{}) + } + // "Group" "Key" "Value" + m[ss[0][1]].(map[string]interface{})[ss[0][2]] = ss[0][3] + } + return unmarshalCfg(m, v) +} diff --git a/unmarshaler_test.go b/unmarshaler_test.go new file mode 100644 index 0000000..54d90ac --- /dev/null +++ b/unmarshaler_test.go @@ -0,0 +1,36 @@ +package cfgreader + +import ( + "fmt" + "os" + "testing" +) + +func TestInit(t *testing.T) { + contents := `Pem=fullchainfile.pem +Sk=privkeyfile.pem +Handler.Name=someName +Handler.Path=/tmp +Handler.Type=type +` + if err := os.WriteFile("test", []byte(contents), 0644); err != nil { + t.Fatal(err) + } +} +func TestHelloWorld(t *testing.T) { + c := struct { + Pem string + Sk string + Handler struct { + Name string + Path string + Type string + } + }{} + if err := FromFile("test", &c); err != nil { + t.Fatal(err) + } + if fmt.Sprintf("%q", &c) != "&{\"fullchainfile.pem\" \"privkeyfile.pem\" {\"someName\" \"/tmp\" \"type\"}}" { + t.Fatal("Not what I expected") + } +} -- 2.34.2