Uclicious
Uclicious is a wrapper around Universal Configuration Library (UCL) parser with a lot of sugar.
Uclicious is built on top of libucl. It is much more complex than json or TOML, so I recommend reading documentaiton about it. Library provides safe, but raw API to that library:
use *;
let mut parser = default;
let input = r#"
test_string = "no scope"
a_float = 3.14
an_integer = 69420
is_it_good = yes
buffer_size = 1KB
interval = 1s
"#;
parser.add_chunk_full.unwrap;
let result = parser.get_object.unwrap;
let lookup_result = result.lookup.unwrap.as_string.unwrap;
assert_eq!;
let lookup_result = result.lookup.unwrap.as_f64.unwrap;
assert_eq!;
let lookup_result = result.lookup.unwrap.as_i64.unwrap;
assert_eq!;
let lookup_result = result.lookup.unwrap.as_bool.unwrap;
assert_eq!;
let lookup_result = result.lookup.unwrap.as_i64.unwrap;
assert_eq!;
let lookup_result = result.lookup.unwrap.as_time.unwrap;
assert_eq!;
In order to get around rust rules library implemets its own trait FromObject for some basic types:
use *;
let mut parser = default;
let input = r#"
test_string = "no scope"
a_float = 3.14
an_integer = 69420
is_it_good = yes
buffer_size = 1KB
"#;
parser.add_chunk_full.unwrap;
let result = parser.get_object.unwrap;
let lookup_result = result.lookup.unwrap;
let maybe: = try_from.unwrap;
assert_eq!;
Automatic Derive
On top of "raw" interface to libUCL, Uclicious provides an easy way to derive constructor for strucs:
use *;
use PathBuf;
use SocketAddr;
use HashMap;
use Duration;
let mut builder = builder.unwrap;
let input = r#"
enabled = yes
host = "some.fake.url"
buffer = 1mb
type = $test
locations = "/etc/"
addr = "127.0.0.1:80"
extra = {
enabled = on
}
subsection {
host = [host1, host2]
}
interval = 10ms
gates {
feature_1 = on
feature_2 = off
feature_3 = on
}"#;
builder.add_chunk_full.unwrap;
let connection: Connection = builder.build.unwrap;
If you choose to derive builder then ::builder()
method will be added to target struct.
Supported attributes (#[ucl(..)]
)
Structure level
skip_builder
- if set, then builder and builder methods won't be generated.
parser(..)
- Optional attribute to configure inner parser.
- Has following nested attributes:
flags
- a path to function that returns flags.
filevars(..)
- call
set_filevars
on a parser. - Has following nested attributes:
path
- a string representation of filepath.
expand
- (optional) if set, then variables would be expanded to absolute.
- call
var(..)
- Optional attribute to register string variables with the parser.
- Has following nested attributes:
name
- A name of the variable without
$
part.
- A name of the variable without
value
- A string values for the variable.
- Onlt string variables are supported by libUCL.
include(..)
- Used to add files into the parser.
- If file doesn't exist or failed to parse, then error will be returned in a constructor.
- Has following nested attirbutes:
- (required)
path(string)
- File path. Can be absolute or relative to CWD.
- (optional)
priority(u32)
- 0-15 priority for the source. Consult the libUCL documentation for more information.
- (optional)
strategy(uclicious::DuplicateStrategy)
- Strategy to use for duplicate keys. Consult the libUCL documentation for more information.
- (required)
Field level
default
- Use Default::default if key not found in object.
default(expression)
- Use this expression as value if key not found.
- Could be a value or a function call.
path(string)
- By default field name is used as path.
- If set that would be used as a key.
- dot notation for key is supported.
Additional notes
- If target type is an array, but key is a single value — an implicit list is created.
- Automatic derive on enums is not supported, but you can implement it yourself.
- I have a few more features I want to implement before publishing this crate:
- Ability to add variables.
- Ability to add macross handlers.
- (maybe) configure parser that us used for derived builder with atrributes.
- (done) add sources to parser with attributes.
Contributing
PRs, feature requests, bug reports are welcome. I won't be adding CoC — be civilized.
Goals
- Provider safe and convient configuration library
- Automatic derive, so you don't have to think about parser object
Not Goals
- Providing UCL Object generation tools is not a goal for this project
- 1:1 interface to libUCL
- sugar inside
raw
module
Special thanks
- draft6 and hauleth
- libucl-rs was a good starting point
- Type wrappers pretty much copied from there
- colin-kiegel
- Rust-derive-builder was used as a starting point for uclicious-derive
- Very well documented proc_macro crate, do recommend