use crate::signal::Signal;
use std::pin::Pin;
use std::marker::Unpin;
use std::task::{Poll, Context};
use pin_project::pin_project;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MapDiff<K, V> {
Replace {
entries: Vec<(K, V)>,
},
Insert {
key: K,
value: V,
},
Update {
key: K,
value: V,
},
Remove {
key: K,
},
Clear {},
}
impl<K, A> MapDiff<K, A> {
fn map<B, F>(self, mut callback: F) -> MapDiff<K, B> where F: FnMut(A) -> B {
match self {
MapDiff::Replace { entries } => MapDiff::Replace { entries: entries.into_iter().map(|(k, v)| (k, callback(v))).collect() },
MapDiff::Insert { key, value } => MapDiff::Insert { key, value: callback(value) },
MapDiff::Update { key, value } => MapDiff::Update { key, value: callback(value) },
MapDiff::Remove { key } => MapDiff::Remove { key },
MapDiff::Clear {} => MapDiff::Clear {},
}
}
}
#[must_use = "SignalMaps do nothing unless polled"]
pub trait SignalMap {
type Key;
type Value;
fn poll_map_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>>;
}
impl<'a, A> SignalMap for &'a mut A where A: ?Sized + SignalMap + Unpin {
type Key = A::Key;
type Value = A::Value;
#[inline]
fn poll_map_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> {
A::poll_map_change(Pin::new(&mut **self), cx)
}
}
impl<A> SignalMap for Box<A> where A: ?Sized + SignalMap + Unpin {
type Key = A::Key;
type Value = A::Value;
#[inline]
fn poll_map_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> {
A::poll_map_change(Pin::new(&mut *self), cx)
}
}
impl<A> SignalMap for Pin<A>
where A: Unpin + ::std::ops::DerefMut,
A::Target: SignalMap {
type Key = <<A as ::std::ops::Deref>::Target as SignalMap>::Key;
type Value = <<A as ::std::ops::Deref>::Target as SignalMap>::Value;
#[inline]
fn poll_map_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> {
Pin::get_mut(self).as_mut().poll_map_change(cx)
}
}
pub trait SignalMapExt: SignalMap {
#[inline]
fn map_value<A, F>(self, callback: F) -> MapValue<Self, F>
where F: FnMut(Self::Value) -> A,
Self: Sized {
MapValue {
signal: self,
callback,
}
}
#[inline]
fn key_cloned(self, key: Self::Key) -> MapWatchKeySignal<Self>
where Self::Key: Eq,
Self::Value: Clone,
Self: Sized {
MapWatchKeySignal {
signal_map: self,
watch_key: key
}
}
#[inline]
fn poll_map_change_unpin(&mut self, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> where Self: Unpin + Sized {
Pin::new(self).poll_map_change(cx)
}
}
impl<T: ?Sized> SignalMapExt for T where T: SignalMap {}
#[pin_project(project = MapValueProj)]
#[derive(Debug)]
#[must_use = "SignalMaps do nothing unless polled"]
pub struct MapValue<A, B> {
#[pin]
signal: A,
callback: B,
}
impl<A, B, F> SignalMap for MapValue<A, F>
where A: SignalMap,
F: FnMut(A::Value) -> B {
type Key = A::Key;
type Value = B;
#[inline]
fn poll_map_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> {
let MapValueProj { signal, callback } = self.project();
signal.poll_map_change(cx).map(|some| some.map(|change| change.map(|value| callback(value))))
}
}
#[pin_project(project = MapWatchKeySignalProj)]
#[derive(Debug)]
pub struct MapWatchKeySignal<M> where M: SignalMap {
#[pin]
signal_map: M,
watch_key: M::Key,
}
impl<M> Signal for MapWatchKeySignal<M>
where M: SignalMap,
M::Key: PartialEq,
M::Value: Clone {
type Item = Option<M::Value>;
fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let MapWatchKeySignalProj { mut signal_map, watch_key } = self.project();
let mut did_close = false;
let mut most_recent_value: Option<Option<M::Value>> = None;
loop {
match signal_map.as_mut().poll_map_change(cx) {
Poll::Ready(some) => match some {
Some(MapDiff::Replace { entries }) => {
most_recent_value = Some(
entries
.into_iter()
.find(|entry| entry.0 == *watch_key)
.map(|entry| entry.1)
);
},
Some(MapDiff::Insert { key, value }) | Some(MapDiff::Update { key, value }) => {
if key == *watch_key {
most_recent_value = Some(Some(value));
}
continue;
},
Some(MapDiff::Remove { key }) => {
if key == *watch_key {
most_recent_value = Some(None);
}
continue;
},
Some(MapDiff::Clear {}) => {
most_recent_value = Some(None);
continue;
},
None => {
did_close = true;
break;
}
},
Poll::Pending => {
break;
},
}
};
if did_close {
Poll::Ready(None)
} else if most_recent_value.is_some() {
Poll::Ready(most_recent_value)
} else {
Poll::Pending
}
}
}
mod mutable_btree_map {
use super::{SignalMap, SignalMapExt, MapDiff};
use std::pin::Pin;
use std::marker::Unpin;
use std::fmt;
use std::ops::{Deref, Index};
use std::cmp::{Ord, Ordering};
use std::hash::{Hash, Hasher};
use std::collections::BTreeMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::task::{Poll, Context};
use futures_channel::mpsc;
use futures_util::stream::StreamExt;
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use crate::signal_vec::{SignalVec, VecDiff};
#[derive(Debug)]
struct MutableBTreeState<K, V> {
values: BTreeMap<K, V>,
senders: Vec<mpsc::UnboundedSender<MapDiff<K, V>>>,
}
impl<K: Ord, V> MutableBTreeState<K, V> {
#[inline]
fn notify<B: FnMut() -> MapDiff<K, V>>(&mut self, mut change: B) {
self.senders.retain(|sender| {
sender.unbounded_send(change()).is_ok()
});
}
#[inline]
fn notify_clone<A, F>(&mut self, value: Option<A>, mut f: F) where A: Clone, F: FnMut(A) -> MapDiff<K, V> {
if let Some(value) = value {
let mut len = self.senders.len();
if len > 0 {
let mut copy = Some(value);
self.senders.retain(move |sender| {
let value = copy.take().unwrap();
len -= 1;
if len != 0 {
copy = Some(value.clone());
}
sender.unbounded_send(f(value)).is_ok()
});
}
}
}
#[inline]
fn change<A, F>(&self, f: F) -> Option<A> where F: FnOnce() -> A {
if self.senders.is_empty() {
None
} else {
Some(f())
}
}
fn clear(&mut self) {
if !self.values.is_empty() {
self.values.clear();
self.notify(|| MapDiff::Clear {});
}
}
}
impl<K: Ord + Clone, V> MutableBTreeState<K, V> {
fn remove(&mut self, key: &K) -> Option<V> {
let value = self.values.remove(key)?;
let key = self.change(|| key.clone());
self.notify_clone(key, |key| MapDiff::Remove { key });
Some(value)
}
}
impl<K: Clone + Ord, V: Clone> MutableBTreeState<K, V> {
fn entries_cloned(values: &BTreeMap<K, V>) -> Vec<(K, V)> {
values.into_iter().map(|(k, v)| {
(k.clone(), v.clone())
}).collect()
}
fn replace_cloned(&mut self, values: BTreeMap<K, V>) {
let entries = self.change(|| Self::entries_cloned(&values));
self.values = values;
self.notify_clone(entries, |entries| MapDiff::Replace { entries });
}
fn insert_cloned(&mut self, key: K, value: V) -> Option<V> {
let x = self.change(|| (key.clone(), value.clone()));
if let Some(value) = self.values.insert(key, value) {
self.notify_clone(x, |(key, value)| MapDiff::Update { key, value });
Some(value)
} else {
self.notify_clone(x, |(key, value)| MapDiff::Insert { key, value });
None
}
}
fn signal_map_cloned(&mut self) -> MutableSignalMap<K, V> {
let (sender, receiver) = mpsc::unbounded();
if !self.values.is_empty() {
sender.unbounded_send(MapDiff::Replace {
entries: Self::entries_cloned(&self.values),
}).unwrap();
}
self.senders.push(sender);
MutableSignalMap {
receiver
}
}
}
impl<K: Copy + Ord, V: Copy> MutableBTreeState<K, V> {
fn entries(values: &BTreeMap<K, V>) -> Vec<(K, V)> {
values.into_iter().map(|(k, v)| {
(*k, *v)
}).collect()
}
fn replace(&mut self, values: BTreeMap<K, V>) {
let entries = self.change(|| Self::entries(&values));
self.values = values;
self.notify_clone(entries, |entries| MapDiff::Replace { entries });
}
fn insert(&mut self, key: K, value: V) -> Option<V> {
if let Some(value) = self.values.insert(key, value) {
self.notify(|| MapDiff::Update { key, value });
Some(value)
} else {
self.notify(|| MapDiff::Insert { key, value });
None
}
}
fn signal_map(&mut self) -> MutableSignalMap<K, V> {
let (sender, receiver) = mpsc::unbounded();
if !self.values.is_empty() {
sender.unbounded_send(MapDiff::Replace {
entries: Self::entries(&self.values),
}).unwrap();
}
self.senders.push(sender);
MutableSignalMap {
receiver
}
}
}
macro_rules! make_shared {
($t:ty) => {
impl<'a, K, V> PartialEq<BTreeMap<K, V>> for $t where K: PartialEq<K>, V: PartialEq<V> {
#[inline] fn eq(&self, other: &BTreeMap<K, V>) -> bool { **self == *other }
#[inline] fn ne(&self, other: &BTreeMap<K, V>) -> bool { **self != *other }
}
impl<'a, K, V> PartialEq<$t> for $t where K: PartialEq<K>, V: PartialEq<V> {
#[inline] fn eq(&self, other: &$t) -> bool { *self == **other }
#[inline] fn ne(&self, other: &$t) -> bool { *self != **other }
}
impl<'a, K, V> Eq for $t where K: Eq, V: Eq {}
impl<'a, K, V> PartialOrd<BTreeMap<K, V>> for $t where K: PartialOrd<K>, V: PartialOrd<V> {
#[inline]
fn partial_cmp(&self, other: &BTreeMap<K, V>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &*other)
}
}
impl<'a, K, V> PartialOrd<$t> for $t where K: PartialOrd<K>, V: PartialOrd<V> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<'a, K, V> Ord for $t where K: Ord, V: Ord {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<'a, 'b, K, V> Index<&'b K> for $t where K: Ord {
type Output = V;
#[inline]
fn index(&self, key: &'b K) -> &Self::Output {
Index::index(&**self, key)
}
}
impl<'a, K, V> Deref for $t {
type Target = BTreeMap<K, V>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.lock.values
}
}
impl<'a, K, V> Hash for $t where K: Hash, V: Hash {
#[inline]
fn hash<H>(&self, state: &mut H) where H: Hasher {
Hash::hash(&**self, state)
}
}
};
}
#[derive(Debug)]
pub struct MutableBTreeMapLockRef<'a, K, V> where K: 'a, V: 'a {
lock: RwLockReadGuard<'a, MutableBTreeState<K, V>>,
}
make_shared!(MutableBTreeMapLockRef<'a, K, V>);
#[derive(Debug)]
pub struct MutableBTreeMapLockMut<'a, K, V> where K: 'a, V: 'a {
lock: RwLockWriteGuard<'a, MutableBTreeState<K, V>>,
}
make_shared!(MutableBTreeMapLockMut<'a, K, V>);
impl<'a, K, V> MutableBTreeMapLockMut<'a, K, V> where K: Ord {
#[inline]
pub fn clear(&mut self) {
self.lock.clear()
}
}
impl<'a, K, V> MutableBTreeMapLockMut<'a, K, V> where K: Ord + Clone {
#[inline]
pub fn remove(&mut self, key: &K) -> Option<V> {
self.lock.remove(key)
}
}
impl<'a, K, V> MutableBTreeMapLockMut<'a, K, V> where K: Ord + Clone, V: Clone {
#[inline]
pub fn replace_cloned(&mut self, values: BTreeMap<K, V>) {
self.lock.replace_cloned(values)
}
#[inline]
pub fn insert_cloned(&mut self, key: K, value: V) -> Option<V> {
self.lock.insert_cloned(key, value)
}
}
impl<'a, K, V> MutableBTreeMapLockMut<'a, K, V> where K: Ord + Copy, V: Copy {
#[inline]
pub fn replace(&mut self, values: BTreeMap<K, V>) {
self.lock.replace(values)
}
#[inline]
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
self.lock.insert(key, value)
}
}
pub struct MutableBTreeMap<K, V>(Arc<RwLock<MutableBTreeState<K, V>>>);
impl<K, V> MutableBTreeMap<K, V> {
#[inline]
pub fn with_values(values: BTreeMap<K, V>) -> Self {
Self(Arc::new(RwLock::new(MutableBTreeState {
values,
senders: vec![],
})))
}
#[inline]
pub fn lock_ref(&self) -> MutableBTreeMapLockRef<K, V> {
MutableBTreeMapLockRef {
lock: self.0.read().unwrap(),
}
}
#[inline]
pub fn lock_mut(&self) -> MutableBTreeMapLockMut<K, V> {
MutableBTreeMapLockMut {
lock: self.0.write().unwrap(),
}
}
}
impl<K, V> MutableBTreeMap<K, V> where K: Ord {
#[inline]
pub fn new() -> Self {
Self::with_values(BTreeMap::new())
}
}
impl<K, V> MutableBTreeMap<K, V> where K: Ord + Clone, V: Clone {
#[inline]
pub fn signal_map_cloned(&self) -> MutableSignalMap<K, V> {
self.0.write().unwrap().signal_map_cloned()
}
#[inline]
pub fn signal_vec_keys(&self) -> MutableBTreeMapKeys<K, V> {
MutableBTreeMapKeys {
signal: self.signal_map_cloned(),
keys: vec![],
}
}
#[inline]
pub fn entries_cloned(&self) -> MutableBTreeMapEntries<K, V> {
MutableBTreeMapEntries {
signal: self.signal_map_cloned(),
keys: vec![],
}
}
}
impl<K, V> MutableBTreeMap<K, V> where K: Ord + Copy, V: Copy {
#[inline]
pub fn signal_map(&self) -> MutableSignalMap<K, V> {
self.0.write().unwrap().signal_map()
}
#[inline]
pub fn signal_vec_entries(&self) -> MutableBTreeMapEntries<K, V> {
MutableBTreeMapEntries {
signal: self.signal_map(),
keys: vec![],
}
}
}
impl<K, V> fmt::Debug for MutableBTreeMap<K, V> where K: fmt::Debug, V: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let state = self.0.read().unwrap();
fmt.debug_tuple("MutableBTreeMap")
.field(&state.values)
.finish()
}
}
impl<K, V> Serialize for MutableBTreeMap<K, V> where BTreeMap<K, V>: Serialize {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
self.0.read().unwrap().values.serialize(serializer)
}
}
impl<'de, K, V> Deserialize<'de> for MutableBTreeMap<K, V> where BTreeMap<K, V>: Deserialize<'de> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
<BTreeMap<K, V>>::deserialize(deserializer).map(MutableBTreeMap::with_values)
}
}
impl<K, V> Default for MutableBTreeMap<K, V> where K: Ord {
#[inline]
fn default() -> Self {
MutableBTreeMap::new()
}
}
#[derive(Debug)]
#[must_use = "SignalMaps do nothing unless polled"]
pub struct MutableSignalMap<K, V> {
receiver: mpsc::UnboundedReceiver<MapDiff<K, V>>,
}
impl<K, V> Unpin for MutableSignalMap<K, V> {}
impl<K, V> SignalMap for MutableSignalMap<K, V> {
type Key = K;
type Value = V;
#[inline]
fn poll_map_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<MapDiff<Self::Key, Self::Value>>> {
self.receiver.poll_next_unpin(cx)
}
}
#[derive(Debug)]
#[must_use = "SignalVecs do nothing unless polled"]
pub struct MutableBTreeMapKeys<K, V> {
signal: MutableSignalMap<K, V>,
keys: Vec<K>,
}
impl<K, V> Unpin for MutableBTreeMapKeys<K, V> {}
impl<K, V> SignalVec for MutableBTreeMapKeys<K, V> where K: Ord + Clone {
type Item = K;
#[inline]
fn poll_vec_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<VecDiff<Self::Item>>> {
loop {
return match self.signal.poll_map_change_unpin(cx) {
Poll::Ready(Some(diff)) => match diff {
MapDiff::Replace { entries } => {
self.keys = entries.into_iter().map(|(k, _)| k).collect();
Poll::Ready(Some(VecDiff::Replace { values: self.keys.clone() }))
},
MapDiff::Insert { key, value: _ } => {
let index = self.keys.binary_search(&key).unwrap_err();
self.keys.insert(index, key.clone());
Poll::Ready(Some(VecDiff::InsertAt { index, value: key }))
},
MapDiff::Update { .. } => {
continue;
},
MapDiff::Remove { key } => {
let index = self.keys.binary_search(&key).unwrap();
self.keys.remove(index);
Poll::Ready(Some(VecDiff::RemoveAt { index }))
},
MapDiff::Clear {} => {
self.keys.clear();
Poll::Ready(Some(VecDiff::Clear {}))
},
},
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
};
}
}
}
#[derive(Debug)]
#[must_use = "SignalVecs do nothing unless polled"]
pub struct MutableBTreeMapEntries<K, V> {
signal: MutableSignalMap<K, V>,
keys: Vec<K>,
}
impl<K, V> Unpin for MutableBTreeMapEntries<K, V> {}
impl<K, V> SignalVec for MutableBTreeMapEntries<K, V> where K: Ord + Clone {
type Item = (K, V);
#[inline]
fn poll_vec_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<VecDiff<Self::Item>>> {
self.signal.poll_map_change_unpin(cx).map(|opt| opt.map(|diff| {
match diff {
MapDiff::Replace { entries } => {
self.keys = entries.iter().map(|(k, _)| k.clone()).collect();
VecDiff::Replace { values: entries }
},
MapDiff::Insert { key, value } => {
let index = self.keys.binary_search(&key).unwrap_err();
self.keys.insert(index, key.clone());
VecDiff::InsertAt { index, value: (key, value) }
},
MapDiff::Update { key, value } => {
let index = self.keys.binary_search(&key).unwrap();
VecDiff::UpdateAt { index, value: (key, value) }
},
MapDiff::Remove { key } => {
let index = self.keys.binary_search(&key).unwrap();
self.keys.remove(index);
VecDiff::RemoveAt { index }
},
MapDiff::Clear {} => {
self.keys.clear();
VecDiff::Clear {}
},
}
}))
}
}
}
pub use self::mutable_btree_map::*;