diff --git a/src/data.rs b/src/data.rs index 91093b7..2449565 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,4 +1,5 @@ use core::cmp::Ordering; +use core::fmt::{Debug, Formatter}; use crate::upcast::IntoUsize; //noinspection SpellCheckingInspection @@ -87,4 +88,62 @@ pub fn iterate(pointer: T) -> T::IterType { pub fn fill_with T>(slice: &mut [T], mut func: F) { slice.iter_mut().enumerate().for_each(|(i,v)|*v = func(i)) +} + +pub struct FixedVec { + length: usize, + buffer: [core::mem::MaybeUninit;MAX_LEN], +} + +impl FixedVec { + pub fn push(&mut self, value: T) -> Option<()> { + if self.length >= MAX_LEN { return None } + unsafe { *self.buffer[self.length].as_mut_ptr() = value }; + self.length += 1; + Some(()) + } + + pub fn pop(&mut self) -> Option { + if self.length == 0 { return None } + self.length -= 1; + Some(unsafe { self.buffer[self.length].assume_init_read() }) + } + + pub fn extend>(&mut self, mut iter: Iter) -> Result { + let mut count = 0; + loop { + if self.length == MAX_LEN { + return Err(count); + } + match iter.next() { + None => return Ok(count), + Some(value) => { + unsafe { *self.buffer[self.length].as_mut_ptr() = value }; + self.length += 1; + count += 1; + } + } + + } + } + + pub fn as_slice(&self) -> &[T] { + // length can't be larger than MaxLen, use unsafe to dodge the panic + unsafe { core::slice::from_raw_parts(self.buffer.as_ptr() as *const T, self.length) } + } + +} + +impl Debug for FixedVec { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + Debug::fmt(self.as_slice(), f) + } +} + +impl Drop for FixedVec { + fn drop(&mut self) { + for e in &mut self.buffer[..self.length] { + unsafe { e.assume_init_drop() } + } + } } \ No newline at end of file diff --git a/src/iter_tools/mod.rs b/src/iter_tools/mod.rs new file mode 100644 index 0000000..52585b8 --- /dev/null +++ b/src/iter_tools/mod.rs @@ -0,0 +1,18 @@ + +mod take_until; +pub use take_until::*; + +pub trait IterTools: Iterator { + + #[inline] + fn take_until

(self, predicate: P) -> TakeUntil + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + TakeUntil::new(self, predicate) + } + +} + +impl IterTools for T {} diff --git a/src/iter_tools/take_until.rs b/src/iter_tools/take_until.rs new file mode 100644 index 0000000..b40b190 --- /dev/null +++ b/src/iter_tools/take_until.rs @@ -0,0 +1,50 @@ + +use core::fmt; + + +#[derive(Clone)] +pub struct TakeUntil { + iter: I, + flag: bool, + predicate: P, +} + +impl TakeUntil { + pub(in super) fn new(iter: I, predicate: P) -> TakeUntil { + TakeUntil { iter, flag: false, predicate } + } +} + +impl Iterator for TakeUntil + where + P: FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.flag { + None + } else { + let x = self.iter.next()?; + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + Some(x) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.flag { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + } +} + + diff --git a/src/lib.rs b/src/lib.rs index b6d8532..2116162 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,4 +42,7 @@ mod hash; pub use hash::*; mod strings; -pub use strings::*; \ No newline at end of file +pub use strings::*; + +mod iter_tools; +pub use iter_tools::*; \ No newline at end of file