libconfig/
lib.rs

1//! A library to parse and load configuration files.
2//!
3//! This library parses and loads configuration files in much the same way as C/C++'s
4//! [libconfig](http://www.hyperrealm.com/libconfig/). At this time, it can only read and load
5//! configurations, but future plans include a much richer user API to allow other forms of
6//! interaction, such as manipulating values, writing the current configuration to a file, etc.
7//!
8//!# Getting started
9//!
10//! A configuration file consists of a group of settings. A setting is a key/value pair, where the
11//! key is a string of the form `[a-zA-Z][-a-zA-Z0-9_]*`, and the value is anything represented by
12//! `types::Value`. In a configuration file, setting/value pairs are written as
13//! `setting_name = value;`. Possible values include primitive integer and floating point types,
14//! strings, arrays, lists, etc.
15//!
16//! The library provides a bunch of methods to read the configuration data in the `reader` module.
17//! The possibilities include reading from a string, from a file, or from anything that implements
18//! the `Read` trait.
19//!
20//! As of now, every reader will first attempt to read the whole configuration into memory,
21//! and only begins parsing once everything was read.
22//!
23//! In case of error, the parser returns a `config::error`.
24//! On success, the parser returns a `Config`, which can then be used to browse the loaded data.
25//!
26//! Browsing is typically done with the `lookup_*` methods implemented by `Config`. The `lookup`
27//! methods work with *paths*. Essentially, a path unambiguously describes the location of
28//! a setting.
29//!
30//! For example, consider this input configuration file:
31//!
32//!```ignore
33//! title = "My HTTP server";
34//! listen_ports = [ 80, 443 ];
35//! misc = {
36//!     owner = "Chuck Norris";
37//!     location = "CA";
38//!     contact = {
39//!         phone = "415-256-9999";
40//!         // This is an array. Arrays start with `[` and end with `]`
41//!         // Arrays are homogeneous and can only hold scalar data types.
42//!         // See types::ScalarValue for further information
43//!         emails = ["chuck@norris.com", "chuck.norris@gmail.com"];
44//!     };
45//! };
46//!```
47//!
48//! At the top level, we have 3 settings: `title`, `listen_ports` and `misc`. `misc` is itself a
49//! group of settings. Each value in this configuration is reachable by a unique path of settings
50//! to follow. Each setting in a path is separated by `.`
51//!
52//! **Example**: The path `misc.contact.phone` identifies the setting with value `415-256-9999`.
53//!
54//! Array and list types are indexed using `[i]` in a path.
55//!
56//! **Example**: The path `listen_ports.[1]` identifies the setting with value `443`.
57//!
58//! **Example**: The path `misc.contact.emails.[0]` identifies the setting with value
59//! `chuck@norris.com`
60//!
61//! Lists, as opposed to arrays, are heterogeneous and can store any data type, including other
62//! lists. Here's a setting consisting of a heterogeneous list:
63//!
64//!```ignore
65//! // This is a list. Lists start with `(` and end with `)`
66//! // Lists are heterogeneous and can store any data type, including other lists
67//! a_setting = ("a string", // The first element is a string
68//!              ((1, 2, 3)), // The 2nd element is a list storing a list of 3 integers
69//!              misc = { x = 4; y = 3; } // 3rd element: a group
70//!             );
71//!```
72//!
73//! Here are some valid paths for this example:
74//!
75//! `a_setting.[0]` - returns the string `a string`
76//!
77//! `a_setting.[1].[0].[2]` - returns the integer `3`
78//!
79//! `a_setting.[2].misc.x` - returns the integer `4`
80//!
81//! Adjacent string literals separated by whitespace, newlines and / or comments are automatically
82//! concatenated.
83//!
84//! **Example**:
85//!
86//! ```ignore
87//! "a"/* a comment */" string"    " liter"
88//!
89//! // This is a commment
90//!
91//!    "al"
92//! ```
93//!
94//! is equivalent to:
95//!
96//! ```ignore
97//! "a string literal"
98//! ```
99//!
100//! See the integration tests (in the `tests/` directory) for sample use cases and more complex
101//! examples.
102//!
103//!# Environment variables
104//!
105//! The crate has an ability to inject environment variables into the configuration file. That
106//! becomes possible using special syntax:  
107//!
108//!  * `$"SOME_ENV_VAR_NAME"::str` to inject the environment variables `SOME_ENV_VAR_NAME` as the string value.
109//!    No additiocal changes are made ot the value.
110//!  * `$"SOME_ENV_VAR_NAME"::bool` to inject the environment variable `SOME_ENV_VAR_NAME` as the boolean value.
111//!    The value `true` or `yes` or `on` or `1` are converted into `true` otherwise into `false`.  
112//!  * `$"SOME_ENV_VAR_NAME"::int` to inject the environment variable `SOME_ENV_VAR_NAME` as the integer value.
113//!    The successfully parsed value is injected as `i32` or `i64`, depending on the format, otherwise `0i32` is injected.  
114//!  * `$"SOME_ENV_VAR_NAME"::flt` to inject the environment variable `SOME_ENV_VAR_NAME` as the floating value.
115//!    The successfully parsed value is injected as `f32` or `f64`, depending on the format, otherwise `0f32` is injected.  
116//!  * `$"SOME_ENV_VAR_NAME"::auto` or `$"SOME_ENV_VAR_NAME"` to inject the environment variable `SOME_ENV_VAR_NAME`
117//!    and resolve the type automatically. Rules of the type auto-resolution:  
118//!    - If the value is *True* or *Yes* or *On* then the result type is `boolean True`;  
119//!    - If the value is *False* or *No* or *Off* then the result type is `boolean False`;  
120//!    - If the value is floating then the result type is `floating`;  
121//!    - If the value is integer then the result type is `integer`;  
122//!    - Otherwise the result is `string` value.  
123//!
124//!**Example**:
125//!
126//! ```ignore
127//! #!/bin/sh
128//! export LOG_LEVEL=debug
129//! ```
130//! 
131//! ```ignore
132//! // Configuration file
133//! log = {
134//!       // Inject (use) the value of the environment variable LOG_LEVEL
135//!       level = $"LOG_LEVEL"::str;
136//! }
137//! ```
138//!
139//!# Grammar
140//!
141//! This section describes the configuration input format. The starting rule is `conf`.
142//!
143//! ```text
144//! conf -> __ settings_list __
145//!
146//! settings_list -> // empty
147//!                | setting settings_list
148//! setting -> __ name __ (":"|"=") __ value __ ";" __
149//!
150//! name -> [a-zA-Z][-a-zA-Z0-9_]*
151//!
152//! value -> scalar_value
153//!        | array_value
154//!        | list_value
155//!        | group_value
156//!
157//! scalar_value -> boolean_scalar_value
158//!               | floating64_scalar_value
159//!               | floating32_scalar_value
160//!               | integer64_scalar_value
161//!               | integer32_scalar_value
162//!               | str_scalar_value
163//!               | auto_env_scalar_value
164//!
165//! boolean_scalar_value -> [Tt][Rr][Uu][Ee]
166//!                       | [Yy][Ee][Ss]
167//!                       | [Oo][Nn]
168//!                       | [Ff][Aa][Ll][Ss][Ee]
169//!                       | [Nn][Oo]
170//!                       | [Oo][Ff][Ff]
171//!                       | $"ENV_VAR_NAME"::bool
172//!
173//! floating64_scalar_value -> [+-]?([0-9]+\.[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?"L"
174//!                          | $"ENV_VAR_NAME"::flt
175//!
176//! floating32_scalar_value -> [+-]?([0-9]+\.[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?
177//!                          | $"ENV_VAR_NAME"::flt
178//!
179//! integer32_scalar_value -> [+-]?[0-9]+
180//!                         | $"ENV_VAR_NAME"::int
181//!
182//! integer64_scalar_value -> [+-]?[0-9]+"L"
183//!                         | $"ENV_VAR_NAME"::int
184//!
185//! str_scalar_value -> __ str_literal __
186//!                   | __ str_literal __ str_scalar_value
187//!                   | $"ENV_VAR_NAME"::str
188//!
189//! auto_env_scalar_value -> $"ENV_VAR_NAME"::auto
190//!                        | $"ENV_VAR_NAME"
191//!
192//! str_literal -> "\"" ([^\"\\]|(("\\r"|"\\n"|"\\t"|"\\\""|"\\\\")))* "\""
193//!
194//! array_value -> "["
195//!                (bool_array |
196//!                 flt64_array | flt32_array |
197//!                 int64_array | int32_array |
198//!                 str_array)
199//!                "]"
200//!              | "[" __ "]"
201//!
202//! bool_array -> __ boolean_scalar_value __
203//!             | __ boolean_scalar_value __ "," __ bool_array
204//!
205//! flt64_array -> __ floating64_scalar_value __
206//!              | __ floating64_scalar_value __ "," __ flt64_array
207//!
208//! flt32_array -> __ floating32_scalar_value __
209//!              | __ floating32_scalar_value __ "," __ flt32_array
210//
211//! int64_array -> __ integer64_scalar_value __
212//!              | __ integer64_scalar_value __ "," __ int64_array
213//!
214//! int32_array -> __ integer32_scalar_value __
215//!              | __ integer32_scalar_value __ "," __ int32_array
216//!
217//! str_array -> __ str_scalar_value __
218//!            | __ str_scalar_value __ "," __ str_array
219//!
220//! list_value -> "(" __ ")"
221//!             | "(" list_elements ")"
222//!
223//! list_elements -> __ value __
224//!                | __ value __ "," __ list_elements
225//!
226//! group_value -> "{" settings_list "}"
227//!
228//! __ -> // empty
229//!     | whitespace __
230//!     | eol __
231//!     | comment __
232//!
233//! whitespace -> [\s\t]
234//!
235//! eol -> "\r\n"
236//!      | "\n"
237//!
238//! comment -> single_line_comment
239//!          | multi_line_comment
240//!
241//! single_line_comment -> ("//"|"#")[^\n]*"\n"?
242//!
243//! multi_line_comment -> "/*"([^*]|"*"[^/])*"*/"
244//!
245//! ```
246//!
247
248#![crate_name = "libconfig"]
249#![crate_type = "lib"]
250#![warn(missing_docs)]
251
252#[macro_use]
253extern crate nom;
254
255mod parser;
256
257pub mod types;
258pub mod error;
259pub mod reader;