Documentation
¶
Overview ¶
Package barky provides utilities for handling hierarchical key/value data structures that commonly appear in configuration formats such as JSON, YAML, or TOML. It is designed to transform nested data into a flat representation, while preserving enough metadata to reconstruct paths, detect conflicts, and manage data from multiple sources.
Key features include:
Flattening: Nested maps, slices, and arrays can be converted into a flat map[string]string using dot notation for maps and index notation for arrays/slices. For example, {"db": {"hosts": ["a", "b"]}} becomes {"db.hosts[0]": "a", "db.hosts[1]": "b"}.
Path handling: The package defines a Path abstraction that represents hierarchical keys as a sequence of typed segments (map keys or array indices). Paths can be split from strings like "foo.bar[0]" or joined back into their string form.
Storage: A Storage type manages a collection of flattened key/value pairs. It builds and maintains a hierarchical tree internally to prevent property conflicts (e.g., treating the same key as both a map and a value). Storage also associates values with the files they originated from, which allows multi-file merging and provenance tracking.
Querying: The Storage type provides helper methods for retrieving values, checking for the existence of keys, enumerating subkeys, and iterating in a deterministic order.
Typical use cases:
- Normalizing configuration files from different sources into a flat key/value map for comparison, merging, or diffing.
- Querying nested data using simple string paths without dealing with reflection or nested map structures directly.
- Building tools that need to unify structured data from multiple files while preserving provenance information and preventing conflicts.
Overall, barky acts as a bridge between deeply nested structured data and flat, queryable representations that are easier to work with in configuration management, testing, or data transformation pipelines.
Index ¶
- func FlattenMap(m map[string]any) map[string]string
- func FlattenValue(key string, val any, result map[string]string)
- func JoinPath(path []Path) string
- type Path
- type PathType
- type Storage
- func (s *Storage) AddFile(file string) int8
- func (s *Storage) Data() map[string]string
- func (s *Storage) Get(key string, def ...string) string
- func (s *Storage) Has(key string) bool
- func (s *Storage) Keys() []string
- func (s *Storage) RawData() map[string]ValueInfo
- func (s *Storage) RawFile() map[string]int8
- func (s *Storage) Set(key string, val string, file int8) error
- func (s *Storage) SubKeys(key string) (_ []string, err error)
- type ValueInfo
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FlattenMap ¶
FlattenMap takes a nested map[string]any and flattens it into a map[string]string. Nested maps are represented using dot-notation (e.g. "parent.child"), and slices/arrays are represented using index-notation (e.g. "array[0]"). The following rules apply:
- Nil values (both untyped and typed nil) are represented as "<nil>".
- Nil elements in slices/arrays are preserved and represented as "<nil>".
- Empty maps are represented as "{}".
- Empty slices/arrays are represented as "[]".
- All primitive values are converted to strings using cast.ToString.
func FlattenValue ¶
FlattenValue recursively flattens a value (map, slice, array, or primitive) into the result map under the given key. Nested structures are expanded using dot notation (for maps) and index notation (for slices/arrays).
Types ¶
type Path ¶
type Path struct {
// Whether the element is a key or an index.
Type PathType
// Actual key or index value as a string.
// For PathTypeKey, it's the key string;
// for PathTypeIndex, it's the index number as a string.
Elem string
}
Path represents a single segment in a parsed key path. A path is composed of multiple Path elements that can be joined or split. For example, "foo.bar[0]" parses into:
[{Type: PathTypeKey, Elem: "foo"},
{Type: PathTypeKey, Elem: "bar"},
{Type: PathTypeIndex, Elem: "0"}].
func SplitPath ¶
SplitPath parses a hierarchical key string into a slice of Path objects. It supports dot-notation for maps and bracket-notation for arrays. Examples:
"foo.bar[0]" -> [{Key:"foo"}, {Key:"bar"}, {Index:"0"}]
"a[1][2]" -> [{Key:"a"}, {Index:"1"}, {Index:"2"}]
Rules:
- Keys must be non-empty strings without spaces.
- Indices must be unsigned integers (no sign, no decimal).
- Empty maps/slices are not special-cased here.
- Returns an error if the key is malformed (e.g. unbalanced brackets, unexpected characters, or empty keys if disallowed).
type PathType ¶
type PathType int8
PathType represents the type of a path element in a hierarchical key. A path element can either be a key (map field) or an index (array/slice element).
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage manages hierarchical key/value data with structural validation. It provides:
- A hierarchical tree (root) for detecting structural conflicts.
- A flat map (data) for quick value lookups.
- An empty map (empty) for representing empty containers like "[]" or "{}".
- A file map for mapping file names to numeric indexes, allowing traceability.
Invariants:
- `root` stores only the tree structure (no leaf values).
- `data` stores leaf key-value pairs.
- `empty` stores leaf paths that represent empty arrays/maps or nil values.
func (*Storage) AddFile ¶
AddFile registers a file name in the Storage and assigns it a unique int8 index if not already registered. Returns the index assigned to the given file.
func (*Storage) Data ¶
Data returns a simplified flattened key → string value mapping, omitting file index information.
func (*Storage) Get ¶
Get retrieves the value associated with the given flattened key. If the key is not found and a default value is provided, the default is returned instead. Only the first default value is considered.
func (*Storage) Has ¶
Has checks whether a given key (or path) exists in the Storage. Returns true if the key refers to either a stored value, an empty container, or a valid intermediate node in the hierarchy.
func (*Storage) Keys ¶
Keys returns all flattened keys currently stored in Storage, sorted lexicographically for consistent iteration.
func (*Storage) RawData ¶
RawData exposes the internal flattened key → ValueInfo mapping, combining both data and empty containers if any exist.
WARNING: This method leaks internal state and should be used with caution (e.g., for debugging or low-level access).
func (*Storage) Set ¶
Set inserts or updates a flattened key with the given value and the index of the file it originated from.
It validates the path to prevent structural conflicts:
- Cannot store a value where a container node already exists.
- Cannot change an array branch into a map branch or vice versa.
Returns an error if a structural conflict is detected.
func (*Storage) SubKeys ¶
SubKeys returns the immediate child keys under the given hierarchical path.
For example, if Storage contains keys:
a.b.c a.b.d
then SubKeys("a.b") returns ["c", "d"].
If the path points to a leaf value or structural conflict, an error is returned. If the path does not exist, it returns nil.