vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
changeset 260 445e01aede7e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go	Tue Aug 23 22:39:43 2022 +0200
@@ -0,0 +1,86 @@
+package javaproperties
+
+import (
+	"bytes"
+	"sort"
+	"strings"
+
+	"github.com/magiconair/properties"
+	"github.com/spf13/cast"
+)
+
+// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
+type Codec struct {
+	KeyDelimiter string
+
+	// Store read properties on the object so that we can write back in order with comments.
+	// This will only be used if the configuration read is a properties file.
+	// TODO: drop this feature in v2
+	// TODO: make use of the global properties object optional
+	Properties *properties.Properties
+}
+
+func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) {
+	if c.Properties == nil {
+		c.Properties = properties.NewProperties()
+	}
+
+	flattened := map[string]interface{}{}
+
+	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
+
+	keys := make([]string, 0, len(flattened))
+
+	for key := range flattened {
+		keys = append(keys, key)
+	}
+
+	sort.Strings(keys)
+
+	for _, key := range keys {
+		_, _, err := c.Properties.Set(key, cast.ToString(flattened[key]))
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	var buf bytes.Buffer
+
+	_, err := c.Properties.WriteComment(&buf, "#", properties.UTF8)
+	if err != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
+func (c *Codec) Decode(b []byte, v map[string]interface{}) error {
+	var err error
+	c.Properties, err = properties.Load(b, properties.UTF8)
+	if err != nil {
+		return err
+	}
+
+	for _, key := range c.Properties.Keys() {
+		// ignore existence check: we know it's there
+		value, _ := c.Properties.Get(key)
+
+		// recursively build nested maps
+		path := strings.Split(key, c.keyDelimiter())
+		lastKey := strings.ToLower(path[len(path)-1])
+		deepestMap := deepSearch(v, path[0:len(path)-1])
+
+		// set innermost value
+		deepestMap[lastKey] = value
+	}
+
+	return nil
+}
+
+func (c Codec) keyDelimiter() string {
+	if c.KeyDelimiter == "" {
+		return "."
+	}
+
+	return c.KeyDelimiter
+}