From d97bc62121623e21049a2946ab0b3d3ff7dec16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Fri, 21 Apr 2023 17:14:57 +0200 Subject: [PATCH] Add Entity and Context types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scansion supports declaring components in addition to clients. We don't support components yet but with this change it's not far off anymore. Signed-off-by: Maxime “pep” Buquet --- src/element.rs | 27 ++++++++++++--------------- src/lib.rs | 2 +- src/parsers.rs | 32 ++++++++++++++++++++++---------- src/types.rs | 25 ++++++++++++++++--------- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/element.rs b/src/element.rs index 00adbfd..abb845e 100644 --- a/src/element.rs +++ b/src/element.rs @@ -38,14 +38,12 @@ //! //! ``` -use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::Deref; use crate::parsers::parse_variable; -use crate::types::VariableAttr; -use crate::{Client, ClientName}; +use crate::types::{Client, Context, Entity, VariableAttr}; use jid::BareJid; use minidom::{Element, Node}; @@ -56,8 +54,6 @@ pub static DEFAULT_NS: &str = "jabber:client"; /// Namespace used for scansion attributes pub static SCANSION_NS: &str = "https://matthewwild.co.uk/projects/scansion"; -pub type Context = HashMap; - /// Strict Comparison marker #[derive(Debug)] struct StrictComparison; @@ -261,11 +257,11 @@ impl<'a, 'b> PartialEq<&Element> for ScanElement<'a, 'b> { let Some(context) = self.context { let res = match var { VariableAttr::FullJid(name) => match context.get(&name) { - Some(Client { jid, .. }) => String::from(jid.clone()), + Some(Entity::Client(Client { jid, .. })) => String::from(jid.clone()), _ => return false, }, VariableAttr::BareJid(name) => match context.get(&name) { - Some(Client { jid, .. }) => String::from(BareJid::from(jid.clone())), + Some(Entity::Client(Client { jid, .. })) => String::from(BareJid::from(jid.clone())), _ => return false, }, }; @@ -314,6 +310,7 @@ impl<'a, 'b> PartialEq<&Element> for ScanElement<'a, 'b> { #[cfg(test)] mod tests { use super::*; + use std::collections::HashMap; use std::str::FromStr; use jid::Jid; @@ -591,10 +588,10 @@ mod tests { let louise = Client::new(Jid::from_str("louise@example.com").unwrap(), "passwd"); let rosa_phone = Client::new(Jid::from_str("rosa@example.com/phone").unwrap(), "passwd"); - let clients = Some({ + let context = Some({ let mut tmp = HashMap::new(); - tmp.insert(String::from("louise"), louise); - tmp.insert(String::from("rosa's phone"), rosa_phone); + tmp.insert(String::from("louise"), Entity::Client(louise)); + tmp.insert(String::from("rosa's phone"), Entity::Client(rosa_phone)); tmp }); @@ -604,7 +601,7 @@ mod tests { let elem2: Element = "" .parse() .unwrap(); - let scan1 = ScanElement::new(&elem1).with_context(clients.as_ref()); + let scan1 = ScanElement::new(elem1).with_context(context.as_ref()); assert_eq!(scan1, &elem2); @@ -614,7 +611,7 @@ mod tests { let elem4: Element = "" .parse() .unwrap(); - let scan3 = ScanElement::new(&elem3).with_context(clients.as_ref()); + let scan3 = ScanElement::new(elem3).with_context(context.as_ref()); assert_eq!(scan3, &elem4); } @@ -626,9 +623,9 @@ mod tests { "passwd", ); - let clients = Some({ + let context = Some({ let mut tmp = HashMap::new(); - tmp.insert(String::from("louise"), louise); + tmp.insert(String::from("louise"), Entity::Client(louise)); tmp }); @@ -639,7 +636,7 @@ mod tests { "" .parse() .unwrap(); - let scan1 = ScanElement::new(&elem1).with_context(clients.as_ref()); + let scan1 = ScanElement::new(elem1).with_context(context.as_ref()); assert_eq!(scan1, &elem2); } diff --git a/src/lib.rs b/src/lib.rs index 71f9f2b..86b20b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,4 +12,4 @@ pub mod types; pub use element::ScanElement; pub use parsers::parse_spec; -pub use types::{Action, Client, ClientName, Metadata, Spec}; +pub use types::{Action, Client, Context, Metadata, Name, Spec}; diff --git a/src/parsers.rs b/src/parsers.rs index 7baf77d..a6d241e 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use crate::types::{Action, Client, ClientName, Metadata, Spec, VariableAttr}; +use crate::types::{Action, Client, Context, Entity, Metadata, Name, Spec, VariableAttr}; use std::collections::HashMap; use std::str::FromStr; @@ -130,7 +130,7 @@ fn parse_meta(s: Span) -> IResult { Ok((s, meta)) } -fn parse_client(s: Span) -> IResult { +fn parse_client(s: Span) -> IResult { let (s, (_, _, _, name, _)) = tuple((allspaces, tag("[Client]"), space0, take_until("\n"), space0))(s)?; @@ -189,15 +189,26 @@ fn parse_client(s: Span) -> IResult { Ok((s, (String::from(name), client))) } -fn parse_clients(s: Span) -> IResult> { +fn parse_clients(s: Span) -> IResult> { let (s, clients) = many0(parse_client)(s)?; - let mut map: HashMap = HashMap::new(); + let mut map: HashMap = HashMap::new(); for (name, client) in clients { map.insert(name, client); } Ok((s, map)) } +fn parse_context(s: Span) -> IResult { + let (s, clients) = parse_clients(s)?; + Ok(( + s, + clients + .into_iter() + .map(|(name, client)| (name, Entity::Client(client))) + .collect::>(), + )) +} + fn parse_sep(s: Span) -> IResult { let (s, (pos, _)) = delimited(allspaces, tuple((position, many1(tag("-")))), allspaces)(s)?; Ok((s, Token { position: pos })) @@ -269,12 +280,12 @@ fn parse_actions(s: Span) -> IResult> { pub fn parse_spec(i: &str) -> Result { let s: Span = i.into(); let (s, metadata) = opt(parse_meta)(s)?; - let (s, clients) = parse_clients(s)?; + let (s, context) = parse_context(s)?; let (s, _) = parse_sep(s)?; let (_, actions) = parse_actions(s)?; Ok(Spec { metadata, - clients, + context, actions, }) } @@ -300,6 +311,7 @@ pub fn parse_variable(s: Span) -> IResult { #[cfg(test)] mod tests { use super::*; + use std::collections::HashMap; fn get_client(name: &str) -> Client { Client::new( @@ -457,7 +469,7 @@ mod tests { password: password "#; - let mut clients: HashMap = HashMap::new(); + let mut clients: HashMap = HashMap::new(); clients.insert( String::from("louise"), Client::new(Jid::from_str("louise@localhost").unwrap(), "password"), @@ -574,8 +586,8 @@ louise receives: .with_tags(vec![String::from("tag1"), String::from("tag2")]), ); - let mut clients: HashMap = HashMap::new(); - clients.insert(String::from("louise"), get_client("louise")); + let mut context: Context = HashMap::new(); + context.insert(String::from("louise"), Entity::Client(get_client("louise"))); let actions = vec![ Action::Connect(String::from("louise")), @@ -588,7 +600,7 @@ louise receives: let spec = Spec { metadata, - clients, + context, actions, }; diff --git a/src/types.rs b/src/types.rs index 661219e..26f39ac 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,8 +10,8 @@ use jid::Jid; #[derive(Debug, PartialEq)] pub enum VariableAttr { - FullJid(ClientName), - BareJid(ClientName), + FullJid(Name), + BareJid(Name), } #[derive(Debug, Clone, PartialEq)] @@ -36,7 +36,7 @@ impl Metadata { } } -pub type ClientName = String; +pub type Name = String; #[derive(Debug, Clone, PartialEq)] pub struct Client { @@ -67,18 +67,25 @@ impl Client { } } +#[derive(Debug, Clone, PartialEq)] +pub enum Entity { + Client(Client), +} + +pub type Context = HashMap; + #[derive(Debug, Clone, PartialEq)] pub enum Action<'a> { - Connect(ClientName), - Send(ClientName, &'a str), - Receive(ClientName, &'a str), - ReceiveNone(ClientName), - Disconnect(ClientName), + Connect(Name), + Send(Name, &'a str), + Receive(Name, &'a str), + ReceiveNone(Name), + Disconnect(Name), } #[derive(Debug, Clone, PartialEq)] pub struct Spec<'a> { pub metadata: Option, - pub clients: HashMap, + pub context: Context, pub actions: Vec>, }