Add metadata support

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2023-01-12 23:33:14 +01:00
parent 54debb3e2f
commit ab40eb688b

View file

@ -43,6 +43,18 @@ impl<'a> From<NomErr<nom::error::Error<LocatedSpan<&'a str>>>> for Token<'a> {
pub static DEFAULT_NS: &'static str = "jabber:client"; pub static DEFAULT_NS: &'static str = "jabber:client";
pub static SCANSION_NS: &'static str = "https://matthewwild.co.uk/projects/scansion"; pub static SCANSION_NS: &'static str = "https://matthewwild.co.uk/projects/scansion";
#[derive(Debug, Clone, PartialEq)]
pub struct Metadata {
pub title: String,
pub description: Option<String>,
}
impl Metadata {
pub fn new<S: Into<String>, T: Into<String>>(title: S, desc: Option<T>) -> Metadata {
Metadata { title: title.into(), description: desc.map(|t| t.into()) }
}
}
pub type ClientName = String; pub type ClientName = String;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -84,6 +96,7 @@ pub enum Action {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Spec { pub struct Spec {
pub metadata: Option<Metadata>,
pub clients: HashMap<ClientName, Client>, pub clients: HashMap<ClientName, Client>,
pub actions: Vec<Action>, pub actions: Vec<Action>,
} }
@ -139,6 +152,28 @@ where
} }
} }
fn parse_meta(s: Span) -> IResult<Span, Metadata> {
let (s, (_pos, title)) =
tuple((position, delimited(tag("#"), take_until("\n"), tag("\n"))))(s)?;
let optdesc = opt(tuple((
position,
delimited(tag("#"), take_until("\n"), tag("\n")),
)))(s)?;
let mut desc: Option<&str> = None;
let s = match optdesc {
(s, Some((_pos, val))) => {
desc = Some(val.trim());
s
}
(s, None) => s,
};
let meta = Metadata::new(title.trim(), desc);
Ok((s, meta))
}
fn parse_client(s: Span) -> IResult<Span, (ClientName, Client)> { fn parse_client(s: Span) -> IResult<Span, (ClientName, Client)> {
let (s, (_, _, _, name, _)) = let (s, (_, _, _, name, _)) =
tuple((allspaces, tag("[Client]"), space0, take_until("\n"), space0))(s)?; tuple((allspaces, tag("[Client]"), space0, take_until("\n"), space0))(s)?;
@ -268,10 +303,15 @@ fn parse_actions(s: Span) -> IResult<Span, Vec<Action>> {
pub fn parse_spec(i: &str) -> Result<Spec, Token> { pub fn parse_spec(i: &str) -> Result<Spec, Token> {
let s: Span = i.into(); let s: Span = i.into();
let (s, metadata) = opt(parse_meta)(s)?;
let (s, clients) = parse_clients(s)?; let (s, clients) = parse_clients(s)?;
let (s, _) = parse_sep(s)?; let (s, _) = parse_sep(s)?;
let (_, actions) = parse_actions(s)?; let (_, actions) = parse_actions(s)?;
Ok(Spec { clients, actions }) Ok(Spec {
metadata,
clients,
actions,
})
} }
#[cfg(test)] #[cfg(test)]
@ -450,7 +490,9 @@ mod tests {
#[test] #[test]
fn test_parse_spec() { fn test_parse_spec() {
let buf = r#" let buf = r#"# Test title
# Description Foo
[Client] louise [Client] louise
jid: louise@localhost jid: louise@localhost
password: password password: password
@ -468,6 +510,8 @@ louise receives:
"#; "#;
let metadata = Some(Metadata::new("Test title", Some("Description Foo")));
let mut clients: HashMap<ClientName, Client> = HashMap::new(); let mut clients: HashMap<ClientName, Client> = HashMap::new();
clients.insert(String::from("louise"), get_client("louise")); clients.insert(String::from("louise"), get_client("louise"));
@ -486,7 +530,11 @@ louise receives:
), ),
]; ];
let spec = Spec { clients, actions }; let spec = Spec {
metadata,
clients,
actions,
};
assert_eq!(parse_spec(buf), Ok(spec)); assert_eq!(parse_spec(buf), Ok(spec));
} }