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;