repline: Promote to its own crate!
cl-repl: Major refactor based on the design of typeck.rs
This commit is contained in:
		
							
								
								
									
										68
									
								
								src/iter.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/iter.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
//! Shmancy iterator adapters
 | 
			
		||||
 | 
			
		||||
pub use chars::Chars;
 | 
			
		||||
pub use flatten::Flatten;
 | 
			
		||||
 | 
			
		||||
pub mod chars {
 | 
			
		||||
    //! Converts an <code>[Iterator]<Item = [u8]></code> into an
 | 
			
		||||
    //! <code>[Iterator]<Item = [Result]<[char], [BadUnicode]>></code>
 | 
			
		||||
 | 
			
		||||
    /// Invalid unicode codepoint found when iterating over [Chars]
 | 
			
		||||
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 | 
			
		||||
    pub struct BadUnicode(pub u32);
 | 
			
		||||
    impl std::error::Error for BadUnicode {}
 | 
			
		||||
    impl std::fmt::Display for BadUnicode {
 | 
			
		||||
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
            let Self(code) = self;
 | 
			
		||||
            write!(f, "Bad unicode: {code}")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Converts an <code>[Iterator]<Item = [u8]></code> into an
 | 
			
		||||
    /// <code>[Iterator]<Item = [char]></code>
 | 
			
		||||
    #[derive(Clone, Debug)]
 | 
			
		||||
    pub struct Chars<I: Iterator<Item = u8>>(pub I);
 | 
			
		||||
    impl<I: Iterator<Item = u8>> Iterator for Chars<I> {
 | 
			
		||||
        type Item = Result<char, BadUnicode>;
 | 
			
		||||
        fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
            let Self(bytes) = self;
 | 
			
		||||
            let start = bytes.next()? as u32;
 | 
			
		||||
            let (mut out, count) = match start {
 | 
			
		||||
                start if start & 0x80 == 0x00 => (start, 0), // ASCII valid range
 | 
			
		||||
                start if start & 0xe0 == 0xc0 => (start & 0x1f, 1), // 1 continuation byte
 | 
			
		||||
                start if start & 0xf0 == 0xe0 => (start & 0x0f, 2), // 2 continuation bytes
 | 
			
		||||
                start if start & 0xf8 == 0xf0 => (start & 0x07, 3), // 3 continuation bytes
 | 
			
		||||
                _ => return None,
 | 
			
		||||
            };
 | 
			
		||||
            for _ in 0..count {
 | 
			
		||||
                let cont = bytes.next()? as u32;
 | 
			
		||||
                if cont & 0xc0 != 0x80 {
 | 
			
		||||
                    return None;
 | 
			
		||||
                }
 | 
			
		||||
                out = out << 6 | (cont & 0x3f);
 | 
			
		||||
            }
 | 
			
		||||
            Some(char::from_u32(out).ok_or(BadUnicode(out)))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
pub mod flatten {
 | 
			
		||||
    //! Flattens an [Iterator] returning [`Result<T, E>`](Result) or [`Option<T>`](Option)
 | 
			
		||||
    //! into a *non-[FusedIterator](std::iter::FusedIterator)* over `T`
 | 
			
		||||
 | 
			
		||||
    /// Flattens an [Iterator] returning [`Result<T, E>`](Result) or [`Option<T>`](Option)
 | 
			
		||||
    /// into a *non-[FusedIterator](std::iter::FusedIterator)* over `T`
 | 
			
		||||
    #[derive(Clone, Debug)]
 | 
			
		||||
    pub struct Flatten<T, I: Iterator<Item = T>>(pub I);
 | 
			
		||||
    impl<T, E, I: Iterator<Item = Result<T, E>>> Iterator for Flatten<Result<T, E>, I> {
 | 
			
		||||
        type Item = T;
 | 
			
		||||
        fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
            self.0.next()?.ok()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    impl<T, I: Iterator<Item = Option<T>>> Iterator for Flatten<Option<T>, I> {
 | 
			
		||||
        type Item = T;
 | 
			
		||||
        fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
            self.0.next()?
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user