mod get_parser;
mod non_parsing_methods;
mod parse_errors;
mod parsing_polymorphism_macros;
mod primitive_parsing;
#[cfg(feature = "parsing_proc")]
mod parser_method_macro;
pub use self::{
get_parser::{HasParser, StdParser},
parse_errors::{ErrorKind, ParseDirection, ParseError},
};
#[cfg(feature = "parsing_proc")]
#[doc(inline)]
pub use self::parser_method_macro::parser_method;
#[doc(inline)]
pub use self::parsing_polymorphism_macros::parse_type;
use crate::string::{self, Pattern};
#[cfg_attr(feature = "parsing_proc", doc = "```rust")]
#[cfg_attr(not(feature = "parsing_proc"), doc = "```ignore")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "parsing")))]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Parser<'a> {
parse_direction: ParseDirection,
yielded_last_split: bool,
start_offset: u32,
str: &'a str,
}
impl<'a> Parser<'a> {
pub const fn split_terminator<'p, P>(&mut self, delimiter: P) -> Result<&'a str, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing! {self, FromStart, ret;
if self.str.is_empty() || self.yielded_last_split {
throw!(if self.yielded_last_split {
ErrorKind::SplitExhausted
} else {
ErrorKind::DelimiterNotFound
})
}
match string::split_once(self.str, delimiter) {
Some((before, after)) => {
self.yielded_last_split = after.is_empty();
self.str = after;
before
}
None => throw!(ErrorKind::DelimiterNotFound),
}
}
}
pub const fn rsplit_terminator<'p, P>(
&mut self,
delimiter: P,
) -> Result<&'a str, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing! {self, FromEnd, ret;
if self.str.is_empty() || self.yielded_last_split {
throw!(if self.yielded_last_split {
ErrorKind::SplitExhausted
} else {
ErrorKind::DelimiterNotFound
})
}
match string::rsplit_once(self.str, delimiter) {
Some((after, before)) => {
self.yielded_last_split = after.is_empty();
self.str = after;
before
}
None => throw!(ErrorKind::DelimiterNotFound),
}
}
}
pub const fn split<'p, P>(&mut self, delimiter: P) -> Result<&'a str, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing! {self, FromStart, ret;
if self.yielded_last_split {
throw!(ErrorKind::SplitExhausted)
}
let (before, after) = match string::split_once(self.str, delimiter) {
Some(pair) => pair,
None => {
self.yielded_last_split = true;
(self.str, string::str_from(self.str, self.str.len()))
}
};
self.str = after;
before
}
}
pub const fn rsplit<'p, P>(&mut self, delimiter: P) -> Result<&'a str, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing! {self, FromEnd, ret;
if self.yielded_last_split {
throw!(ErrorKind::SplitExhausted)
}
let (after, before) = match string::rsplit_once(self.str, delimiter) {
Some(pair) => pair,
None => {
self.yielded_last_split = true;
(string::str_up_to(self.str, 0), self.str)
}
};
self.str = after;
before
}
}
#[cfg_attr(feature = "parsing_proc", doc = "```rust")]
#[cfg_attr(not(feature = "parsing_proc"), doc = "```ignore")]
pub const fn split_keep<'p, P>(&mut self, delimiter: P) -> Result<&'a str, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing! {self, FromStart, ret;
if self.yielded_last_split {
throw!(ErrorKind::SplitExhausted)
}
let (before, after) = match string::find(self.str, delimiter) {
Some(pos) => string::split_at(self.str, pos),
None => {
self.yielded_last_split = true;
(self.str, string::str_from(self.str, self.str.len()))
}
};
self.str = after;
before
}
}
#[inline]
pub const fn strip_prefix<'p, P>(&mut self, matched: P) -> Result<&mut Self, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing_ret_parser! {self, FromStart;
match string::strip_prefix(self.str, matched) {
Some(x) => self.str = x,
None => throw!(ErrorKind::Strip),
}
}
}
#[inline]
pub const fn strip_suffix<'p, P>(&mut self, matched: P) -> Result<&mut Self, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing_ret_parser! {self, FromEnd;
match string::strip_suffix(self.str, matched) {
Some(x) => self.str = x,
None => throw!(ErrorKind::Strip),
}
}
}
pub const fn trim(&mut self) -> &mut Self {
parsing! {self, FromBoth;
self.str = self.str.trim_ascii();
}
self
}
pub const fn trim_start(&mut self) -> &mut Self {
parsing! {self, FromStart;
self.str = self.str.trim_ascii_start();
}
self
}
pub const fn trim_end(&mut self) -> &mut Self {
parsing! {self, FromEnd;
self.str = self.str.trim_ascii_end();
}
self
}
pub const fn trim_matches<'p, P>(&mut self, needle: P) -> &mut Self
where
P: Pattern<'p>,
{
parsing! {self, FromBoth;
self.str = crate::string::trim_matches(self.str, needle);
}
self
}
pub const fn trim_start_matches<'p, P>(&mut self, needle: P) -> &mut Self
where
P: Pattern<'p>,
{
parsing! {self, FromStart;
self.str = crate::string::trim_start_matches(self.str, needle);
}
self
}
pub const fn trim_end_matches<'p, P>(&mut self, needle: P) -> &mut Self
where
P: Pattern<'p>,
{
parsing! {self, FromEnd;
self.str = crate::string::trim_end_matches(self.str, needle);
}
self
}
pub const fn find_skip<'p, P>(&mut self, needle: P) -> Result<&mut Self, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing_ret_parser! {self, FromStart;
self.str = match crate::string::find_skip(self.str, needle) {
Some(x) => x,
None => throw!(ErrorKind::Find),
};
}
}
pub const fn rfind_skip<'p, P>(&mut self, needle: P) -> Result<&mut Self, ParseError<'a>>
where
P: Pattern<'p>,
{
try_parsing_ret_parser! {self, FromEnd;
self.str = match crate::string::rfind_skip(self.str, needle) {
Some(x) => x,
None => throw!(ErrorKind::Find),
};
}
}
}