Documentation ¶
Overview ¶
Package gofigure parses configuration files. An application might use this instead of parsing JSON, YAML, or many other alternatives.
Our primary goals include:
- Provide a human-friendly configuration file format.
- Minimize third-party dependencies.
Our definition of "human-friendly" is opinionated. It basically means a configuration file format that supports comments, and is not sensitive to whitespace or indentation.
The motivation to avoid third-party dependencies is to minimize the amount of code that needs to be audited, in particular for secure applications where the size of a software bill of materials may be a concern.
To accomplish these goals, the configuration syntax is based on the Go (golang) language. This allows us to use Go's parser, already part of the standard library, rather than third-party imports. And Go's syntax meets our standard for user-friendliness.
Example Configuration ¶
The supported syntax supports, for example,
local = env { port: 8080, host: "127.0.0.1", } prod = env { port: 80, host: "0.0.0.0", } // environment tells the application which of the envs to use by default. environment = local
Example Application Code ¶
Gofigure provides a multiplexer, with a simple scheme in which a handler is called for each value in a configuration file.
A handler is called if it is the best match for a "path" in the configuration file. In the example above, "local = env {}" is a fully-qualified path that matchs only the first item, while "env" is a path that matches all the `env{...}` objects.
mux := gofigure.Mux{ "env": gofigure.Object(handleEnv), // ... }
Above, "env" is the path to match, `HandleEnv` is the application-provided handler function, and `gofigure.Object` instructs gofigure to unmarshal the value as an object. Under the hood, gofigure uses "encoding/json" for decoding into Go structs, and Object, Array, and Scalar tell gofigure what kind of value to expect.
// env is the Go struct to decode into type env struct { Host string Port int } // handleEnv shows the signature of a handler function for env objects. func handleEnv(r gofigure.Route, v env) error {...}
For each match in the configuration file, a handler is passed the full route and value. In this example, a route would be ["local", "=", "env", "{}"] and the same handler would be called again with a route starting "prod".
Index ¶
- func FileToJSON(out io.Writer, filename string, opt ...Option) error
- func NewConfiguration() *gofigure
- func ToJSON(out io.Writer, in io.Reader, opt ...Option) (err error)
- type Assign
- type Compose
- type Concat
- type DecodeHandler
- type Error
- type Handler
- type Mux
- type Option
- type OuterBracket
- type ParseOption
- type Route
- type Stream
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewConfiguration ¶
func NewConfiguration() *gofigure
Types ¶
type Assign ¶
An Assignment is called when gofigure parses an ast.ValueSpec, such as "x = something".
type Compose ¶
A Compose callback is called on an ast.KeyValueExpr, such as "foo{first: x, second: y}".
type Concat ¶
A Concat callback is called on an ast.CompositeLit, such as "f(1, 2, 3)"
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
type Handler ¶
type Handler interface {
// contains filtered or unexported methods
}
A Handler is created by passing a function to Scalar, Array, or Object.
func Array ¶
Array defines a handler which will be passed gofigure payloads. To produce the payload, gofigure encodes a value as JSON, and decodes the JSON into a variable. The JSON is encoded within square brackets, so it is treated a a single variable with zero or more items.
func Object ¶
Object defines a handler which will be passed gofigure payloads. To produce the payload, gofigure encodes a value as JSON, and decodes the JSON into a variable. The JSON is encoded within curly brackets, so it is treated a a single struct variable.
type Mux ¶
A Mux is multiplexer that calls a handler for each configuration payload parsed. The Mux can have multiple routes, each with a handler. During [Parse], the Mux attempts to match each item in a configuraiton file with an appropriate handler.
Example ¶
package main import ( "fmt" "strings" "src.d10.dev/gofigure" ) const configfile = ` local = env { port: 8080, host: "127.0.0.1", } prod = env { port: 80, host: "0.0.0.0", } // environment tells the application which of the envs to use by default. environment = local ` type env struct { Host string Port int } func HandleEnv(r gofigure.Route, v env) error { fmt.Printf("env %q is %s:%d\n", r[0], v.Host, v.Port) return nil } func HandleEnvironment(_ gofigure.Route, v string) error { fmt.Printf("default environment is %q\n", v) return nil } func main() { mux := gofigure.Mux{ "environment": gofigure.Scalar(HandleEnvironment), "env": gofigure.Object(HandleEnv), } err := mux.Parse("configfile", mux.Source(strings.NewReader(configfile))) if err != nil { fmt.Println(err) } }
Output: env "local" is 127.0.0.1:8080 env "prod" is 0.0.0.0:80 default environment is "local"
func (Mux) Parse ¶
func (m Mux) Parse(filename string, opt ...ParseOption) error
Parse attempts to visit each item in a configuration file, decoding a value and invoking a hander for each item.
func (*Mux) Source ¶
func (*Mux) Source(r io.Reader) ParseOption
type Option ¶
type Option func(*walk) error
func WithOuterBracket ¶
func WithOuterBracket(b OuterBracket) Option
type OuterBracket ¶
type OuterBracket uint
const ( OuterBracketNone OuterBracket = iota OuterBracketArray OuterBracketObject )
type Route ¶
type Route []string
A Route provides a handler with information about where a payload appears in configuration.
If configuration is `f = g(x)`, the route will include "f", "=", "g", and "()".
if configuration is only `g{x}`, the route will include "g" and "{}".
if configuration is `f = x`, the route will include "f" and "=".