diff --git a/src/interpreter.rs b/src/interpreter.rs index ac852c0..81af096 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -15,8 +15,8 @@ use crate::element::{ScanElement, DEFAULT_NS, SCANSION_NS}; use crate::parsers::{parse_spec, Token}; -use crate::types::{Action, Context, Entity, Spec}; -use jid::Jid; +use crate::types::{Action, Client, Context, Entity, Spec}; +use jid::{BareJid, Jid}; use minidom::{Element, Error as MinidomError}; use rand::{thread_rng, Rng}; use std::collections::BTreeMap; @@ -115,6 +115,73 @@ pub fn read_actions(spec: Spec, context: &Context) -> Result Result { + let mut inout = InOutStanza::new(); + for action in spec.actions { + match action { + Action::Receive(name, s) => { + let _jid = context + .get(&name) + .expect(format!("Name '{}' not found in clients", name).as_str()); + + let prefixes: BTreeMap, String> = { + let mut tmp = BTreeMap::new(); + tmp.insert(None, String::from(DEFAULT_NS)); + tmp.insert(Some(String::from("scansion")), String::from(SCANSION_NS)); + tmp + }; + let elem: Element = + Element::from_reader_with_prefixes(s.as_ref(), prefixes).unwrap(); + inout.receives(ScanElement::new(elem).apply_context(&context)); + } + Action::Send(name, s) => { + let client = context + .get(&name) + .expect(format!("Name '{}' not found in clients", name).as_str()); + + let jid: BareJid = match client { + Entity::Client(Client { + jid: Jid::Full(full), + .. + }) => BareJid::from(full.clone()), + Entity::Client(Client { + jid: Jid::Bare(bare), + .. + }) => bare.clone(), + }; + + let prefixes: BTreeMap, String> = { + let mut tmp = BTreeMap::new(); + tmp.insert(None, String::from(DEFAULT_NS)); + tmp.insert(Some(String::from("scansion")), String::from(SCANSION_NS)); + tmp + }; + let mut elem: Element = + Element::from_reader_with_prefixes(s.as_ref(), prefixes).unwrap(); + + // Ensure stanza have to/from parameters. We may be able to infer where the stanza + // comes from but we need them to be addressed to the component explicitely. + assert_ne!( + elem.attr("to"), + None, + "Stanza sent by '{}' should possess a 'to' parameter", + name, + ); + if elem.attr("from").is_none() { + elem.set_attr("from", Jid::Bare(jid)); + } + + inout.sends(ScanElement::new(elem).apply_context(&context)); + } + _ => (), + } + } + + Ok(inout) +} + pub fn read_spec<'a, 'b>(buf: &str) -> Result { let mut spec = parse_spec(buf)?; spec.context = bind_context(spec.context.clone()); diff --git a/src/lib.rs b/src/lib.rs index 5ea33f2..1c02edc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,6 @@ pub mod parsers; pub mod types; pub use element::ScanElement; -pub use interpreter::{read_actions, read_spec}; +pub use interpreter::{read_actions, read_actions_component, read_spec}; pub use parsers::parse_spec; pub use types::{Action, Client, Context, Entity, Metadata, Name, Spec};