jacl

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Jan 22, 2022 License: MIT Imports: 9 Imported by: 0

README

Build Status Coverage Status

Go-Jacl

This module implements the base and the extended specifications of the Jacl configuration language.

Change Log

0.2.0 (2019-07-06)
0.1.0 (2019-06-30)
  • Initial release.

Installation

Requirements:

  • Go 1.12 or better (not tried with versions below).

The following should be enough to install it:

go get github.com/yuce/go-jacl

Jacl Specification

See the Jacl configuration language for information about the configuration language.

Usage

Go-Jacl has a single function, jacl.Unmarshal, to decode configuration from text into a map[string]interface{} or a pointer to a struct.

Example:

text := `
    // Sample configuration

    bind: "https://01.pilosa.local:10101"
    data-dir: "/tmp/data"

    cluster: {
        coordinator: true    
    }

    tls: {
        certificate: "pilosa.local.crt"
        key: "pilosa.local.key"
        skip-verify: true
    }

    gossip: {
        seeds: [
            "01.pilosa.local:15000"
            "02.pilosa.local:15000"
        ]
        port: 15000
        key: "pilosa.local.gossip32"
    }
`

// Decode to a map
config := map[string]interface{}{}
err := jacl.Unmarshal(text, &config)
if err != nil {
    // handle the error
}

// Decode to a struct
type ClusterConfig struct {
    Coordinator     bool   `jacl:"coordinator"`
    SomeLegacyField string `jacl:"-"` // This field is skipped.
}

type TLSConfig struct {
    CertificatePath string `jacl:"certificate"`
    KeyPath         string `jacl:"key"`
    SkipVerify      bool   `jacl:"skip-verify"`
}

type GossipConfig struct {
    Seeds   []string `jacl:"seeds"`
    Port    int      `jacl:"port"`
    KeyPath string   `jacl:"key"`
}

type Config struct {
    DataDir string        `jacl:"data-dir"`
    Bind    string        `jacl:"bind"`
    Cluster ClusterConfig `jacl:"cluster"`
    TLS     TLSConfig     `jacl:"tls"`
    Gossip  GossipConfig  `jacl:"gossip"`
}

config := Config{}
err := jacl.Unmarshal(text, &config)
if err != nil {
    // handle the error
}

Decoding Into Structs

When decoding into structs:

  • Only exported fields of the struct are considered.
  • All fields of the struct must have corresponding values in the configuration, otherwise an error is returned.
  • The field name must match the property/map key, unless jacl:"KEY_NAME" used in the field definition. In that case the configuration key KEY_NAME is matched to the corresponding field.
  • Use jacl:"-" in order to skip a field.
Supported Go Data Types

The following are the Go data types which are mapped from their Jacl counterparts. Note that trying to unmarshal to a field with a different type (e.g., a signed integer to uint vice versa, or a float to int) returns an error:

Jacl Type Go Type Allowed Field Types
String string string
Unsigned integer uint64 uint, uint8, uint16, uint32, uint64
Signed integer int64 int, int8, int16, int32, int64
Float float64 float32, float64
Boolean bool bool
Array []interface{} []interface{}, []T
Map map[string]interface{} map[string]interface{}, map[string]T

In the table above T is one of bool, string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64.

Field Underflow/Overflow

If unmarshalling to a field underflows or overflows the chosen data type, then an error is returned:

type Config struct {
    Number int8
}
config := Config{}
err := jacl.Unmarshal("Number: 128", &config)

err above is not nil, since 128 is bigger than math.MaxInt8.

Default Struct Values

Go-Jacl requires every field of a struct to be set on unmarshal unless a field is skipped with jacl:"-". So, if a property is missing in the configuration jacl.Unmarshal would return an error.

Consider the following struct:

type C struct {
    F1 string
    F2 int
}

In order to have defaults for fields F1 and F2, you can pass a map with defaults to jacl.Unmarshal:

defaults := map[string]interface{}{
    "F1": "default string",
    "F2": 54,
}

text := `
    F1: "modified string"
`
err := jacl.Unmarshal(text, &defaults)
if err != nil {
    // handle the error
}

The defaults map contains the following values after unmarshalling:

map[string]interface{}{
    "F1": "modified string",
    "F2": int64(54),
}

Since the properties for all fields are set, we can pass that map to jacl.UnmarshalStruct:

config := C{}
err = jacl.UnmarshalStruct(defaults, &config)
if err != nil {
    t.Fatal(err)
}

The value of config is:

C{
    F1: "modified string",
    F2: 54,
}
Unmarshaling From Multiple Texts

Suppose we separated our configuration into multiple files since there are lots of properties to be set. Instead of having separate structs for each file, we want to have a single struct. We can use the same jack.UnmarshalStruct technique in the previous section to accomplish that.

This is the sample struct:

type C struct {
    F1 string
    F2 string
    // ...
    F9 string
}

These are the contents of the configuration files:

texts := []string{
    `F1: "field 1"`,
    `F2: "field 2"`,
    // ...
    `F9: "field 9"`,
}

We use the same map to unmarshal each text:

props := map[string]interface{}{}
for _, text := range texts {
    err := jacl.Unmarshal(text, &props)
    if err != nil {
        // handle the error
    }
}

Finally, unmarshal the map to a struct:

config := C{}
err := jacl.UnmarshalStruct(props, &config)
if err != nil {
    // handle the error
}

TODO

  • Maps of typed slices and slices of typed maps are not yet supported when unmarshalling struct fields. E.g., Field1 []map[string]interface{} is OK, but Field2 []map[string]int is not supported yet.

License

Copyright (c) 2019-2021 Yuce Tekol. Licensed under MIT.

Documentation

Index

Constants

View Source
const MaxInt = int(MaxUint >> 1)
View Source
const MaxUint = ^uint(0)
View Source
const MinInt = -MaxInt - 1

Variables

This section is empty.

Functions

func Unmarshal

func Unmarshal(text string, v interface{}) (err error)

Unmarshal decodes the Jacl configuration given in `text` to v. `v` should be either a map[string]interface{}, or it should be a pointer to a struct.

func UnmarshalStruct

func UnmarshalStruct(m map[string]interface{}, v interface{}) (err error)

UnmarshalStruct decodes the map given in m to v. v should be a pointer to a struct.

Types

This section is empty.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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