Last active
February 15, 2024 17:58
-
-
Save ClarkeRemy/88ed7204d44fa2917ba5f88c9114c2ed to your computer and use it in GitHub Desktop.
GroupBy Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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