config 0.1.3

A library to parse and load configuration files

Crate config [] [src]

A library to parse and load configuration files.

This library parses and loads configuration files in much the same way as C/C++'s libconfig. At this time, it can only read and load configurations, but future plans include a much richer user API to allow other forms of interaction, such as manipulating values, writing the current configuration to a file, etc.

Getting started

A configuration file consists of a group of settings. A setting is a key/value pair, where the key is a string of the form [a-zA-Z][-a-zA-Z0-9_]*, and the value is anything represented by types::Value. In a configuration file, setting/value pairs are written as setting_name = value;. Possible values include primitive integer and floating point types, strings, arrays, lists, etc.

The library provides a bunch of methods to read the configuration data in the reader module. The possibilities include reading from a string, from a file, or from anything that implements the Read trait.

As of now, every reader will first attempt to read the whole configuration into memory, and only begins parsing once everything was read.

In case of error, the parser returns a config::error. On success, the parser returns a Config, which can then be used to browse the loaded data.

Browsing is typically done with the lookup_* methods implemented by Config. The lookup methods work with paths. Essentially, a path unambiguously describes the location of a setting.

For example, consider this input configuration file:

 title = "My HTTP server";
 listen_ports = [ 80, 443 ];
 misc = {
     owner = "Chuck Norris";
     location = "CA";
     contact = {
         phone = "415-256-9999";
         // This is an array. Arrays start with `[` and end with `]`
         // Arrays are homogeneous and can only hold scalar data types.
         // See types::ScalarValue for further information
         emails = ["chuck@norris.com", "chuck.norris@gmail.com"];
     };
 };

At the top level, we have 3 settings: title, listen_ports and misc. misc is itself a group of settings. Each value in this configuration is reachable by a unique path of settings to follow. Each setting in a path is separated by .

Example: The path misc.contact.phone identifies the setting with value 415-256-9999.

Array and list types are indexed using [i] in a path.

Example: The path listen_ports.[1] identifies the setting with value 443.

Example: The path misc.contact.emails.[0] identifies the setting with value chuck@norris.com

Lists, as opposed to arrays, are heterogeneous and can store any data type, including other lists. Here's a setting consisting of a heterogeneous list:

 // This is a list. Lists start with `(` and end with `)`
 // Lists are heterogeneous and can store any data type, including other lists
 a_setting = ("a string", // The first element is a string
              ((1, 2, 3)), // The 2nd element is a list storing a list of 3 integers
              misc = { x = 4; y = 3; } // 3rd element: a group
             );

Here are some valid paths for this example:

a_setting.[0] - returns the string a string

a_setting.[1].[0].[2] - returns the integer 3

a_setting.[2].misc.x - returns the integer 4

Adjacent string literals separated by whitespace, newlines and / or comments are automatically concatenated.

Example:

 "a"/* a comment */" string"    " liter"

 // This is a commment

    "al"

is equivalent to:

 "a string literal"

See the integration tests (in the tests/ directory) for sample use cases and more complex examples.

Environment variables

The crate has an ability to inject environment variables into the configuration file. That becomes possible using special syntax:

  • $"SOME_ENV_VAR_NAME"::str to inject the environment variables SOME_ENV_VAR_NAME as the string value. No additiocal changes are made ot the value.
  • $"SOME_ENV_VAR_NAME"::bool to inject the environment variable SOME_ENV_VAR_NAME as the boolean value. The value true or yes or on or 1 are converted into true otherwise into false.
  • $"SOME_ENV_VAR_NAME"::int to inject the environment variable SOME_ENV_VAR_NAME as the integer value. The successfully parsed value is injected as i32 or i64, depending on the format, otherwise 0i32 is injected.
  • $"SOME_ENV_VAR_NAME"::flt to inject the environment variable SOME_ENV_VAR_NAME as the floating value. The successfully parsed value is injected as f32 or f64, depending on the format, otherwise 0f32 is injected.
  • $"SOME_ENV_VAR_NAME"::auto or $"SOME_ENV_VAR_NAME" to inject the environment variable SOME_ENV_VAR_NAME and resolve the type automatically. Rules of the type auto-resolution:
    • If the value is True or Yes or On then the result type is boolean True;
    • If the value is False or No or Off then the result type is boolean False;
    • If the value is floating then the result type is floating;
    • If the value is integer then the result type is integer;
    • Otherwise the result is string value.

