package cnf import ( lib "github.com/xdrm-brackets/nix-amer/internal/cnf/parser/nginx" "io" "strings" ) type nginx struct { data *lib.Line parsed bool } // ReadFrom implements io.ReaderFrom func (d *nginx) ReadFrom(_reader io.Reader) (int64, error) { d.data = new(lib.Line) // 1. get nginx decoder decoder := lib.NewDecoder(_reader) err := decoder.Decode(d.data) if err != nil { return 0, err } d.parsed = true return 0, nil } // WriteTo implements io.WriterTo func (d *nginx) WriteTo(_writer io.Writer) (int64, error) { encoder := lib.NewEncoder(_writer) return 0, encoder.Encode(d.data) } // browse returns the target of a dot-separated path (as an interface{} chain where the last is the target if found) // if is true, create if does not exist func (d *nginx) browse(_path string, create ...bool) (*lib.Line, bool) { mustCreate := len(create) > 0 && create[0] // 1. extract path path := strings.Split(_path, ".") // 2. nothing if len(path) < 1 { return &lib.Line{}, true } // 3. init output chain current := d.data // 4. iterate over path / nested fields l := len(path) for i, field := range path { // 5. intermediary fields (sections) if i < l-1 { found := false for _, child := range current.Lines { if child.Type == lib.SECTION && len(child.Components) > 0 && child.Components[0] == field { found = true current = child break } } if found { continue } // create section if mustCreate { sec := &lib.Line{ Type: lib.SECTION, Components: []string{field}, Lines: make([]*lib.Line, 0), } current.Lines = append(current.Lines, sec) current = sec continue } // not found and not create return nil, false } // 6. last field (assignment) for _, child := range current.Lines { if child.Type == lib.ASSIGNMENT && len(child.Components) > 0 && child.Components[0] == field { return child, true } } // create assignment if mustCreate { assignment := &lib.Line{ Type: lib.ASSIGNMENT, Components: []string{field, ""}, Lines: nil, } current.Lines = append(current.Lines, assignment) return assignment, true } // not found and not create return nil, false } return nil, false } // Get returns the value of a dot-separated path, and if it exists func (d *nginx) Get(_path string) (string, bool) { // 1. browse path last, found := d.browse(_path, true) if !found || len(last.Components) < 2 { return "", false } // 2. Get last field return last.Components[1], true } // Set the value of a dot-separated path, and creates it if not found func (d *nginx) Set(_path, _value string) bool { // 1. browse path last, found := d.browse(_path, true) if !found || len(last.Components) < 2 { return false } // 2. Set value last.Components[1] = _value return true }