use core::iter::FusedIterator;
mod ascii;
mod full;
#[derive(Debug, Clone)]
#[allow(variant_size_differences)]
enum Inner<'a> {
Empty,
Full(full::Uppercase<'a>),
Ascii(ascii::Uppercase<'a>),
}
#[derive(Debug, Clone)]
#[must_use = "Uppercase is a Iterator and must be used"]
pub struct Uppercase<'a> {
iter: Inner<'a>,
}
impl<'a> Uppercase<'a> {
pub const fn new() -> Self {
Self { iter: Inner::Empty }
}
pub const fn with_slice(slice: &'a [u8]) -> Self {
Self {
iter: Inner::Full(full::Uppercase::with_slice(slice)),
}
}
pub const fn with_ascii_slice(slice: &'a [u8]) -> Self {
Self {
iter: Inner::Ascii(ascii::Uppercase::with_slice(slice)),
}
}
}
impl<'a> Iterator for Uppercase<'a> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
match self.iter {
Inner::Empty => None,
Inner::Full(ref mut iter) => iter.next(),
Inner::Ascii(ref mut iter) => iter.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.iter {
Inner::Empty => (0, Some(0)),
Inner::Full(ref iter) => iter.size_hint(),
Inner::Ascii(ref iter) => iter.size_hint(),
}
}
fn count(self) -> usize {
match self.iter {
Inner::Empty => 0,
Inner::Full(iter) => iter.count(),
Inner::Ascii(iter) => iter.count(),
}
}
}
impl<'a> FusedIterator for Uppercase<'a> {}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use bstr::ByteSlice;
use super::Uppercase;
#[test]
fn empty() {
let iter = Uppercase::new();
assert_eq!(iter.collect::<Vec<_>>().as_bstr(), b"".as_bstr());
let iter = Uppercase::with_slice(b"");
assert_eq!(iter.collect::<Vec<_>>().as_bstr(), b"".as_bstr());
let iter = Uppercase::with_ascii_slice(b"");
assert_eq!(iter.collect::<Vec<_>>().as_bstr(), b"".as_bstr());
}
#[test]
fn size_hint() {
assert_eq!(Uppercase::new().size_hint(), (0, Some(0)));
assert_eq!(Uppercase::with_slice(b"abc, xyz").size_hint(), (8, Some(8)));
assert_eq!(
Uppercase::with_slice(b"abc, \xFF\xFE, xyz").size_hint(),
(12, Some(144))
);
assert_eq!(
Uppercase::with_slice("�".as_bytes()).size_hint(),
(3, Some(36))
);
assert_eq!(
Uppercase::with_slice("Έτος".as_bytes()).size_hint(),
(8, Some(96))
);
assert_eq!(
Uppercase::with_slice("ZȺȾ".as_bytes()).size_hint(),
(5, Some(60))
);
let mut utf8_with_invalid_bytes = b"\xFF\xFE".to_vec();
utf8_with_invalid_bytes.extend_from_slice("Έτος".as_bytes());
assert_eq!(
Uppercase::with_slice(&utf8_with_invalid_bytes).size_hint(),
(10, Some(120))
);
assert_eq!(
Uppercase::with_ascii_slice(b"abc, xyz").size_hint(),
(8, Some(8))
);
assert_eq!(
Uppercase::with_ascii_slice(b"abc, \xFF\xFE, xyz").size_hint(),
(12, Some(12))
);
assert_eq!(
Uppercase::with_ascii_slice("�".as_bytes()).size_hint(),
(3, Some(3))
);
assert_eq!(
Uppercase::with_ascii_slice("Έτος".as_bytes()).size_hint(),
(8, Some(8))
);
assert_eq!(
Uppercase::with_ascii_slice("ZȺȾ".as_bytes()).size_hint(),
(5, Some(5))
);
let mut utf8_with_invalid_bytes = b"\xFF\xFE".to_vec();
utf8_with_invalid_bytes.extend_from_slice("Έτος".as_bytes());
assert_eq!(
Uppercase::with_ascii_slice(&utf8_with_invalid_bytes).size_hint(),
(10, Some(10))
);
}
#[test]
fn count() {
assert_eq!(Uppercase::new().count(), 0);
assert_eq!(Uppercase::with_slice(b"abc, xyz").count(), 8);
assert_eq!(Uppercase::with_slice(b"abc, \xFF\xFE, xyz").count(), 12);
assert_eq!(Uppercase::with_slice("�".as_bytes()).count(), 3);
assert_eq!(Uppercase::with_slice("Έτος".as_bytes()).count(), 8);
assert_eq!(Uppercase::with_slice("zⱥⱦ".as_bytes()).count(), 5);
let mut utf8_with_invalid_bytes = b"\xFF\xFE".to_vec();
utf8_with_invalid_bytes.extend_from_slice("Έτος".as_bytes());
assert_eq!(Uppercase::with_slice(&utf8_with_invalid_bytes).count(), 10);
assert_eq!(Uppercase::with_ascii_slice(b"abc, xyz").count(), 8);
assert_eq!(
Uppercase::with_ascii_slice(b"abc, \xFF\xFE, xyz").count(),
12
);
assert_eq!(Uppercase::with_ascii_slice("�".as_bytes()).count(), 3);
assert_eq!(Uppercase::with_ascii_slice("Έτος".as_bytes()).count(), 8);
assert_eq!(Uppercase::with_ascii_slice("ZȺȾ".as_bytes()).count(), 5);
let mut utf8_with_invalid_bytes = b"\xFF\xFE".to_vec();
utf8_with_invalid_bytes.extend_from_slice("Έτος".as_bytes());
assert_eq!(
Uppercase::with_ascii_slice(&utf8_with_invalid_bytes).count(),
10
);
}
#[test]
fn size_hint_covers_count() {
let iter = Uppercase::new();
let (min, max) = iter.size_hint();
let count = iter.count();
assert!(min <= count);
assert!(count <= max.unwrap());
}
}