From 4fceafcac4ff6d50dfa931c730c0f16af3781387 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Sat, 16 Jan 2021 20:19:52 +0100
Subject: [PATCH] index/sequence: get() always return Option

---
 src/grid/offset.rs         | 17 +++++------------
 src/index/map_item.rs      | 18 ++++++------------
 src/index/map_key.rs       | 14 ++++----------
 src/index/mod.rs           | 10 +++++-----
 src/main.rs                | 39 ++++++++------------------------------
 src/sequence/mod.rs        |  6 +++---
 src/sequence/seq2idx.rs    | 25 ++++++++----------------
 src/sequence/vec_buffer.rs | 12 +++++++-----
 src/string_editor.rs       |  2 +-
 src/terminal/compositor.rs |  2 +-
 src/terminal/mod.rs        |  2 +-
 11 files changed, 49 insertions(+), 98 deletions(-)

diff --git a/src/grid/offset.rs b/src/grid/offset.rs
index ae5928d..459640d 100644
--- a/src/grid/offset.rs
+++ b/src/grid/offset.rs
@@ -22,8 +22,7 @@ pub struct GridOffset<V: GridView + ?Sized> {
     cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = V::Item>>>>
 }
 
-impl<V: 'static + GridView + ?Sized> GridOffset<V>
-where V::Item: Default {
+impl<V: 'static + GridView + ?Sized> GridOffset<V> {
     pub fn new(port: InnerViewPort<dyn GridView<Item = V::Item>>) -> Arc<RwLock<Self>> {
         let offset_view =
             Arc::new(RwLock::new(
@@ -52,16 +51,11 @@ impl<V: GridView + ?Sized> View for GridOffset<V> {
     type Msg = Point2<i16>;
 }
 
-impl<V: GridView + ?Sized> IndexView<Point2<i16>> for GridOffset<V>
-where V::Item: Default {
+impl<V: GridView + ?Sized> IndexView<Point2<i16>> for GridOffset<V> {
     type Item = V::Item;
 
-    fn get(&self, pos: &Point2<i16>) -> Self::Item {
-        if let Some(src) = self.src.as_ref() {
-            src.get(&(pos - self.offset))
-        } else {
-            Self::Item::default()
-        }
+    fn get(&self, pos: &Point2<i16>) -> Option<Self::Item> {
+        self.src.as_ref()?.get(&(pos - self.offset))
     }
 
     fn area(&self) -> Option<Vec<Point2<i16>>> {
@@ -74,8 +68,7 @@ where V::Item: Default {
     }
 }
 
-impl<V: GridView + ?Sized> Observer<V> for GridOffset<V>
-where V::Item: Default {
+impl<V: GridView + ?Sized> Observer<V> for GridOffset<V> {
     fn reset(&mut self, view: Option<Arc<V>>) {
         let old_area = self.area();
         self.src = view;
diff --git a/src/index/map_item.rs b/src/index/map_item.rs
index 0a3e874..f1d4b59 100644
--- a/src/index/map_item.rs
+++ b/src/index/map_item.rs
@@ -19,7 +19,7 @@ pub use {
 
 impl<Key: 'static, Item: 'static> OuterViewPort<dyn IndexView<Key, Item = Item>> {
     pub fn map_item<
-        DstItem: Default + 'static,
+        DstItem: 'static,
         F: Fn(&Item) -> DstItem + Send + Sync + 'static
     >(
         &self,
@@ -43,7 +43,7 @@ where SrcView: IndexView<Key> + ?Sized,
 
 impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F>
 where Key: 'static,
-      DstItem: Default + 'static,
+      DstItem: 'static,
       SrcView: IndexView<Key> + ?Sized + 'static,
       F: Fn(&SrcView::Item) -> DstItem + Send + Sync + 'static
 {
@@ -72,18 +72,13 @@ where SrcView: IndexView<Key> + ?Sized,
 }
 
 impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
-where DstItem: Default,
-      SrcView: IndexView<Key> + ?Sized,
+where SrcView: IndexView<Key> + ?Sized,
       F: Fn(&SrcView::Item) -> DstItem + Send + Sync
 {
     type Item = DstItem;
 
-    fn get(&self, key: &Key) -> Self::Item {
-        if let Some(v) = self.src_view.as_ref() {
-            (self.f)(&v.get(key))
-        } else {
-            DstItem::default()
-        }
+    fn get(&self, key: &Key) -> Option<Self::Item> {
+        self.src_view.as_ref()?.get(key).as_ref().map(&self.f)
     }
 
     fn area(&self) -> Option<Vec<Key>> {
@@ -92,8 +87,7 @@ where DstItem: Default,
 }
 
 impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
-where DstItem: Default,
-      SrcView: IndexView<Key> + ?Sized,
+where SrcView: IndexView<Key> + ?Sized,
       F: Fn(&SrcView::Item) -> DstItem + Send + Sync
 {
     fn reset(&mut self, view: Option<Arc<SrcView>>) {
diff --git a/src/index/map_key.rs b/src/index/map_key.rs
index 73cdce8..8138c3b 100644
--- a/src/index/map_key.rs
+++ b/src/index/map_key.rs
@@ -17,7 +17,7 @@ pub use {
     }
 };
 
-impl<SrcKey: 'static, Item: 'static + Default> OuterViewPort<dyn IndexView<SrcKey, Item = Item>> {
+impl<SrcKey: 'static, Item: 'static> OuterViewPort<dyn IndexView<SrcKey, Item = Item>> {
     pub fn map_key<
         DstKey: 'static,
         F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static,
@@ -49,7 +49,7 @@ impl<DstKey, SrcKey, SrcView, F1, F2> MapIndexKey<DstKey, SrcKey, SrcView, F1, F
 where DstKey: 'static,
       SrcKey: 'static,
       SrcView: IndexView<SrcKey> + ?Sized + 'static,
-      SrcView::Item: Default + 'static,
+      SrcView::Item: 'static,
       F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static,
       F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync + 'static,
 {
@@ -82,18 +82,13 @@ where SrcView: IndexView<SrcKey> + ?Sized,
 
 impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
 where SrcView: IndexView<SrcKey> + ?Sized,
-      SrcView::Item: Default,
       F1: Fn(&SrcKey) -> DstKey + Send + Sync,
       F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
 {
     type Item = SrcView::Item;
 
-    fn get(&self, key: &DstKey) -> Self::Item {
-        if let (Some(v), Some(k)) = (self.src_view.as_ref(), (self.f2)(key)) {
-            v.get(&k)
-        } else {
-            Self::Item::default()
-        }
+    fn get(&self, key: &DstKey) -> Option<Self::Item> {
+        self.src_view.as_ref()?.get(&(self.f2)(key)?)
     }
 
     fn area(&self) -> Option<Vec<DstKey>> {
@@ -103,7 +98,6 @@ where SrcView: IndexView<SrcKey> + ?Sized,
 
 impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
 where SrcView: IndexView<SrcKey> + ?Sized,
-      SrcView::Item: Default,
       F1: Fn(&SrcKey) -> DstKey + Send + Sync,
       F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
 {
diff --git a/src/index/mod.rs b/src/index/mod.rs
index 2ad17c7..8bcf20b 100644
--- a/src/index/mod.rs
+++ b/src/index/mod.rs
@@ -15,7 +15,7 @@ use {
 pub trait IndexView<Key> : View<Msg = Key> {
     type Item;
 
-    fn get(&self, key: &Key) -> Self::Item;
+    fn get(&self, key: &Key) -> Option<Self::Item>;
 
     // todo: AreaIterator enum to switch between Allocated and Procedural area
     fn area(&self) -> Option<Vec<Key>> {
@@ -28,7 +28,7 @@ pub trait IndexView<Key> : View<Msg = Key> {
 impl<Key, V: IndexView<Key>> IndexView<Key> for RwLock<V> {
     type Item = V::Item;
 
-    fn get(&self, key: &Key) -> Self::Item {
+    fn get(&self, key: &Key) -> Option<Self::Item> {
         self.read().unwrap().get(key)
     }
 
@@ -40,7 +40,7 @@ impl<Key, V: IndexView<Key>> IndexView<Key> for RwLock<V> {
 impl<Key, V: IndexView<Key>> IndexView<Key> for Arc<V> {
     type Item = V::Item;
 
-    fn get(&self, key: &Key) -> Self::Item {
+    fn get(&self, key: &Key) -> Option<Self::Item> {
         self.deref().get(key)
     }
 
@@ -55,7 +55,7 @@ pub trait ImplIndexView : Send + Sync {
     type Key;
     type Value;
 
-    fn get(&self, key: &Self::Key) -> Self::Value;
+    fn get(&self, key: &Self::Key) -> Option<Self::Value>;
     fn area(&self) -> Option<Vec<Self::Key>> {
         None
     }    
@@ -68,7 +68,7 @@ impl<V: ImplIndexView> View for V {
 impl<V: ImplIndexView> IndexView<V::Key> for V {
     type Item = V::Value;
 
-    fn get(&self, key: &V::Key) -> Self::Item {
+    fn get(&self, key: &V::Key) -> Option<Self::Item> {
         (self as &V).get(key)
     }
 
diff --git a/src/main.rs b/src/main.rs
index 878bba1..7b858a4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -59,11 +59,6 @@ async fn main() {
         let edit_port = ViewPort::<dyn TerminalView>::new();        
         let mut editor = string_editor::StringEditor::new(edit_port.inner());
 
-        compositor.push(edit_port.outer().map_key(
-            |pt| pt + Vector2::new(4, 2),
-            |pt| Some(pt - Vector2::new(4, 2))
-        ));
-
         let edit_offset_port = ViewPort::<dyn TerminalView>::new();
         let edit_o = GridOffset::new(edit_offset_port.inner());
 
@@ -73,32 +68,11 @@ async fn main() {
             edit_offset_port
                 .into_outer()
                 // add a nice black background
-                .map_item(|atom| atom.map(
-                    |a| a.add_style_back(TerminalStyle::bg_color((0,0,0)))))
+                .map_item(|a| a.add_style_back(TerminalStyle::bg_color((0,0,0))))
         );
 
         edit_o.write().unwrap().set_offset(Vector2::new(40, 4));
 
-        //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
-        // stupid label animation
-        let label_port = ViewPort::<dyn TerminalView>::new();
-        compositor.push(
-            label_port.outer()
-                .map_item(
-                    |atom| atom.map(|atom|
-                                    atom.add_style_back(TerminalStyle::fg_color((255, 255, 255)))
-                                    .add_style_back(TerminalStyle::bg_color((0, 0, 0))))
-                )
-        );
-        task::spawn(async move {
-            loop {
-                label_port.set_view(Some(Arc::new(TermLabel(String::from("Hello")))));
-                task::sleep(std::time::Duration::from_secs(1)).await;
-                label_port.set_view(Some(Arc::new(TermLabel(String::from("I'm a dynamic label")))));
-                task::sleep(std::time::Duration::from_secs(1)).await;
-            }
-        });
-
         //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
         // Vec-Buffer
         let vec_port = ViewPort::new();
@@ -115,7 +89,7 @@ async fn main() {
                 |pt: &Point2<i16>| if pt.y == 0 { Some(pt.x as usize) } else { None }
             )
             .map_item(
-                |c| Some(TerminalAtom::new(c.clone()?, TerminalStyle::fg_color((200, 10, 10))))
+                |c| TerminalAtom::new(*c, TerminalStyle::fg_color((200, 10, 10)))
             );
 
         compositor.push(vec_term_view);
@@ -123,6 +97,8 @@ async fn main() {
         vec_buf.push('a');
         vec_buf.push('b');
         vec_buf.push('c');
+        vec_buf.insert(1, 'x');
+        vec_buf.remove(2);
 
                             /*\
         <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@@ -151,6 +127,7 @@ async fn main() {
                  Terminal Rendering
     <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
                         \*/
+
     term_writer.show().await.ok();
 }
 
@@ -158,7 +135,7 @@ async fn main() {
 struct Checkerboard;
 impl ImplIndexView for Checkerboard {
     type Key = Point2<i16>;
-    type Value = Option<TerminalAtom>;
+    type Value = TerminalAtom;
 
     fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
         if pos.x == 0 || pos.x == 1 || pos.x > 17 || pos.y == 0 || pos.y > 8 {
@@ -183,7 +160,7 @@ impl ImplIndexView for Checkerboard {
 struct TermLabel(String);
 impl ImplIndexView for TermLabel {
     type Key = Point2<i16>;
-    type Value = Option<TerminalAtom>;
+    type Value = TerminalAtom;
 
     fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
         if pos.y == 5 {
@@ -206,7 +183,7 @@ impl ImplIndexView for TermLabel {
 struct ScrambleBackground;
 impl ImplIndexView for ScrambleBackground {
     type Key = Point2<i16>;
-    type Value = Option<TerminalAtom>;
+    type Value = TerminalAtom;
 
     fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
         if ((pos.x/2) % 2 == 0) ^ (pos.y % 2 == 0) {
diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs
index 813ad2d..e80e98a 100644
--- a/src/sequence/mod.rs
+++ b/src/sequence/mod.rs
@@ -14,7 +14,7 @@ use crate::core::View;
 pub trait SequenceView : View<Msg = usize> {
     type Item;
 
-    fn get(&self, idx: usize) -> Self::Item;
+    fn get(&self, idx: &usize) -> Option<Self::Item>;
     fn len(&self) -> Option<usize>;
 }
 
@@ -28,7 +28,7 @@ use std::{
 impl<V: SequenceView> SequenceView for RwLock<V> {
     type Item = V::Item;
 
-    fn get(&self, idx: usize) -> Self::Item {
+    fn get(&self, idx: &usize) -> Option<Self::Item> {
         self.read().unwrap().get(idx)
     }
 
@@ -40,7 +40,7 @@ impl<V: SequenceView> SequenceView for RwLock<V> {
 impl<V: SequenceView> SequenceView for Arc<V> {
     type Item = V::Item;
 
-    fn get(&self, idx: usize) -> Self::Item {
+    fn get(&self, idx: &usize) -> Option<Self::Item> {
         self.deref().get(idx)
     }
 
diff --git a/src/sequence/seq2idx.rs b/src/sequence/seq2idx.rs
index 78134cd..c42af0b 100644
--- a/src/sequence/seq2idx.rs
+++ b/src/sequence/seq2idx.rs
@@ -16,13 +16,13 @@ use {
 pub struct Sequence2Index<SrcView>
 where SrcView: SequenceView + ?Sized + 'static {
     src_view: Option<Arc<SrcView>>,
-    cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<usize, Item = Option<SrcView::Item>>>>>
+    cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<usize, Item = SrcView::Item>>>>
 }
 
 impl<SrcView> Sequence2Index<SrcView>
 where SrcView: SequenceView + ?Sized + 'static {
     pub fn new(
-        port: InnerViewPort<dyn IndexView<usize, Item = Option<SrcView::Item>>>
+        port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>>
     ) -> Arc<RwLock<Self>> {
         let s2i = Arc::new(RwLock::new(
             Sequence2Index {
@@ -36,7 +36,7 @@ where SrcView: SequenceView + ?Sized + 'static {
 }
 
 impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
-    pub fn to_index(&self) -> OuterViewPort<dyn IndexView<usize, Item = Option<Item>>> {
+    pub fn to_index(&self) -> OuterViewPort<dyn IndexView<usize, Item = Item>> {
         let port = ViewPort::new();
         self.add_observer(Sequence2Index::new(port.inner()));
         port.into_outer()
@@ -50,24 +50,15 @@ where SrcView: SequenceView + ?Sized + 'static {
 
 impl<SrcView> IndexView<usize> for Sequence2Index<SrcView>
 where SrcView: SequenceView + ?Sized + 'static {
-    type Item = Option<SrcView::Item>;
+    type Item = SrcView::Item;
 
-    fn get(&self, key: &usize) -> Self::Item {
-        if let Some(v) = self.src_view.as_ref() {
-            if *key < v.len().unwrap_or(usize::MAX) {
-                return Some(v.get(*key));
-            }
-        }
-        None
+    fn get(&self, key: &usize) -> Option<Self::Item> {
+        self.src_view.as_ref()?.get(key)
     }
 
     fn area(&self) -> Option<Vec<usize>> {
-        if let Some(v) = self.src_view.as_ref() {
-            if let Some(len) = v.len() {
-                return Some((0 .. len).collect());
-            }
-        }
-        None
+        let len = self.src_view.as_ref()?.len()?;
+        Some((0 .. len).collect())
     }
 }
 
diff --git a/src/sequence/vec_buffer.rs b/src/sequence/vec_buffer.rs
index 3543b9e..ce6cd6f 100644
--- a/src/sequence/vec_buffer.rs
+++ b/src/sequence/vec_buffer.rs
@@ -65,8 +65,9 @@ where T: Clone + Send + Sync + 'static {
                 *l += 1;
             },
             VecDiff::Remove(idx) => {
-                self.cast.notify(&idx);
-                *self.cur_len.write().unwrap() -= 1;
+                let mut l = self.cur_len.write().unwrap();
+                *l -= 1;
+                self.cast.notify_each(*idx .. *l+1);
             },
             VecDiff::Insert{ idx, val: _ } => {
                 let mut l = self.cur_len.write().unwrap();
@@ -89,9 +90,10 @@ impl<T> SequenceView for VecSequence<T>
 where T: Clone + Send + Sync + 'static {
     type Item = T;
 
-    fn get(&self, idx: usize) -> T {
-        self.data.as_ref().unwrap()
-            .read().unwrap()[idx].clone()
+    fn get(&self, idx: &usize) -> Option<T> {
+        self.data.as_ref()?
+            .read().unwrap()
+            .get(*idx).cloned()
     }
 
     fn len(&self) -> Option<usize> {
diff --git a/src/string_editor.rs b/src/string_editor.rs
index 91c6d72..7b20a89 100644
--- a/src/string_editor.rs
+++ b/src/string_editor.rs
@@ -26,7 +26,7 @@ pub struct StringEditorState {
 
 impl ImplIndexView for StringEditorState {
     type Key = Point2<i16>;
-    type Value = Option<TerminalAtom>;
+    type Value = TerminalAtom;
 
     fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
         let data = self.data.read().unwrap();
diff --git a/src/terminal/compositor.rs b/src/terminal/compositor.rs
index 8352e7e..a52b153 100644
--- a/src/terminal/compositor.rs
+++ b/src/terminal/compositor.rs
@@ -55,7 +55,7 @@ pub struct TerminalCompositeView {
 
 impl ImplIndexView for TerminalCompositeView {
     type Key = Point2<i16>;
-    type Value = Option<TerminalAtom>;
+    type Value = TerminalAtom;
 
     fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
         let mut atom = None;
diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs
index 1d02f02..65d8f8a 100644
--- a/src/terminal/mod.rs
+++ b/src/terminal/mod.rs
@@ -18,7 +18,7 @@ use {
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
-pub trait TerminalView = GridView<Item = Option<TerminalAtom>>;
+pub trait TerminalView = GridView<Item = TerminalAtom>;
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>