Skip to content
Snippets Groups Projects
Unverified Commit 54a6046d authored by Xiliang Chen's avatar Xiliang Chen Committed by GitHub
Browse files

implement Drop for enumerator (#28)

* implement Drop for enumerator

* add drop
parent 58146e4a
No related branches found
No related tags found
No related merge requests found
use codec::{Decode, Encode};
use rstd::{iter, marker};
use rstd::{iter, marker, prelude::*};
use sr_primitives::{traits::Member, RuntimeDebug};
use support::{Parameter, StorageMap};
......@@ -17,11 +17,11 @@ impl<Item> Default for LinkedItem<Item> {
pub struct LinkedList<Storage, Key, Item>(rstd::marker::PhantomData<(Storage, Key, Item)>);
impl<'a, Storage, Key, Value> LinkedList<Storage, Key, Value>
impl<Storage, Key, Value> LinkedList<Storage, Key, Value>
where
Value: Parameter + Member + Copy,
Key: Parameter,
Storage: StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
Storage: 'static + StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
{
fn read_head(key: &Key) -> LinkedItem<Value> {
Self::read(key, None)
......@@ -88,66 +88,73 @@ where
}
}
pub fn enumerate(key: &'a Key) -> Enumerator<'a, Key, Value, Self> {
Enumerator::<'a, Key, Value, Self> {
key,
should_take: false,
linkage: Self::read_head(key),
_phantom: Default::default(),
}
pub fn enumerate(key: &Key) -> Enumerator<Key, Value, Self> {
Enumerator::<Key, Value, Self>::new(key, false, Self::read_head(key))
}
pub fn take_all(key: &'a Key) -> Enumerator<'a, Key, Value, Self> {
Enumerator::<'a, Key, Value, Self> {
key,
should_take: true,
linkage: Self::read_head(key),
_phantom: Default::default(),
}
pub fn take_all(key: &Key) -> Enumerator<Key, Value, Self> {
Enumerator::<Key, Value, Self>::new(key, true, Self::read_head(key))
}
}
pub struct Enumerator<'a, Key, Value, LinkedList> {
key: &'a Key,
pub struct Enumerator<Key, Value, LinkedList> {
key: Key,
should_take: bool,
linkage: LinkedItem<Value>,
next_fn: fn(&mut Enumerator<Key, Value, LinkedList>) -> Option<Value>,
_phantom: marker::PhantomData<LinkedList>,
}
impl<'a, Key, Value, Storage> iter::Iterator for Enumerator<'a, Key, Value, LinkedList<Storage, Key, Value>>
impl<Key, Value, Storage> Enumerator<Key, Value, LinkedList<Storage, Key, Value>>
where
Key: Parameter,
Value: Parameter + Member + Copy,
Storage: StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
Storage: 'static + StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
{
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
fn new(key: &Key, should_take: bool, linkage: LinkedItem<Value>) -> Self {
Self {
key: key.clone(),
should_take,
linkage,
next_fn: Self::next,
_phantom: Default::default(),
}
}
fn next(&mut self) -> Option<Value> {
let next_value = self.linkage.next?;
if self.should_take {
self.linkage = <LinkedList<Storage, Key, Value>>::take(self.key, next_value);
self.linkage = <LinkedList<Storage, Key, Value>>::take(&self.key, next_value);
} else {
self.linkage = <LinkedList<Storage, Key, Value>>::read(self.key, Some(next_value));
self.linkage = <LinkedList<Storage, Key, Value>>::read(&self.key, Some(next_value));
}
Some(next_value)
}
}
// FIXME: error[E0366]: Implementations of Drop cannot be specialized
// impl<'a, Key, Value, Storage> Drop for Enumerator<'a, Key, Value, LinkedList<Storage, Key, Value>>
// where
// Key: Parameter,
// Value: Parameter + Member + Copy,
// Storage: StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
// {
// fn drop(&mut self) {
// if !self.should_take {
// return
// }
// while self.next() != None {}
// }
// }
impl<Key, Value, Storage> iter::Iterator for Enumerator<Key, Value, LinkedList<Storage, Key, Value>>
where
Key: Parameter,
Value: Parameter + Member + Copy,
Storage: 'static + StorageMap<(Key, Option<Value>), LinkedItem<Value>, Query = Option<LinkedItem<Value>>>,
{
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
let next_fn = self.next_fn;
next_fn(self)
}
}
impl<Key, Value, LinkedList> Drop for Enumerator<Key, Value, LinkedList> {
fn drop(&mut self) {
if !self.should_take {
return;
}
let next_fn = self.next_fn;
while next_fn(self).is_some() {}
}
}
#[cfg(test)]
mod tests {
......@@ -386,4 +393,22 @@ mod tests {
assert_eq!(TestLinkedList::enumerate(&0).collect::<Vec<_>>(), []);
});
}
#[test]
fn linked_list_take_all_is_safe() {
new_test_ext().execute_with(|| {
assert_eq!(TestLinkedList::take_all(&0).collect::<Vec<_>>(), []);
TestLinkedList::append(&0, 1);
TestLinkedList::append(&0, 2);
TestLinkedList::append(&0, 3);
let _ = TestLinkedList::take_all(&0);
assert_eq!(TestItem::get(&(0, Some(1))), None);
assert_eq!(TestItem::get(&(0, Some(2))), None);
assert_eq!(TestItem::get(&(0, Some(3))), None);
assert_eq!(TestLinkedList::enumerate(&0).collect::<Vec<_>>(), []);
});
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment