// Copyright (c) 2016-2021 Fabian Schuiki //! This module provides an abstraction similar to iterators. Elements are //! produced in one direction, while errors bubble backwards until they are //! vented. This allows for complex transformation chains such as lexical //! analyzers and parsers to be constructed, where errors, warnings, or notices //! might be emitted without disturbing the transformation. use std; use std::marker::PhantomData; mod filter; mod lookahead; mod peek; pub mod utf8; pub use self::filter::Filter; pub use self::lookahead::Lookahead; pub use self::peek::Peekable; pub trait Chisel: Default { type Value; fn end() -> Self; fn is_end(&self) -> bool; fn value(self) -> Option; fn value_ref(&self) -> Option<&Self::Value>; } impl Chisel for Option { type Value = T; fn end() -> Option { None } fn is_end(&self) -> bool { self.is_none() } fn value(self) -> Option { self } fn value_ref(&self) -> Option<&T> { self.as_ref() } } pub trait Grinder { type Item: Chisel; type Error; fn next(&mut self) -> Self::Item; fn emit(&mut self, err: Self::Error); #[inline] fn vent(self, f: F) -> Vent where Self: Sized, F: Fn(E), { Vent { inner: self, ventfn: f, phantom: PhantomData, } } #[inline] fn unwrap(self) -> Unwrap where Self: Sized, { Unwrap { inner: self } } #[inline] fn map_err(self, f: F) -> MapErrGrinder where Self: Sized, F: Fn(E) -> Self::Error, { MapErrGrinder { inner: self, mapfn: f, phantom: PhantomData, } } #[inline] fn peekable(self) -> Peekable where Self: Sized, { Peekable::new(self) } #[inline] fn lookaheadable(self) -> Lookahead where Self: Sized, { Lookahead::new(self) } #[inline] fn filter(self, f: F) -> Filter where Self: Sized, F: Fn(&::Value) -> bool, { Filter::new(self, f) } } // All Grinder implement UnventedGrinder. // impl UnventedGrinder for T { // type Item = T::Item; // // fn next(&mut self) -> Self::Item { // self.next() // } // } // // impl Iterator for Grinder { // type Item = ::Item; // fn next(&mut self) -> Option { // self.next().value() // } // } impl, E> Iterator for dyn Grinder { type Item = I; fn next(&mut self) -> Option { self.next().value() } } pub struct Vent { inner: T, ventfn: F, phantom: PhantomData, } impl Grinder for Vent where F: Fn(E), { type Item = T::Item; type Error = E; fn next(&mut self) -> Self::Item { self.inner.next() } fn emit(&mut self, err: E) { (self.ventfn)(err) } } pub struct MapErrGrinder { inner: T, mapfn: F, phantom: PhantomData, } impl Grinder for MapErrGrinder where T: Grinder, F: Fn(E) -> T::Error, { type Item = T::Item; type Error = E; fn next(&mut self) -> Self::Item { self.inner.next() } fn emit(&mut self, err: E) { let e = (self.mapfn)(err); self.inner.emit(e); } } pub struct Read { inner: R, buffer: Vec, ptr: usize, max: usize, } impl Grinder for Read { type Item = Option>; type Error = (); fn next(&mut self) -> Self::Item { if self.ptr >= self.max { self.ptr = 0; match self.inner.read(&mut self.buffer) { Ok(sz) if sz > 0 => self.max = sz, Ok(_) => return None, Err(e) => return Some(Err(e)), } } let v = Some(Ok(self.buffer[self.ptr])); self.ptr += 1; v } fn emit(&mut self, _: ()) { unreachable!() } } // pub fn from_read(read: T) -> Iter>> { // use std::io::Read; // from_iter(std::io::BufReader::with_capacity(1024, read).bytes()) // } pub fn from_read(read: T) -> Read { Read { inner: read, buffer: Vec::with_capacity(1024), ptr: 0, max: 0, } } pub struct Iter { inner: I, } impl Grinder for Iter { type Item = Option; type Error = (); fn next(&mut self) -> Option { self.inner.next() } fn emit(&mut self, _: ()) { unreachable!() } } pub fn from_iter(iter: I) -> Iter { Iter { inner: iter } } pub struct Unwrap { inner: T, } impl Grinder for Unwrap where C: Chisel>, T: Grinder, { type Item = Option; type Error = T::Error; fn emit(&mut self, err: E) { self.inner.emit(err) } fn next(&mut self) -> Self::Item { match self.inner.next().value() { Some(Ok(v)) => Some(v), Some(Err(e)) => { self.emit(e); None } None => None, } } }