Implement take_until_tags parser to make it slightly more nom idiomatic
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
0747db35ee
commit
c522257e8c
1 changed files with 44 additions and 46 deletions
90
src/lib.rs
90
src/lib.rs
|
@ -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)),
|
||||
|
|
Loading…
Reference in a new issue