package configkit import "gitea.maximumdirect.net/eric/ConfigKit/internal/document" func metadataFromDecoded(decoded decodedConfiguration) Metadata { metadata := Metadata{ fields: make(map[string]FieldInfo), history: make(map[string][]Change), } baseline := make(map[string]*document.Node) indexDocument(decoded.baseline, Path{}, baseline) for pointer := range baseline { path, err := ParsePath(pointer) if err != nil { continue } metadata.history[pointer] = append(metadata.history[pointer], Change{ Path: path, Origin: Origin{Layer: LayerDefault}, }) } for pointer, input := range decoded.presence { path, err := ParsePath(pointer) if err != nil { continue } origin := Origin{Layer: LayerBase, Locations: []Location{{ SourceID: input.location.SourceID, Line: input.location.Line, Column: input.location.Column, }}} change := Change{Path: path, Origin: origin} if _, ok := baseline[pointer]; ok { change.Previous = []Origin{{Layer: LayerDefault}} } metadata.history[pointer] = append(metadata.history[pointer], change) } collectFieldInfo(decoded.final, Path{}, decoded, metadata.fields) return metadata } func collectFieldInfo(node *document.Node, path Path, decoded decodedConfiguration, fields map[string]FieldInfo) { pointer := path.String() _, explicit := decoded.presence[pointer] fields[pointer] = FieldInfo{ Explicit: explicit, Null: node.Kind == document.Null, Origin: cloneOrigin(decoded.origins[pointer]), } switch node.Kind { case document.Mapping: for _, entry := range node.Mapping { collectFieldInfo(entry.Value, path.Key(entry.Key), decoded, fields) } case document.Sequence: for index, child := range node.Sequence { collectFieldInfo(child, path.Index(index), decoded, fields) } } } func indexDocument(node *document.Node, path Path, index map[string]*document.Node) { if node == nil { return } index[path.String()] = node switch node.Kind { case document.Mapping: for _, entry := range node.Mapping { indexDocument(entry.Value, path.Key(entry.Key), index) } case document.Sequence: for position, child := range node.Sequence { indexDocument(child, path.Index(position), index) } } } func cloneMetadata(metadata Metadata) Metadata { if metadata.fields == nil && metadata.history == nil { return Metadata{} } cloned := Metadata{ fields: make(map[string]FieldInfo, len(metadata.fields)), history: make(map[string][]Change, len(metadata.history)), } for path, info := range metadata.fields { cloned.fields[path] = cloneFieldInfo(info) } for path, changes := range metadata.history { clonedChanges := make([]Change, len(changes)) for index, change := range changes { clonedChanges[index] = cloneChange(change) } cloned.history[path] = clonedChanges } return cloned }