sc

package module
v0.0.0-...-a3e9adc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2021 License: MIT Imports: 10 Imported by: 1

README

SC language support for Go

Go Reference sc-lang

The sc package provides support for the Simple Config (SC) language in Go. It supports decoding SC data into Go values.

Installation

go get github.com/sc-lang/go-sc

Usage

See the package documentation for full usage details.

This package works in a similar way to the encoding/json package in the standard library.

Example

Here is an example of decoding some SC data into a Go struct.

package main

import (
	"fmt"

	"github.com/sc-lang/go-sc"
)

var scData = []byte(`{
  name: "foo"
  memory: 256
  required: true
}`)

type Config struct {
    Name       string                 // Implicit key name
    Memory     int    `sc:"memory"`   // Explicit key name
    IsRequired bool   `sc:"required"` // Rename key
}

func main() {
	var config Config
	err := sc.Unmarshal(scData, &config)
	if err != nil {
		fmt.Printf("error: %v\n", err)
	}
	fmt.Printf("%+v\n", config)
}

This produces the output:

{Name:foo Memory:256 IsRequired:true}

Documentation

Overview

Package sc implements support for the SC language in Go. It allows for decoding SC data into Go values.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(v interface{}) ([]byte, error)

Marshal encodes v into an SC representation and returns the data. v must be a struct or a map or a pointer to one of these types.

If a value implements the Marshaler interface, Marshal calls its MarshalSC method to produce an SC node. If the value implements the encoding.TextMarshaler interface, Marshal calls its MarshalText method and encodes the result as an SC string.

Struct fields are only encoded if they are exported and use the field name as the key by default. Struct fields can be customized using the "sc" key in the field's tag. The tag value is the name of the field optionally followed by a comma-separated list of options. The name of the field can be omitted to specify options without overridding the default field name. If the tag value is "-", then the field will be omitted.

The "omitempty" option causes the field to be omitted if it is an empty value. Empty values are false, 0, a nil pointer, a nil interface value, and an empty array, slice, map, or string.

Example
type Config struct {
	Name       string `sc:"name"`
	Memory     int    `sc:"memory"`
	IsRequired bool   `sc:"required"`
}
config := Config{
	Name:       "foo",
	Memory:     256,
	IsRequired: true,
}
b, err := sc.Marshal(config)
if err != nil {
	fmt.Printf("error: %v\n", err)
}
fmt.Printf("%s\n", b)
Output:

{
  name: "foo"
  memory: 256
  required: true
}

func Unmarshal

func Unmarshal(data []byte, v interface{}, opts ...UnmarshalOption) error

Unmarshal parses the SC-encoded data and stores the result in the value pointed to by v. If v is nil or not a pointer, Unmarshal returns InvalidUnmarshalError. The top level SC value must be a dictionary. Therefore, v must point to either a map or a struct that is capable of holding the SC data.

Unmarshal will initialize any nested maps, slices, and pointers it encounters as needed. If a value implements the Unmarshaler interface, Unmarshal calls its UnmarshalSC method with the SC node and any variable values provided to Unmarshal. If the value implements the encoding.TextUnmarshaler and the SC value is a string, Unmarshal call the value's UnmarshalText method with the unquoted form of the SC string.

Struct fields are only unmarshaled if they are exported and are unmarshaled using the field name as the default key. Custom keys may be defined via the "sc" name in the field tag.

Unmarshal supports unmarshaling into node types defined in the scparse package. This can allow for delaying the unmarshaling process and for accessing parts of the node like comments. UnmarshalNode may be used to continue the unmarshaling process and unmarshal the node into a Go value.

If the target value is an empty interface, Unmarshal stores SC values into the following Go values:

nil for SC null
bool for SC booleans
int for SC numbers that can be represented as integers
float64 for all other SC numbers
[]interface{} for SC lists
map[string]interface{} for SC dictionaries

If a SC value is not appropriate for a given target type, Umarshal skips that field and completes the unmarshaling as best it can. Unmarshal keeps track of all non-critical errors encountered and returns a sc.Errors which is a list of error values that can be checked individually. If an error is encountered while parsing the SC value, Unmarshal will immediately return the parse error, which will likely be a *scparse.Error.

