Skip to main content

AsPlist

Macro AsPlist 

Source
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". Use field<":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"
);