use core::{fmt, iter, slice, str::CharIndices}; use crate::Span; pub trait Input: Clone { type Item; type Items: Clone + Iterator; fn items(&self) -> Self::Items; fn slice(&self, span: Span) -> Self; fn len(&self) -> usize; } impl<'a> Input for &'a str { type Item = char; type Items = CharIndices<'a>; fn items(&self) -> Self::Items { self.char_indices() } fn slice(&self, span: Span) -> Self { &self[span] } fn len(&self) -> usize { (*self).len() } } impl<'a> Input for &'a [u8] { type Item = u8; type Items = iter::Enumerate>>; fn items(&self) -> Self::Items { self.iter().copied().enumerate() } fn slice(&self, span: Span) -> Self { &self[span] } fn len(&self) -> usize { (*self).len() } } pub trait Character { fn is_ascii(&self) -> bool; fn is_alphabetic(&self) -> bool; fn is_ascii_alphabetic(&self) -> bool; fn is_numeric(&self) -> bool; fn is_ascii_numeric(&self) -> bool { self.is_ascii() && self.is_numeric() } fn is_whitespace(&self) -> bool; fn is_ascii_whitespace(&self) -> bool; fn is_alphanumeric(&self) -> bool { self.is_alphabetic() || self.is_numeric() } fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphabetic() || self.is_ascii_numeric() } } impl Character for char { fn is_ascii(&self) -> bool { (*self).is_ascii() } fn is_alphabetic(&self) -> bool { (*self).is_ascii_alphabetic() } fn is_ascii_alphabetic(&self) -> bool { (*self).is_ascii_alphabetic() } fn is_numeric(&self) -> bool { (*self).is_numeric() } fn is_whitespace(&self) -> bool { (*self).is_whitespace() } fn is_ascii_whitespace(&self) -> bool { (*self).is_ascii_whitespace() } } impl Character for u8 { fn is_ascii(&self) -> bool { (*self).is_ascii() } fn is_alphabetic(&self) -> bool { (*self).is_ascii_alphabetic() } fn is_ascii_alphabetic(&self) -> bool { (*self).is_ascii_alphabetic() } fn is_numeric(&self) -> bool { (*self).is_ascii_digit() } fn is_whitespace(&self) -> bool { (*self).is_ascii_whitespace() } fn is_ascii_whitespace(&self) -> bool { (*self).is_ascii_whitespace() } } #[derive(Clone)] pub struct InputIter { pub it: I::Items, pub input: I, } impl InputIter where I: Input, { pub fn new(input: I) -> Self { Self { it: input.items(), input, } } pub fn position(&self) -> usize { match self.it.clone().next() { Some((i, _)) => i, None => self.input.len(), } } pub fn is_finished(&self) -> bool { self.clone().next().is_none() } pub fn rest(&self) -> I { self.input.slice(self.position()..self.input.len()) } } impl Iterator for InputIter where I: Input, { type Item = (usize, I::Item); fn next(&mut self) -> Option { self.it.next() } } impl fmt::Debug for InputIter where I: Input + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.rest()) } }