Skip to content

Instantly share code, notes, and snippets.

@ClarkeRemy
Last active February 15, 2024 17:58
Show Gist options
  • Save ClarkeRemy/88ed7204d44fa2917ba5f88c9114c2ed to your computer and use it in GitHub Desktop.
Save ClarkeRemy/88ed7204d44fa2917ba5f88c9114c2ed to your computer and use it in GitHub Desktop.
GroupBy Rust
use core::{marker::PhantomData, sync::atomic::{AtomicBool, Ordering}};
fn main() {
println!("Hello, world!");
let test = *b"aabba";
let group_by_0 = GroupBy::new(test.into_iter(), |&x|x);
for (key, group) in group_by_0 {
println!("key: {} {{", key as char);
for each in group {
println!("\t{}", each as char)
}
println!("}}")
}
let test = *b"aabba";
let mut group_by_2 = GroupBy::new(test.into_iter(), |&x|x);
let Some(mut a) = group_by_2.next() else {return;};
let b = group_by_2.next();
// creation of b requires a to be dropped
if b.is_none() { println!("master of fate!") }
if let Some(a_) = a.1.next() {
println!("a? {}", a_);
}; // we use a once
drop(a); // a is out of scope
// be can now be made as a is out of scope
let (_,b) = group_by_2.next().expect("a is still in scope");
for b_ in b {
println!("b? {b_}")
}
}
struct GroupBy<
'parent,
Key,
Item,
Iter : Iterator<Item = Item>,
Keygen : Fn(&Item)->Key
> {
iterator : std::iter::Peekable<Iter>,
keygen : Keygen,
boo : PhantomData<&'parent mut ()>,
child : AtomicBool
}
impl< 'parent,
Key, Item,
Iter : Iterator<Item = Item>,
Keygen : Fn(&Item)->Key
>
GroupBy < 'parent, Key, Item, Iter, Keygen> {
fn new(i : Iter, keygen : Keygen)->Self {
Self { iterator: i.peekable(), keygen, boo: PhantomData, child : AtomicBool::new(false) }
}
}
struct Group<
'parent,
Key,
Item,
Iter : Iterator<Item = Item>,
Keygen : Fn(&Item)->Key,
> {
head : Option<Item>,
parent : &'parent mut GroupBy<'parent, Key,Item, Iter, Keygen>
}
impl<'parent, Key, Item, Iter,Keygen>
Iterator for GroupBy<'parent, Key,Item, Iter, Keygen>
where
Iter : Iterator<Item = Item> + 'parent,
Keygen : Fn(&Item)->Key + 'parent,
Item : 'parent,
Key : 'parent
{
type Item = (Key, Group<'parent, Key, Item, Iter, Keygen>);
fn next(&mut self) -> Option<Self::Item> {
if self.child.load(Ordering::Acquire) { return None; }
self.child.store(true, Ordering::Release);
let Some(first) = self.iterator.peek() else {return None};
let key = (self.keygen)(first);
let parent = unsafe{&mut *(self as *mut Self)};
let head = parent.iterator.next();
Some((key, Group { head , parent }))
}
}
impl <'parent, Key, Item, Iter,Keygen>
Iterator for Group<'parent ,Key ,Item ,Iter ,Keygen>
where
Iter : Iterator<Item = Item> + 'parent,
Keygen : Fn(&Item)->Key + 'parent,
Item : PartialEq + 'parent,
Key : 'parent,
{
type Item = Item;
fn next(&mut self) -> Option<Self::Item> {
let head @ Some(_) = self.head.take() else {return None;};
let next_head = self.parent.iterator.peek();
if next_head != head.as_ref() { return head; }
self.head = self.parent.iterator.next();
head
}
}
impl<'parent, Key, Item, Iter,Keygen>
Drop for Group<'parent ,Key ,Item ,Iter ,Keygen>
where
Iter : Iterator<Item = Item> + 'parent,
Keygen : Fn(&Item)->Key + 'parent,
Item : 'parent,
Key : 'parent
{
fn drop(&mut self) {
while let Some(_) = self.parent.next() {}
self.parent.child.store(false, Ordering::Release)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment