pub mod info;
pub mod separator;
pub use info::StrInfo;
use separator::StrSeparator;
use crate::splitter::Splitter;
use core::{num::NonZeroUsize, str::from_utf8};
pub struct StrSplitter<'a, I, S>
where
I: StrInfo<'a>,
S: StrSeparator,
{
#[allow(clippy::type_complexity)]
splitter: Splitter<'a, u8, &'a [u8], S>,
ctx: I::Context,
}
impl<'a, S> StrSplitter<'a, &'a str, S>
where
S: StrSeparator,
{
pub fn new(content: &'a str, sep: S) -> Self {
fn increment(s: &[u8]) -> NonZeroUsize {
let next = from_utf8(s).expect("valid utf8").chars().next();
let len = unsafe { next.unwrap_unchecked().len_utf8() };
unsafe { NonZeroUsize::new_unchecked(len) }
}
Self {
splitter: Splitter::new(content.as_bytes(), sep).with_increment(increment),
ctx: (),
}
}
}
impl<'a, H, S> StrSplitter<'a, H, S>
where
H: StrInfo<'a>,
S: StrSeparator,
{
pub fn with_info<I: StrInfo<'a>>(self) -> StrSplitter<'a, I, S> {
StrSplitter { splitter: self.splitter, ctx: I::Context::default() }
}
}
impl<'a, I, S> Iterator for StrSplitter<'a, I, S>
where
I: StrInfo<'a>,
S: StrSeparator,
{
type Item = I;
fn next(&mut self) -> Option<Self::Item> {
self.splitter.next().map(|b|
I::generate(&mut self.ctx, from_utf8(b).expect("valid utf8"))
)
}
}