Unmarshal can optionally be provided additional option arguments that modify the unmarshal process. For example, sc.WithVariables can be used to provide values for SC variables that will be expanded during unmarshaling. See the documentation for each UnmarshalOption to learn more.

Example
scData := []byte(`{
  name: "foo"
  memory: 256
  required: true
}`)
type Config struct {
	Name       string `sc:"name"`
	Memory     int    `sc:"memory"`
	IsRequired bool   `sc:"required"`
}
var config Config
err := sc.Unmarshal(scData, &config)
if err != nil {
	fmt.Printf("error: %v\n", err)
}
fmt.Printf("%+v\n", config)
Output:

{Name:foo Memory:256 IsRequired:true}
Example (Variables)
scData := []byte(`{
  code: ${id}
  path: "/home/${user}/data"
}`)
type Config struct {
	Code int    `sc:"code"`
	Path string `sc:"path"`
}
var config Config
vars := sc.MustVariables(map[string]interface{}{
	"id":   145,
	"user": "ted",
})
err := sc.Unmarshal(scData, &config, sc.WithVariables(vars))
if err != nil {
	fmt.Printf("error: %v\n", err)
}
fmt.Printf("%+v\n", config)
Output:

{Code:145 Path:/home/ted/data}

func UnmarshalNode

func UnmarshalNode(n scparse.ValueNode, v interface{}, opts ...UnmarshalOption) error

UnmarshalNode is like Unmarshal but it takes a ValueNode instead of SC-encoded data.

If an SC value was previously unmarshaled into a node, UnmarshalNode can be used to unmarshal the node into a Go value.

See the documentation for Unmarshal for details on the unmarshal process.

Example
scData := []byte(`{
  name: "test"
  ports: [
    { src: 8080, dst: 8080 }
	{ src: 80, dst: 80 }
  ]
}`)
type Config struct {
	Name  string
	Ports scparse.ValueNode
}
var config Config
err := sc.Unmarshal(scData, &config)
if err != nil {
	fmt.Printf("error: %v\n", err)
}
// Can inspect node
fmt.Printf("%v\n", config.Ports.Type())

// Finish the unmarshaling process
type Port struct {
	Src int
	Dst int
}
var ports []Port
err = sc.UnmarshalNode(config.Ports, &ports)
if err != nil {
	fmt.Printf("error: %v\n", err)
}
fmt.Printf("%+v\n", ports)
Output:

List
[{Src:8080 Dst:8080} {Src:80 Dst:80}]

Types

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

A Decoder reads and decodes SC values from an input stream.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a new decoder that reads from r.

The decoder will read the entire contents of r and expects r to only contain valid SC data.

func (*Decoder) Decode

func (dec *Decoder) Decode(v interface{}) error

Decode reads the SC-encoded value from its input and stores it in the value pointed to by v.

See the documentation for Unmarshal for details about the decoding process.

func (*Decoder) DisallowUnknownFields

func (dec *Decoder) DisallowUnknownFields(b bool)

DisallowUnknownFields controls how the Decoder will behave when the destination is a struct and the input contains dictionary keys which do not match any non-ignored, exported fields in the destination.

By default, unknown fields are silently ignored. If set to true, unknown fields will instead cause an error to be returned during decoding.

func (*Decoder) DisallowUnknownVariables

func (dec *Decoder) DisallowUnknownVariables(b bool)

DisallowUnknownVariables controls how the Decoder will behave when a variable is being decoded and no matching variable value is found.

By default, unknown variables are silently ignored. If set to true, unknown variables will instead cause an UnmarshalUnknownVariableError to be returned during decoding.

How variables are ignored depends on where the variable occurs in the SC source. If the variable is a standalone value, the zero value of the destination Go value will be used. If the variable is interpolated in a string, it will be treated as an empty string.

func (*Decoder) Variables

func (dec *Decoder) Variables(vars Variables)

Variables sets the variables that should be used during decoding.

type Errors

type Errors []error

Errors is a list of errors that occurred during unmarshaling.

Where possible, Unmarshal tries to continue unmarshaling as best it can and report all encountered errors. This way multiple errors can be discovered at once.

Each error can be inspected individually to obtain more details about it.

func (Errors) Error

func (e Errors) Error() string

