From f0ac6e6eb3e22c37fe56c84c503b773720c5e94a Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 22 Mar 2024 18:34:42 +0100 Subject: [PATCH] vec buffer: add VecBufferTarget projection and `attach_to()` --- src/buffer/vec.rs | 99 +++++++++++++++++++++++++++++++++++++- src/projection/vec2list.rs | 4 +- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/buffer/vec.rs b/src/buffer/vec.rs index de42a27..cfe0fe4 100644 --- a/src/buffer/vec.rs +++ b/src/buffer/vec.rs @@ -1,6 +1,9 @@ use { crate::{ - view::{InnerViewPort, OuterViewPort, View, ViewPort}, + view::{ + InnerViewPort, OuterViewPort, View, Observer, ViewPort, + list::* + } }, std::sync::RwLock, std::{ @@ -31,6 +34,42 @@ where //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> +pub struct VecBufferTarget +where T: Clone + Send + Sync + 'static +{ + buffer: VecBuffer, + src_view: Option>> +} + +impl Observer< dyn ListView > for VecBufferTarget +where T: Clone + Send + Sync + 'static +{ + fn notify(&mut self, msg: &ListDiff) { + 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>>) { + 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)] pub struct VecBuffer where @@ -58,6 +97,20 @@ where } } + pub fn attach_to(&self, port: OuterViewPort< dyn ListView >) -> Arc>> { + 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) -> Self { VecBuffer::with_data_port(data, ViewPort::new().into_inner()) } @@ -133,6 +186,10 @@ where val: self.get(idx), } } + + pub fn into_inner(self) -> Arc>> { + self.data + } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> @@ -179,7 +236,13 @@ where #[cfg(test)] mod tests { - use crate::buffer::vec::*; + use crate::{ + buffer::vec::*, + view::{ + port::UpdateTask, + list::ListView, + } + }; #[test] fn vec_buffer1() { @@ -189,5 +252,37 @@ mod tests { buffer.push('b'); buffer.push('c'); } + + #[test] + fn list_to_vec() { + let mut buf = VecBuffer::::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'); + } } diff --git a/src/projection/vec2list.rs b/src/projection/vec2list.rs index 0711bc3..febf290 100644 --- a/src/projection/vec2list.rs +++ b/src/projection/vec2list.rs @@ -1,7 +1,9 @@ use { crate::{ view::{ - InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort, + View, ViewPort, + InnerViewPort, OuterViewPort, + Observer, ObserverBroadcast, ObserverExt, list::{ListView, ListDiff}, }, buffer::vec::VecDiff,