interpreter: new read_actions_component
Rejects stanza without an @to, and automatically adds @from. Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
365f5d60a2
commit
d4a8719e09
2 changed files with 70 additions and 3 deletions
|
@ -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<InOutStanza, Minido
|
|||
Ok(inout)
|
||||
}
|
||||
|
||||
/// Reads Actions from Spec and converts that to InOutStanza. Also ensures @to and @from attributes
|
||||
/// are set. Rejects stanza without an @to, and automatically adds @from.
|
||||
pub fn read_actions_component(spec: Spec, context: &Context) -> Result<InOutStanza, MinidomError> {
|
||||
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<Option<String>, 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<Option<String>, 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<Spec, Token> {
|
||||
let mut spec = parse_spec(buf)?;
|
||||
spec.context = bind_context(spec.context.clone());
|
||||
|
|
|
@ -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};
|
||||
|
|
Loading…
Reference in a new issue