parse_action: everything before keyword is an identifier
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
0aec3cea6e
commit
1cb94ccfaf
1 changed files with 75 additions and 48 deletions
123
src/lib.rs
123
src/lib.rs
|
@ -12,7 +12,7 @@ use minidom::Element;
|
|||
use nom::{
|
||||
self,
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_until, take_until1, take_while1},
|
||||
bytes::complete::{tag, take_until, take_until1, take_while, take_while1},
|
||||
character::complete::{multispace0, space0, space1},
|
||||
combinator::recognize,
|
||||
multi::{many0, many1},
|
||||
|
@ -102,57 +102,74 @@ fn parse_sep(i: &str) -> IResult<&str, &str> {
|
|||
Ok((i, ""))
|
||||
}
|
||||
|
||||
fn parse_connect(i: &str) -> IResult<&str, Action> {
|
||||
let (i, (name, _, _)) = tuple((take_while1(is_not_space), space1, tag("connects\n")))(i)?;
|
||||
fn parse_action(i: &str) -> IResult<&str, Action> {
|
||||
let mut name = String::new();
|
||||
let (i, namepart) = recognize(tuple((take_while1(is_not_space), space1)))(i)?;
|
||||
name.push_str(namepart);
|
||||
|
||||
Ok((i, Action::Connect(String::from(name))))
|
||||
let mut i = i;
|
||||
let (i, tagname) = loop {
|
||||
let res = tuple((
|
||||
alt((
|
||||
tag("connects"),
|
||||
tag("disconnects"),
|
||||
tag("sends:"),
|
||||
tag("receives:"),
|
||||
)),
|
||||
space0,
|
||||
tag("\n"),
|
||||
))(i);
|
||||
|
||||
match res {
|
||||
Ok((i, (tagname, _, _))) => break (i, tagname),
|
||||
Err(err) => {
|
||||
if i.len() > 0 && &i[0..=1] == "\n" {
|
||||
return Err(err);
|
||||
} else {
|
||||
()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (j, namepart) = recognize(tuple((take_while1(is_not_space), space1)))(i)?;
|
||||
name.push_str(namepart);
|
||||
i = j;
|
||||
};
|
||||
let name = String::from(name.trim());
|
||||
|
||||
let (i, action) = match tagname {
|
||||
"connects" => (i, Action::Connect(name)),
|
||||
"disconnects" => (i, Action::Disconnect(name)),
|
||||
tagname @ "sends:" | tagname @ "receives:" => parse_send_receive(tagname, name, i)?,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok((i, action))
|
||||
}
|
||||
|
||||
fn parse_disconnect(i: &str) -> IResult<&str, Action> {
|
||||
let (i, (name, _, _)) = tuple((take_while1(is_not_space), space1, tag("disconnects\n")))(i)?;
|
||||
|
||||
Ok((i, Action::Disconnect(String::from(name))))
|
||||
}
|
||||
|
||||
fn parse_action_line(i: &str) -> IResult<&str, &str> {
|
||||
fn parse_action_subline(i: &str) -> IResult<&str, &str> {
|
||||
let (i, (_, line, _)) = tuple((many1(tag("\t")), take_until1("\n"), tag("\n")))(i)?;
|
||||
Ok((i, line))
|
||||
}
|
||||
|
||||
fn parse_send_receive(tagname: &str) -> impl Fn(&str) -> IResult<&str, (String, Element)> + '_ {
|
||||
move |i: &str| {
|
||||
let (i, (name, _, _, _, lines)) = tuple((
|
||||
take_while1(is_not_space),
|
||||
space1,
|
||||
tag(tagname),
|
||||
take_while1(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
|
||||
recognize(many1(parse_action_line)),
|
||||
))(i)?;
|
||||
let lines = lines.trim();
|
||||
fn parse_send_receive<'a>(tagname: &str, name: String, i: &'a str) -> IResult<&'a str, Action> {
|
||||
let (i, (_, lines)) = tuple((
|
||||
take_while(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
|
||||
recognize(many1(parse_action_subline)),
|
||||
))(i)?;
|
||||
let lines = lines.trim();
|
||||
|
||||
let elem: Element =
|
||||
Element::from_reader_with_prefixes(&lines.as_bytes()[..], String::from(DEFAULT_NS))
|
||||
.unwrap();
|
||||
Ok((i, (String::from(name), elem)))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_send(i: &str) -> IResult<&str, Action> {
|
||||
let (i, (name, elem)) = parse_send_receive("sends:")(i)?;
|
||||
Ok((i, Action::Send(name, elem)))
|
||||
}
|
||||
|
||||
fn parse_receive(i: &str) -> IResult<&str, Action> {
|
||||
let (i, (name, elem)) = parse_send_receive("receives:")(i)?;
|
||||
Ok((i, Action::Receive(name, elem)))
|
||||
let elem: Element =
|
||||
Element::from_reader_with_prefixes(&lines.as_bytes()[..], String::from(DEFAULT_NS))
|
||||
.unwrap();
|
||||
Ok(match tagname {
|
||||
"sends:" => (i, Action::Send(name, elem)),
|
||||
"receives:" => (i, Action::Receive(name, elem)),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_actions(i: &str) -> IResult<&str, Vec<Action>> {
|
||||
let (i, actions) = many1(delimited(
|
||||
allspaces,
|
||||
alt((parse_connect, parse_disconnect, parse_send, parse_receive)),
|
||||
allspaces,
|
||||
))(i)?;
|
||||
let (i, actions) = many1(delimited(allspaces, parse_action, allspaces))(i)?;
|
||||
Ok((i, actions))
|
||||
}
|
||||
|
||||
|
@ -243,8 +260,13 @@ mod tests {
|
|||
fn test_action_connect() {
|
||||
let buf1 = "louise connects\n";
|
||||
|
||||
let action = Action::Connect(String::from("louise"));
|
||||
assert_eq!(parse_connect(buf1).unwrap().1, action);
|
||||
let action1 = Action::Connect(String::from("louise"));
|
||||
assert_eq!(parse_action(buf1).unwrap().1, action1);
|
||||
|
||||
let buf2 = "louise's phone connects\n";
|
||||
|
||||
let action2 = Action::Connect(String::from("louise's phone"));
|
||||
assert_eq!(parse_action(buf2).unwrap().1, action2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -252,11 +274,11 @@ mod tests {
|
|||
let buf1 = "louise disconnects\n";
|
||||
|
||||
let action = Action::Disconnect(String::from("louise"));
|
||||
assert_eq!(parse_disconnect(buf1).unwrap().1, action);
|
||||
assert_eq!(parse_action(buf1).unwrap().1, action);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_action_send_receive() {
|
||||
fn test_action_send() {
|
||||
let buf = r#"rosa sends:
|
||||
|
||||
<presence
|
||||
|
@ -270,20 +292,25 @@ mod tests {
|
|||
String::from("rosa"),
|
||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
||||
);
|
||||
assert_eq!(parse_send(buf).unwrap().1, send);
|
||||
assert_eq!(parse_action(buf).unwrap().1, send);
|
||||
}
|
||||
|
||||
let buf2 = r#"rosa receives:
|
||||
#[test]
|
||||
fn test_action_receive() {
|
||||
let buf = r#"rosa receives:
|
||||
|
||||
<presence
|
||||
type="unavailable"
|
||||
/>
|
||||
|
||||
"#;
|
||||
let xml = b"<presence\n\t\ttype=\"unavailable\"\t\n/>";
|
||||
|
||||
let receive = Action::Receive(
|
||||
String::from("rosa"),
|
||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
||||
);
|
||||
assert_eq!(parse_receive(buf2).unwrap().1, receive);
|
||||
assert_eq!(parse_action(buf).unwrap().1, receive);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue