Compare commits

..

3 commits

3 changed files with 141 additions and 4 deletions

View file

@ -1,6 +1,9 @@
use { use {
crate::{ crate::{
view::{InnerViewPort, OuterViewPort, View, ViewPort}, view::{
InnerViewPort, OuterViewPort, View, Observer, ViewPort,
list::*
}
}, },
std::sync::RwLock, std::sync::RwLock,
std::{ std::{
@ -31,6 +34,42 @@ where
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct VecBufferTarget<T>
where T: Clone + Send + Sync + 'static
{
buffer: VecBuffer<T>,
src_view: Option<Arc<dyn ListView<T>>>
}
impl<T> Observer< dyn ListView<T> > for VecBufferTarget<T>
where T: Clone + Send + Sync + 'static
{
fn notify(&mut self, msg: &ListDiff<T>) {
self.buffer.apply_diff(
match msg.clone() {
ListDiff::Clear => VecDiff::Clear,
ListDiff::Remove(idx) => VecDiff::Remove(idx),
ListDiff::Insert{ idx, val } => VecDiff::Insert{ idx, val },
ListDiff::Update{ idx, val } => VecDiff::Update{ idx, val }
}
);
}
fn reset(&mut self, src_view: Option<Arc<dyn ListView<T>>>) {
self.src_view = src_view;
// copy all elements of new view
if let Some(v) = self.src_view.as_ref() {
self.buffer.clear();
for x in v.iter() {
self.buffer.push(x.clone());
}
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)] #[derive(Clone)]
pub struct VecBuffer<T> pub struct VecBuffer<T>
where where
@ -58,6 +97,20 @@ where
} }
} }
pub fn attach_to(&self, port: OuterViewPort< dyn ListView<T> >) -> Arc<RwLock<VecBufferTarget<T>>> {
self.port.0.add_update_hook(Arc::new(port.0.clone()));
let target = Arc::new(RwLock::new(
VecBufferTarget {
buffer: self.clone(),
src_view: None
}
));
port.add_observer(target.clone());
target
}
pub fn with_data(data: Vec<T>) -> Self { pub fn with_data(data: Vec<T>) -> Self {
VecBuffer::with_data_port(data, ViewPort::new().into_inner()) VecBuffer::with_data_port(data, ViewPort::new().into_inner())
} }
@ -133,6 +186,10 @@ where
val: self.get(idx), val: self.get(idx),
} }
} }
pub fn into_inner(self) -> Arc<RwLock<Vec<T>>> {
self.data
}
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -179,7 +236,13 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::buffer::vec::*; use crate::{
buffer::vec::*,
view::{
port::UpdateTask,
list::ListView,
}
};
#[test] #[test]
fn vec_buffer1() { fn vec_buffer1() {
@ -189,5 +252,37 @@ mod tests {
buffer.push('b'); buffer.push('b');
buffer.push('c'); buffer.push('c');
} }
#[test]
fn list_to_vec() {
let mut buf = VecBuffer::<char>::new();
let list_view = buf.get_port().to_list();
let mut buf2 = VecBuffer::new();
let keepalive = buf2.attach_to( list_view.clone() );
assert_eq!(buf2.len(), 0);
buf.push('a');
buf2.get_port().0.update();
assert_eq!(buf2.len(), 1);
assert_eq!(buf2.get(0), 'a');
buf.push('b');
list_view.0.update();
assert_eq!(buf2.len(), 2);
assert_eq!(buf2.get(0), 'a');
assert_eq!(buf2.get(1), 'b');
buf.push('c');
buf.remove(0);
list_view.0.update();
assert_eq!(buf2.len(), 2);
assert_eq!(buf2.get(0), 'b');
assert_eq!(buf2.get(1), 'c');
}
} }

View file

@ -1,7 +1,9 @@
use { use {
crate::{ crate::{
view::{ view::{
InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort, View, ViewPort,
InnerViewPort, OuterViewPort,
Observer, ObserverBroadcast, ObserverExt,
list::{ListView, ListDiff}, list::{ListView, ListDiff},
}, },
buffer::vec::VecDiff, buffer::vec::VecDiff,
@ -69,7 +71,7 @@ where
} }
VecDiff::Push(val) => { VecDiff::Push(val) => {
self.cast.notify(&ListDiff::Insert{ self.cast.notify(&ListDiff::Insert{
idx: self.cur_len + 1, idx: self.cur_len,
val: val.clone() val: val.clone()
}); });
self.cur_len += 1; self.cur_len += 1;

View file

@ -21,6 +21,46 @@ where Item: Clone + Send + Sync + 'static
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub trait ListViewExt<T>: ListView<T>
where T: Clone + Send + Sync + 'static
{
fn iter<'a>(&'a self) -> ListViewIter<'a, T, Self> {
ListViewIter { _phantom: std::marker::PhantomData, view: self, cur: 0 }
}
}
impl<T, V: ListView<T> + ?Sized> ListViewExt<T> for V
where T: Clone + Send + Sync + 'static
{}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ListViewIter<'a, T, V>
where
T: Clone + Send + Sync + 'static,
V: ListView<T> + ?Sized,
{
_phantom: std::marker::PhantomData<T>,
view: &'a V,
cur: usize,
}
impl<'a, T, V> Iterator for ListViewIter<'a, T, V>
where
T: Clone + Send + Sync + 'static,
V: ListView<T> + ?Sized,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let i = self.cur;
self.cur += 1;
self.view.get(&i)
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
use std::sync::RwLock; use std::sync::RwLock;
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};