Created
July 18, 2020 04:08
-
-
Save cart/824022d8c00a0b95ca2e9431a324a5e0 to your computer and use it in GitHub Desktop.
tracker
This file contains 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 std::{fmt::Debug, ops::{Deref, DerefMut}}; | |
pub struct Track<T> { | |
modified: bool, | |
value: T, | |
} | |
pub trait Tracker { | |
fn is_modified(&self) -> bool; | |
fn reset(&mut self); | |
} | |
impl<T> Tracker for Track<T> { | |
fn is_modified(&self) -> bool { | |
self.is_modified() | |
} | |
fn reset(&mut self) { | |
self.reset() | |
} | |
} | |
impl<T> Track<T> { | |
pub fn new(value: T) -> Self { | |
Self { | |
value, | |
modified: false, | |
} | |
} | |
pub fn reset(&mut self) { | |
self.modified = false; | |
} | |
pub fn is_modified(&self) -> bool { | |
self.modified | |
} | |
} | |
impl<T> Debug for Track<T> where T: Debug { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
self.value.fmt(f) | |
} | |
} | |
impl<T> Deref for Track<T> { | |
type Target = T; | |
fn deref(&self) -> &Self::Target { | |
&self.value | |
} | |
} | |
impl<T> DerefMut for Track<T> { | |
fn deref_mut(&mut self) -> &mut T { | |
self.modified = true; | |
&mut self.value | |
} | |
} | |
pub struct ModifiedIter<I> { | |
iter: I | |
} | |
impl<'a, I, T> Iterator for ModifiedIter<I> where I: Iterator<Item=&'a T>, T: Tracker + 'static { | |
type Item = &'a T; | |
fn next(&mut self) -> Option<Self::Item> { | |
loop { | |
match self.iter.next() { | |
Some(value) => if value.is_modified() { | |
break Some(value); | |
}, | |
None => { | |
break None | |
} | |
} | |
} | |
} | |
} | |
pub trait IntoModifiedIter<I> { | |
fn modified(self) -> ModifiedIter<I>; | |
} | |
impl<'a, I, T> IntoModifiedIter<I> for I where I: Iterator<Item=&'a T>, T: Tracker + 'static { | |
fn modified(self) -> ModifiedIter<I> { | |
ModifiedIter { | |
iter: self | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::{IntoModifiedIter, Track}; | |
#[test] | |
fn track() { | |
let mut x = Track::new(vec![]); | |
assert!(!x.is_modified()); | |
x.push(1); | |
assert!(x.is_modified()); | |
let values = vec![ | |
Track::new(vec![2]), | |
x, | |
Track::new(vec![3]), | |
]; | |
for x in values.iter().modified() { | |
println!("{:?}", x); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment