Implement take_until_tags parser to make it slightly more nom idiomatic
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:
Maxime “pep” Buquet 2023-01-11 15:46:25 +01:00
parent 0747db35ee
commit c522257e8c
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2

View file

@ -12,12 +12,13 @@ use minidom::Element;
use nom::{
self,
branch::alt,
bytes::complete::{tag, take_until, take_until1, take_while, take_while1},
character::complete::{multispace0, space0, space1},
bytes::complete::{tag, take_until, take_until1, take_while},
character::complete::{multispace0, space0},
combinator::recognize,
error::{ErrorKind, ParseError},
multi::{many0, many1},
sequence::{delimited, tuple},
IResult,
FindSubstring, IResult, InputLength, InputTake,
};
pub static DEFAULT_NS: &'static str = "jabber:client";
@ -44,10 +45,6 @@ pub struct Spec {
pub actions: Vec<Action>,
}
fn is_not_space(c: char) -> bool {
c != ' ' && c != '\t' && c != '\r' && c != '\n'
}
fn allspaces(i: &str) -> IResult<&str, &str> {
alt((delimited(multispace0, comment, multispace0), multispace0))(i)
}
@ -57,14 +54,35 @@ fn comment(i: &str) -> IResult<&str, &str> {
Ok((i, ""))
}
fn take_until_tags<T, I, E: ParseError<I>, List>(list: List) -> impl Fn(I) -> IResult<I, I, E>
where
I: InputTake + FindSubstring<T>,
T: InputLength + Clone,
List: Iterator<Item = T> + Clone,
{
move |i: I| {
let mut l = list.clone();
let res: Option<usize> = loop {
if let Some(item) = l.next() {
match i.find_substring(item) {
None | Some(0) => continue,
valid @ Some(_) => break valid,
}
} else {
break None;
}
};
let res: IResult<_, _, E> = match res {
None => Err(nom::Err::Error(E::from_error_kind(i, ErrorKind::TakeUntil))),
Some(index) => Ok(i.take_split(index)),
};
res
}
}
fn parse_account(i: &str) -> IResult<&str, (AccountName, Account)> {
let (i, (_, _, _, name, _)) = tuple((
allspaces,
tag("[Client]"),
space0,
take_until("\n"),
space0,
))(i)?;
let (i, (_, _, _, name, _)) =
tuple((allspaces, tag("[Client]"), space0, take_until("\n"), space0))(i)?;
let (i, (_, _, _, _, jid, _)) = tuple((
tag("\n"),
many1(tag("\t")),
@ -104,40 +122,20 @@ fn parse_sep(i: &str) -> IResult<&str, &str> {
}
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);
let (i, name) =
take_until_tags(vec!["disconnects", "connects", "sends:", "receives:"].into_iter())(i)?;
let (i, (tagname, _, _)) = tuple((
alt((
tag("connects"),
tag("disconnects"),
tag("sends:"),
tag("receives:"),
)),
space0,
tag("\n"),
))(i)?;
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)),