Example:

 #!/bin/sh
 export LOG_LEVEL=debug
 // Configuration file
 log = {
       // Inject (use) the value of the environment variable LOG_LEVEL
       level = $"LOG_LEVEL"::str;
 }

Grammar

This section describes the configuration input format. The starting rule is conf.

 conf -> __ settings_list __

 settings_list -> // empty
                | setting settings_list
 setting -> __ name __ (":"|"=") __ value __ ";" __

 name -> [a-zA-Z][-a-zA-Z0-9_]*

 value -> scalar_value
        | array_value
        | list_value
        | group_value

 scalar_value -> boolean_scalar_value
               | floating64_scalar_value
               | floating32_scalar_value
               | integer64_scalar_value
               | integer32_scalar_value
               | str_scalar_value
               | auto_env_scalar_value

 boolean_scalar_value -> [Tt][Rr][Uu][Ee]
                       | [Yy][Ee][Ss]
                       | [Oo][Nn]
                       | [Ff][Aa][Ll][Ss][Ee]
                       | [Nn][Oo]
                       | [Oo][Ff][Ff]
                       | $"ENV_VAR_NAME"::bool

 floating64_scalar_value -> [+-]?([0-9]+\.[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?"L"
                          | $"ENV_VAR_NAME"::flt

 floating32_scalar_value -> [+-]?([0-9]+\.[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
                          | $"ENV_VAR_NAME"::flt

 integer32_scalar_value -> [+-]?[0-9]+
                         | $"ENV_VAR_NAME"::int

 integer64_scalar_value -> [+-]?[0-9]+"L"
                         | $"ENV_VAR_NAME"::int

 str_scalar_value -> __ str_literal __
                   | __ str_literal __ str_scalar_value
                   | $"ENV_VAR_NAME"::str

 auto_env_scalar_value -> $"ENV_VAR_NAME"::auto
                        | $"ENV_VAR_NAME"

 str_literal -> "\"" ([^\"\\]|(("\\r"|"\\n"|"\\t"|"\\\""|"\\\\")))* "\""

 array_value -> "["
                (bool_array |
                 flt64_array | flt32_array |
                 int64_array | int32_array |
                 str_array)
                "]"
              | "[" __ "]"

 bool_array -> __ boolean_scalar_value __
             | __ boolean_scalar_value __ "," __ bool_array

 flt64_array -> __ floating64_scalar_value __
              | __ floating64_scalar_value __ "," __ flt64_array

 flt32_array -> __ floating32_scalar_value __
              | __ floating32_scalar_value __ "," __ flt32_array
 int64_array -> __ integer64_scalar_value __
              | __ integer64_scalar_value __ "," __ int64_array

 int32_array -> __ integer32_scalar_value __
              | __ integer32_scalar_value __ "," __ int32_array

 str_array -> __ str_scalar_value __
            | __ str_scalar_value __ "," __ str_array

 list_value -> "(" __ ")"
             | "(" list_elements ")"

 list_elements -> __ value __
                | __ value __ "," __ list_elements

 group_value -> "{" settings_list "}"

 __ -> // empty
     | whitespace __
     | eol __
     | comment __

 whitespace -> [\s\t]

 eol -> "\r\n"
      | "\n"

 comment -> single_line_comment
          | multi_line_comment

 single_line_comment -> ("//"|"#")[^\n]*"\n"?

 multi_line_comment -> "/*"([^*]|"*"[^/])*"*/"

Modules

error

Errors that can occur while parsing a configuration

reader

Reader types to parse a configuration.

types

Internal types used to represent a configuration and corresponding primitives to browse it