nix-amer/internal/cnf/parser/nginx/encoder.go

127 lines
2.5 KiB
Go

package nginx
import (
"fmt"
"io"
)
var (
defaultPrefix = ""
defaultIndent = "\t"
)
// encoder implements parser.Encoder
type encoder struct {
writer io.Writer
prefix []byte
indent []byte
}
func (e *encoder) SetIndent(prefix, indent string) {
e.prefix = make([]byte, 0)
e.prefix = append(e.prefix, []byte(prefix)...)
e.indent = make([]byte, 0)
e.indent = append(e.indent, []byte(indent)...)
}
func (e *encoder) Encode(v interface{}) error {
// default indentation
if e.prefix == nil || e.indent == nil {
e.SetIndent(defaultPrefix, defaultIndent)
}
// check 'v'
vcast, ok := v.(*Line)
if !ok {
return ErrInvalidReceiver
}
// empty config
if len(vcast.Lines) < 1 {
return nil
}
// actual indentation level
indent := 0
// actual lines to write
stack := make([]*Line, 0)
// push nginx.Lines in reverse order
for l := len(vcast.Lines) - 1; l >= 0; l-- {
stack = append(stack, vcast.Lines[l])
}
for len(stack) > 0 {
// pop stack
line := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// line representation
repr := make([]byte, 0)
if line == nil { // section end
indent--
}
// 1. add indentation
repr = append(repr, []byte(e.prefix)...)
for i := 0; i < indent; i++ {
repr = append(repr, []byte(e.indent)...)
}
// 2. section end
if line == nil {
repr = append(repr, []byte("}\n\n")...)
// Note: new line after section for readability
// 3. comments
} else if line.Type == COMMENT {
repr = append(repr, []byte(fmt.Sprintf("#%s\n", line.Components[0]))...)
} else if line.Type == COLONCOMMENT {
repr = append(repr, []byte(fmt.Sprintf(";%s\n", line.Components[0]))...)
// 4.assignments
} else if line.Type == ASSIGNMENT {
repr = append(repr, []byte(fmt.Sprintf("%s\t\t%s;\n", line.Components[0], line.Components[1]))...)
// 5. include
} else if line.Type == INCLUDE {
repr = append(repr, []byte(fmt.Sprintf("include %s;\n", line.Components[0]))...)
// 6. section
} else {
// push to stack
stack = append(stack, nil)
// push children lines in reverse order
if len(line.Lines) > 0 {
for l := len(line.Lines) - 1; l >= 0; l-- {
stack = append(stack, line.Lines[l])
}
}
if len(line.Components) > 1 {
repr = append(repr, []byte(fmt.Sprintf("%s %s {\n", line.Components[0], line.Components[1]))...)
} else {
repr = append(repr, []byte(fmt.Sprintf("%s {\n", line.Components[0]))...)
}
indent++
}
_, err := e.writer.Write(repr)
if err != nil {
return err
}
}
return nil
}