From c60ba8b339d761f52ff044326c469fe671b67ec8 Mon Sep 17 00:00:00 2001 From: Nagata Kana Date: Fri, 13 Dec 2024 20:31:03 +0900 Subject: [PATCH] add slice_ext --- libs/riff/src/lib.rs | 2 ++ libs/riff/src/slice_ext.rs | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 libs/riff/src/slice_ext.rs diff --git a/libs/riff/src/lib.rs b/libs/riff/src/lib.rs index 30b0fa14..2383fb80 100644 --- a/libs/riff/src/lib.rs +++ b/libs/riff/src/lib.rs @@ -6,6 +6,7 @@ mod bitmask_operations; mod change_min_max; mod numeric_traits; mod pop_if; +mod slice_ext; pub use binary_search::BinarySearch; pub use bitmask_iterators::bitmask_combinations; @@ -14,3 +15,4 @@ pub use bitmask_operations::i2powm1; pub use change_min_max::ChangeMinMax; pub use numeric_traits::Unsigned; pub use pop_if::PopIf; +pub use slice_ext::SliceExt; diff --git a/libs/riff/src/slice_ext.rs b/libs/riff/src/slice_ext.rs new file mode 100644 index 00000000..b084a276 --- /dev/null +++ b/libs/riff/src/slice_ext.rs @@ -0,0 +1,44 @@ +/// A trait for slices. +pub trait SliceExt { + type Item; + /// Groups adjacent elements by a predicate. + /// (Rust 1.77.0) + fn chunk_by(&self, f: F) -> SliceChunkBy<'_, Self::Item, F> + where + F: FnMut(&Self::Item, &Self::Item) -> bool; +} +impl SliceExt for [T] { + type Item = T; + + fn chunk_by(&self, f: F) -> SliceChunkBy<'_, Self::Item, F> + where + F: FnMut(&Self::Item, &Self::Item) -> bool, + { + SliceChunkBy { a: self, f } + } +} + +pub struct SliceChunkBy<'a, T, F> { + a: &'a [T], + f: F, +} +impl<'a, T, F> Iterator for SliceChunkBy<'a, T, F> +where + F: FnMut(&T, &T) -> bool, +{ + type Item = &'a [T]; + + fn next(&mut self) -> Option { + let Self { a, f } = self; + if a.is_empty() { + return None; + } + let mut end = 1; + while end < a.len() && f(&a[end - 1], &a[end]) { + end += 1; + } + let (prefix, rest) = a.split_at(end); + self.a = rest; + Some(prefix) + } +}