type InvalidUnmarshalError

type InvalidUnmarshalError struct {
	Type reflect.Type // Type that was passed to Unmarshal.
}

InvalidUnmarshalError describes an invalid argument passed to Unmarshal. (The argument to Unmarshal must be a non-nil pointer.)

func (*InvalidUnmarshalError) Error

func (e *InvalidUnmarshalError) Error() string

type MarshalError

type MarshalError struct {
	Value   reflect.Value // The value that caused the error.
	Context string        // The details of the error.
}

MarshalError is returned by Marshal and describes an error that occurred during marshaling.

func (*MarshalError) Error

func (e *MarshalError) Error() string

type Marshaler

type Marshaler interface {
	MarshalSC() (scparse.ValueNode, error)
}

Marshaler is the interface implemented by types that can marshal themselves into an SC value.

type UnmarshalOption

type UnmarshalOption func(*decoder)

UnmarshalOption is an option that can be provided to Unmarshal to customize behaviour during the unmarshaling process.

The signature contains an unexported type so that only options defined in this package are valid.

func WithDisallowUnknownFields

func WithDisallowUnknownFields(b bool) UnmarshalOption

WithDisallowUnknownFields controls how Unmarshal will behave when the destination is a struct and the input contains dictionary keys which do not match any non-ignored, exported fields in the destination.

By default, unknown fields are silently ignored. If set to true, unknown fields will instead cause an error to be returned during unmarshaling.

func WithDisallowUnknownVariables

func WithDisallowUnknownVariables(b bool) UnmarshalOption

WithDisallowUnknownVariables controls how Unmarshal will behave when a variable is being decoded and no matching variable value is found.

By default, unknown variables are silently ignored. If set to true, unknown variables will instead cause an UnmarshalUnknownVariableError to be returned during unmarshaling.

How variables are ignored depends on where the variable occurs in the SC source. If the variable is a standalone value, the zero value of the destination Go value will be used. If the variable is interpolated in a string, it will be treated as an empty string.

func WithVariables

func WithVariables(vars Variables) UnmarshalOption

WithVariables sets the variables that should be used during unmarshaling.

type UnmarshalTypeError

type UnmarshalTypeError struct {
	NodeType scparse.NodeType // Type of the AST node.
	Type     reflect.Type     // Type of Go value.
	Pos      scparse.Pos      // Position of the SC node in the input text.
	Struct   string           // Name of the struct type containing the field.
	Field    string           // The full path from the root struct to the field.
}

UnmarshalTypeError describes a SC value that was not appropriate for a value of a specified Go type.

func (*UnmarshalTypeError) Error

func (e *UnmarshalTypeError) Error() string

type UnmarshalUnknownVariableError

type UnmarshalUnknownVariableError struct {
	Variable string      // The name of the variable.
	Pos      scparse.Pos // Position of the SC node in the input text.
}

UnmarshalUnknownVariableError describes a SC variable that did not have an associated value during unmarshaling.

func (*UnmarshalUnknownVariableError) Error

type Unmarshaler

type Unmarshaler interface {
	UnmarshalSC(scparse.ValueNode, Variables) error
}

Unmarshaler is the interface implemented by types that can unmarshal a SC description of themselves. This can be used to customize the unmarshaling process for a type.

type Variables

type Variables struct {
	// contains filtered or unexported fields
}

Variables represents a set of variables provided during the unmarshaling process. It allows for looking up a variable value from a VariableNode.

The zero value is a valid Variables instance and represents an empty set of variables.

func MustVariables

func MustVariables(v interface{}) Variables

MustVariables is like NewVariables but panics if v is an invalid type.

func NewVariables

func NewVariables(v interface{}) (Variables, error)

NewVariables creates a new Variables instance using the variable values v. v must be a map whose keys are a string type.

If v is not a valid type, an error will be returned. NewVariables(nil) returns the zero value.

func (Variables) Lookup

func (vars Variables) Lookup(n *scparse.VariableNode) (interface{}, bool)

Lookup finds the variable value matching n if it exists. The second return value can be used to check if the variable was found.

Directories

Path Synopsis
Package scparse implements parsing and formatting of SC files.
Package scparse implements parsing and formatting of SC files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL