From b977ab6d26f403787c9d046e6cef342faf678d18 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Thu, 23 May 2024 02:05:11 +0200 Subject: [PATCH] add ReverseSequence projection --- src/projection/mod.rs | 1 + src/projection/reverse_sequence.rs | 142 +++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 src/projection/reverse_sequence.rs diff --git a/src/projection/mod.rs b/src/projection/mod.rs index ec95927..b3ae110 100644 --- a/src/projection/mod.rs +++ b/src/projection/mod.rs @@ -22,4 +22,5 @@ pub mod map_index_item; pub mod map_index_key; pub mod grid_offset; pub mod decorate_sequence; +pub mod reverse_sequence; diff --git a/src/projection/reverse_sequence.rs b/src/projection/reverse_sequence.rs new file mode 100644 index 0000000..c6db151 --- /dev/null +++ b/src/projection/reverse_sequence.rs @@ -0,0 +1,142 @@ +use { + crate::{ + view::{ + Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort, + sequence::SequenceView, + }, + }, + std::sync::Arc, + std::sync::RwLock, +}; + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +impl OuterViewPort> { + pub fn reverse(&self) -> OuterViewPort> { + let port = ViewPort::new(); + port.add_update_hook(Arc::new(self.0.clone())); + + let map = Arc::new(RwLock::new(ReverseSequence { + src_view: None, + end: 0, + cast: port.inner().get_broadcast(), + })); + + self.add_observer(map.clone()); + port.inner().set_view(Some(map)); + port.into_outer() + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub struct ReverseSequence +where SrcView: SequenceView + ?Sized +{ + src_view: Option>, + end: usize, + cast: Arc>>> +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +impl View for ReverseSequence +where SrcView: SequenceView + ?Sized +{ + type Msg = usize; +} + +impl SequenceView for ReverseSequence +where SrcView: SequenceView + ?Sized +{ + type Item = SrcView::Item; + + fn len(&self) -> Option { + self.src_view.len() + } + + fn get(&self, idx: &usize) -> Option { + let len = self.src_view.len().unwrap(); + if *idx < len { + let end = len - 1; + self.src_view.get( &(end - idx) ) + } else { + None + } + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +impl Observer for ReverseSequence +where SrcView: SequenceView + ?Sized +{ + fn reset(&mut self, view: Option>) { + let old_len = self.len(); + self.src_view = view; + let new_len = self.len(); + + if let Some(len) = old_len { + self.cast.notify_each(0..len); + } + if let Some(len) = new_len { + self.cast.notify_each(0..len); + self.end = if len > 0 { len - 1 } else { 0 }; + } + } + + fn notify(&mut self, idx: &usize) { + /* todo optimize + */ + let len = self.src_view.len().unwrap(); + let new_end = if len > 0 { len - 1 } else { 0 }; + if new_end < self.end { + self.cast.notify_each( 0 ..= self.end ); + self.end = new_end; + } else { + self.cast.notify_each( 0 ..= new_end ); + self.end = new_end; +// self.cast.notify( &(self.end - idx) ); + } + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +#[cfg(test)] +mod tests { + use crate::buffer::vec::*; + use crate::projection::map_sequence::*; + + use crate::view::{port::UpdateTask, sequence::SequenceView}; + + #[test] + fn rev_seq1() { + let mut buffer = VecBuffer::new(); + + let target_port = buffer.get_port().to_sequence().reverse(); + let target_view = target_port.get_view(); + + buffer.push(0); + buffer.push(7); + buffer.push(9); + + target_port.0.update(); + + assert_eq!(target_view.len(), Some(3)); + + assert_eq!(target_view.get(&0), Some(9)); + assert_eq!(target_view.get(&1), Some(7)); + assert_eq!(target_view.get(&2), Some(0)); + assert_eq!(target_view.get(&3), None); + + buffer.remove(0); + + target_port.0.update(); + assert_eq!(target_view.len(), Some(2)); + assert_eq!(target_view.get(&0), Some(9)); + assert_eq!(target_view.get(&1), Some(7)); + assert_eq!(target_view.get(&2), None); + } +} +