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: ```rust use uclicious::*; let mut parser = Parser::default(); let input = r#" teststring = "no scope" afloat = 3.14 aninteger = 69420 isitgood = yes buffersize = 1KB interval = 1s "#; parser.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); let result = parser.get_object().unwrap();
let lookupresult = result.lookup("teststring").unwrap().asstring().unwrap(); asserteq!(lookupresult.asstr(), "no scope");
let lookupresult = result.lookup("afloat").unwrap().asf64().unwrap(); asserteq!(lookup_result, 3.14f64);
let lookupresult = result.lookup("aninteger").unwrap().asi64().unwrap(); asserteq!(lookup_result, 69420i64);
let lookupresult = result.lookup("isitgood").unwrap().asbool().unwrap(); asserteq!(lookupresult, true);
let lookupresult = result.lookup("buffersize").unwrap().asi64().unwrap(); asserteq!(lookupresult, 1024); let lookupresult = result.lookup("interval").unwrap().astime().unwrap(); asserteq!(lookup_result, 1.0f64); ```
In order to get around rust rules library implemets its own trait FromObject for some basic types: ```rust use uclicious::*; let mut parser = Parser::default(); let input = r#" teststring = "no scope" afloat = 3.14 aninteger = 69420 isitgood = yes buffersize = 1KB "#; parser.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); let result = parser.get_object().unwrap();
let lookupresult = result.lookup("isitgood").unwrap();
let maybe: Option
On top of "raw" interface to libUCL, Uclicious provides an easy way to derive constructor for strucs: ```rust use uclicious::*; use std::path::PathBuf; use std::net::SocketAddr; use std::collections::HashMap; use std::time::Duration;
struct Connection {
#[ucl(default)]
enabled: bool,
host: String,
#[ucl(default = "420")]
port: i64,
buffer: u64,
#[ucl(path = "type")]
kind: String,
locations: Vec
struct Extra { enabled: bool } let mut builder = Connection::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 { feature1 = on feature2 = off feature_3 = on }"#;
builder.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); let connection: Connection = builder.build().unwrap(); ```
If you choose to derive builder then ::builder()
method will be added to target struct.
Library supports running optional validators on values before building the resulting struct:
```rust use uclicious::*; mod validators { use uclicious::ObjectError; pub fn ispositive(lookuppath: &str, value: &i64) -> Result<(), ObjectError> { if *value > 0 { Ok(()) } else { Err(ObjectError::other(format!("{} is not a positive number", lookup_path))) } } }
struct Validated { #[ucl(default, validate="validators::is_positive")] number: i64 } let mut builder = Validated::builder().unwrap();
let input = "number = -1"; builder.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); assert!(builder.build().is_err()) ```
If your target structure has types that don't implement FromObject
you can use From
or TryFrom
via intermediate that does:
```rust use uclicious::*; use std::convert::{From,TryFrom};
enum Mode { On, Off, }
impl TryFrom
struct WrappedInt(i64);
impl From
struct Mapped { #[ucl(from="i64")] number: WrappedInt, #[ucl(try_from="String")] mode: Mode } let mut builder = Mapped::builder().unwrap();
let input = r#" number = -1, mode = "on" "#; builder.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); let actual = builder.build().unwrap(); let expected = Mapped { number: WrappedInt(-1), mode: Mode::On }; assert_eq!(expected, actual); ```
Additionally you can provide mapping to you type from ObjectRef: ```rust use uclicious::*;
pub enum Mode { On, Off, }
pub fn mapbool(src: ObjectRef) -> Result
struct Mapped { #[ucl(map="map_bool")] mode: Mode } let mut builder = Mapped::builder().unwrap();
let input = r#" mode = on "#; builder.addchunkfull(input, Priority::default(), DEFAULTDUPLICATESTRATEGY).unwrap(); let actual = builder.build().unwrap(); let expected = Mapped { mode: Mode::On }; ```
#[ucl(..)]
)skip_builder
parser(..)
flags
filevars(..)
set_filevars
on a parser.path
expand
var(..)
name
$
part.value
include(..)
path = string
priority = u32
strategy = uclicious::DuplicateStrategy
All field level options are optional.
default
default = expression
path = string
validate = path::to_method
Fn(key: &str, value: &T) -> Result<(), E>
ObjectError
from = Type
ObjectRef
to Type
and then use std::convert::From
to convert into target typetry_from = Type
ObjectRef
to Type
and then use std::convert::TryFrom
to convert into target typeObjectError::Other
map = path::to_method
Fn(src: ObjectRef) -> Result<T, E>
From
or TryFrom
or when error is not convertable into ObjectError
PRs, feature requests, bug reports are welcome. I won't be adding CoC — be civilized.
from
and try_from
like in serder [#3]raw
module