macro_rules! AsPlist {
(@key-name
$field:ident<$field_key:literal>) => { ... };
(@key-name $field:ident) => { ... };
(@missing-field $key_name:expr, $default:expr) => { ... };
(@missing-field $key_name:expr,) => { ... };
(@extract-field $ctx:ident, $value:ident, None) => { ... };
(@extract-field $ctx:ident, $value:ident, Some($e: expr)) => { ... };
(@extract-field $ctx:ident, $value:ident, $e: expr) => { ... };
(@extract-field $ctx:ident, $value:ident) => { ... };
(
$( #[$meta:meta] )*
$vis:vis struct $struct_name:ident {
$(
$( #[$($field_meta:tt)+] )*
$field_vis:vis $field:ident$(<$field_key:literal>)? : $type:ty
$({= $($default:tt)+ })?
),+ $(,)?
}
) => { ... };
}Expand description
Derive Plistable for a struct, enabling it to be used as a Plist<T>
argument in defun-registered functions.
§Syntax
AsPlist! {
[attributes]
[pub] struct Name {
[field_vis] field[<":key-name">]: Type [{= default}],
...
}
}- Each field maps to a plist keyword. By default the keyword is
":fieldname". Usefield<":custom-key">to override. - A field with
{= expr}is optional; if absent from the plist the default expression is used. - A field without a default is required; a missing key is an error.
§Example
use tulisp::{TulispContext, Plist, AsPlist};
AsPlist! {
struct Config {
host: String,
port<":port-number">: i64 {= 8080},
scheme: Option<String> {= None},
}
}
let mut ctx = TulispContext::new();
ctx.defun("make-server", |cfg: Plist<Config>| -> String {
format!(
"{}://{}:{}",
cfg.scheme.clone().unwrap_or_else(||"http".to_string()),
cfg.host,
cfg.port
)
});
assert_eq!(
ctx.eval_string(r#"(make-server :host "localhost")"#).unwrap().as_string().unwrap(),
"http://localhost:8080"
);
assert_eq!(
ctx.eval_string(r#"(make-server :host "example.com" :port-number 443)"#).unwrap().as_string().unwrap(),
"http://example.com:443"
);
assert_eq!(
ctx.eval_string(r#"(make-server :host "localhost" :scheme "https")"#).unwrap().as_string().unwrap(),
"https://localhost:8080"
);