use super::generated::case as gen;
#[derive(Clone, Copy)]
#[allow(dead_code)]
pub(crate) enum CaseMap {
Same,
One(char),
Two(char, char),
Three(char, char, char),
}
#[derive(Debug, Clone)]
pub struct CaseMapIter {
buf: [char; 3],
len: u8,
pos: u8,
}
impl CaseMapIter {
#[inline]
fn new(c: char, m: CaseMap) -> Self {
let (buf, len) = match m {
CaseMap::Same => ([c, '\0', '\0'], 1),
CaseMap::One(a) => ([a, '\0', '\0'], 1),
CaseMap::Two(a, b) => ([a, b, '\0'], 2),
CaseMap::Three(a, b, c) => ([a, b, c], 3),
};
CaseMapIter { buf, len, pos: 0 }
}
}
impl Iterator for CaseMapIter {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
if self.pos < self.len {
let c = self.buf[self.pos as usize];
self.pos += 1;
Some(c)
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = (self.len - self.pos) as usize;
(rem, Some(rem))
}
}
impl ExactSizeIterator for CaseMapIter {}
#[inline]
#[must_use]
pub fn to_uppercase(c: char) -> CaseMapIter {
CaseMapIter::new(c, gen::to_upper(c as u32))
}
#[inline]
#[must_use]
pub fn to_lowercase(c: char) -> CaseMapIter {
CaseMapIter::new(c, gen::to_lower(c as u32))
}
#[inline]
#[must_use]
pub fn to_titlecase(c: char) -> CaseMapIter {
CaseMapIter::new(c, gen::to_title(c as u32))
}
#[inline]
#[must_use]
pub fn case_fold(c: char) -> CaseMapIter {
CaseMapIter::new(c, gen::fold(c as u32))
}
#[derive(Clone)]
pub struct CaseMapping<I> {
iter: I,
map: fn(char) -> CaseMapIter,
cur: Option<CaseMapIter>,
}
impl<I: Iterator<Item = char>> Iterator for CaseMapping<I> {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
loop {
if let Some(m) = self.cur.as_mut() {
if let Some(c) = m.next() {
return Some(c);
}
}
let ch = self.iter.next()?;
self.cur = Some((self.map)(ch));
}
}
}
#[inline]
pub fn uppercase<I: Iterator<Item = char>>(iter: I) -> CaseMapping<I> {
CaseMapping {
iter,
map: to_uppercase,
cur: None,
}
}
#[inline]
pub fn lowercase<I: Iterator<Item = char>>(iter: I) -> CaseMapping<I> {
CaseMapping {
iter,
map: to_lowercase,
cur: None,
}
}
#[inline]
pub fn fold<I: Iterator<Item = char>>(iter: I) -> CaseMapping<I> {
CaseMapping {
iter,
map: case_fold,
cur: None,
}
}