index/sequence: get() always return Option

This commit is contained in:
Michael Sippel 2021-01-16 20:19:52 +01:00
parent b62bfa54a0
commit 4fceafcac4
Signed by: senvas
GPG key ID: F96CF119C34B64A6
11 changed files with 49 additions and 98 deletions

View file

@ -22,8 +22,7 @@ pub struct GridOffset<V: GridView + ?Sized> {
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = V::Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = V::Item>>>>
} }
impl<V: 'static + GridView + ?Sized> GridOffset<V> impl<V: 'static + GridView + ?Sized> GridOffset<V> {
where V::Item: Default {
pub fn new(port: InnerViewPort<dyn GridView<Item = V::Item>>) -> Arc<RwLock<Self>> { pub fn new(port: InnerViewPort<dyn GridView<Item = V::Item>>) -> Arc<RwLock<Self>> {
let offset_view = let offset_view =
Arc::new(RwLock::new( Arc::new(RwLock::new(
@ -52,16 +51,11 @@ impl<V: GridView + ?Sized> View for GridOffset<V> {
type Msg = Point2<i16>; type Msg = Point2<i16>;
} }
impl<V: GridView + ?Sized> IndexView<Point2<i16>> for GridOffset<V> impl<V: GridView + ?Sized> IndexView<Point2<i16>> for GridOffset<V> {
where V::Item: Default {
type Item = V::Item; type Item = V::Item;
fn get(&self, pos: &Point2<i16>) -> Self::Item { fn get(&self, pos: &Point2<i16>) -> Option<Self::Item> {
if let Some(src) = self.src.as_ref() { self.src.as_ref()?.get(&(pos - self.offset))
src.get(&(pos - self.offset))
} else {
Self::Item::default()
}
} }
fn area(&self) -> Option<Vec<Point2<i16>>> { fn area(&self) -> Option<Vec<Point2<i16>>> {
@ -74,8 +68,7 @@ where V::Item: Default {
} }
} }
impl<V: GridView + ?Sized> Observer<V> for GridOffset<V> impl<V: GridView + ?Sized> Observer<V> for GridOffset<V> {
where V::Item: Default {
fn reset(&mut self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
let old_area = self.area(); let old_area = self.area();
self.src = view; self.src = view;

View file

@ -19,7 +19,7 @@ pub use {
impl<Key: 'static, Item: 'static> OuterViewPort<dyn IndexView<Key, Item = Item>> { impl<Key: 'static, Item: 'static> OuterViewPort<dyn IndexView<Key, Item = Item>> {
pub fn map_item< pub fn map_item<
DstItem: Default + 'static, DstItem: 'static,
F: Fn(&Item) -> DstItem + Send + Sync + 'static F: Fn(&Item) -> DstItem + Send + Sync + 'static
>( >(
&self, &self,
@ -43,7 +43,7 @@ where SrcView: IndexView<Key> + ?Sized,
impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F>
where Key: 'static, where Key: 'static,
DstItem: Default + 'static, DstItem: 'static,
SrcView: IndexView<Key> + ?Sized + 'static, SrcView: IndexView<Key> + ?Sized + 'static,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync + '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> impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
where DstItem: Default, where SrcView: IndexView<Key> + ?Sized,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync F: Fn(&SrcView::Item) -> DstItem + Send + Sync
{ {
type Item = DstItem; type Item = DstItem;
fn get(&self, key: &Key) -> Self::Item { fn get(&self, key: &Key) -> Option<Self::Item> {
if let Some(v) = self.src_view.as_ref() { self.src_view.as_ref()?.get(key).as_ref().map(&self.f)
(self.f)(&v.get(key))
} else {
DstItem::default()
}
} }
fn area(&self) -> Option<Vec<Key>> { 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> impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
where DstItem: Default, where SrcView: IndexView<Key> + ?Sized,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync F: Fn(&SrcView::Item) -> DstItem + Send + Sync
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {

View file

@ -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< pub fn map_key<
DstKey: 'static, DstKey: 'static,
F1: Fn(&SrcKey) -> DstKey + Send + Sync + '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, where DstKey: 'static,
SrcKey: 'static, SrcKey: 'static,
SrcView: IndexView<SrcKey> + ?Sized + 'static, SrcView: IndexView<SrcKey> + ?Sized + 'static,
SrcView::Item: Default + 'static, SrcView::Item: 'static,
F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static, F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static,
F2: Fn(&DstKey) -> Option<SrcKey> + 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> impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where SrcView: IndexView<SrcKey> + ?Sized, where SrcView: IndexView<SrcKey> + ?Sized,
SrcView::Item: Default,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync, F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{ {
type Item = SrcView::Item; type Item = SrcView::Item;
fn get(&self, key: &DstKey) -> Self::Item { fn get(&self, key: &DstKey) -> Option<Self::Item> {
if let (Some(v), Some(k)) = (self.src_view.as_ref(), (self.f2)(key)) { self.src_view.as_ref()?.get(&(self.f2)(key)?)
v.get(&k)
} else {
Self::Item::default()
}
} }
fn area(&self) -> Option<Vec<DstKey>> { 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> impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where SrcView: IndexView<SrcKey> + ?Sized, where SrcView: IndexView<SrcKey> + ?Sized,
SrcView::Item: Default,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync, F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{ {

View file

@ -15,7 +15,7 @@ use {
pub trait IndexView<Key> : View<Msg = Key> { pub trait IndexView<Key> : View<Msg = Key> {
type Item; 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 // todo: AreaIterator enum to switch between Allocated and Procedural area
fn area(&self) -> Option<Vec<Key>> { 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> { impl<Key, V: IndexView<Key>> IndexView<Key> for RwLock<V> {
type Item = V::Item; type Item = V::Item;
fn get(&self, key: &Key) -> Self::Item { fn get(&self, key: &Key) -> Option<Self::Item> {
self.read().unwrap().get(key) 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> { impl<Key, V: IndexView<Key>> IndexView<Key> for Arc<V> {
type Item = V::Item; type Item = V::Item;
fn get(&self, key: &Key) -> Self::Item { fn get(&self, key: &Key) -> Option<Self::Item> {
self.deref().get(key) self.deref().get(key)
} }
@ -55,7 +55,7 @@ pub trait ImplIndexView : Send + Sync {
type Key; type Key;
type Value; 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>> { fn area(&self) -> Option<Vec<Self::Key>> {
None None
} }
@ -68,7 +68,7 @@ impl<V: ImplIndexView> View for V {
impl<V: ImplIndexView> IndexView<V::Key> for V { impl<V: ImplIndexView> IndexView<V::Key> for V {
type Item = V::Value; 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) (self as &V).get(key)
} }

View file

@ -59,11 +59,6 @@ async fn main() {
let edit_port = ViewPort::<dyn TerminalView>::new(); let edit_port = ViewPort::<dyn TerminalView>::new();
let mut editor = string_editor::StringEditor::new(edit_port.inner()); 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_offset_port = ViewPort::<dyn TerminalView>::new();
let edit_o = GridOffset::new(edit_offset_port.inner()); let edit_o = GridOffset::new(edit_offset_port.inner());
@ -73,32 +68,11 @@ async fn main() {
edit_offset_port edit_offset_port
.into_outer() .into_outer()
// add a nice black background // add a nice black background
.map_item(|atom| atom.map( .map_item(|a| a.add_style_back(TerminalStyle::bg_color((0,0,0))))
|a| a.add_style_back(TerminalStyle::bg_color((0,0,0)))))
); );
edit_o.write().unwrap().set_offset(Vector2::new(40, 4)); 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 // Vec-Buffer
let vec_port = ViewPort::new(); 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 } |pt: &Point2<i16>| if pt.y == 0 { Some(pt.x as usize) } else { None }
) )
.map_item( .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); compositor.push(vec_term_view);
@ -123,6 +97,8 @@ async fn main() {
vec_buf.push('a'); vec_buf.push('a');
vec_buf.push('b'); vec_buf.push('b');
vec_buf.push('c'); vec_buf.push('c');
vec_buf.insert(1, 'x');
vec_buf.remove(2);
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -151,6 +127,7 @@ async fn main() {
Terminal Rendering Terminal Rendering
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
term_writer.show().await.ok(); term_writer.show().await.ok();
} }
@ -158,7 +135,7 @@ async fn main() {
struct Checkerboard; struct Checkerboard;
impl ImplIndexView for Checkerboard { impl ImplIndexView for Checkerboard {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = Option<TerminalAtom>; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<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 { 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); struct TermLabel(String);
impl ImplIndexView for TermLabel { impl ImplIndexView for TermLabel {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = Option<TerminalAtom>; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
if pos.y == 5 { if pos.y == 5 {
@ -206,7 +183,7 @@ impl ImplIndexView for TermLabel {
struct ScrambleBackground; struct ScrambleBackground;
impl ImplIndexView for ScrambleBackground { impl ImplIndexView for ScrambleBackground {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = Option<TerminalAtom>; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
if ((pos.x/2) % 2 == 0) ^ (pos.y % 2 == 0) { if ((pos.x/2) % 2 == 0) ^ (pos.y % 2 == 0) {

View file

@ -14,7 +14,7 @@ use crate::core::View;
pub trait SequenceView : View<Msg = usize> { pub trait SequenceView : View<Msg = usize> {
type Item; type Item;
fn get(&self, idx: usize) -> Self::Item; fn get(&self, idx: &usize) -> Option<Self::Item>;
fn len(&self) -> Option<usize>; fn len(&self) -> Option<usize>;
} }
@ -28,7 +28,7 @@ use std::{
impl<V: SequenceView> SequenceView for RwLock<V> { impl<V: SequenceView> SequenceView for RwLock<V> {
type Item = V::Item; type Item = V::Item;
fn get(&self, idx: usize) -> Self::Item { fn get(&self, idx: &usize) -> Option<Self::Item> {
self.read().unwrap().get(idx) self.read().unwrap().get(idx)
} }
@ -40,7 +40,7 @@ impl<V: SequenceView> SequenceView for RwLock<V> {
impl<V: SequenceView> SequenceView for Arc<V> { impl<V: SequenceView> SequenceView for Arc<V> {
type Item = V::Item; type Item = V::Item;
fn get(&self, idx: usize) -> Self::Item { fn get(&self, idx: &usize) -> Option<Self::Item> {
self.deref().get(idx) self.deref().get(idx)
} }

View file

@ -16,13 +16,13 @@ use {
pub struct Sequence2Index<SrcView> pub struct Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where SrcView: SequenceView + ?Sized + 'static {
src_view: Option<Arc<SrcView>>, 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> impl<SrcView> Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where SrcView: SequenceView + ?Sized + 'static {
pub fn new( pub fn new(
port: InnerViewPort<dyn IndexView<usize, Item = Option<SrcView::Item>>> port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>>
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let s2i = Arc::new(RwLock::new( let s2i = Arc::new(RwLock::new(
Sequence2Index { Sequence2Index {
@ -36,7 +36,7 @@ where SrcView: SequenceView + ?Sized + 'static {
} }
impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> { 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(); let port = ViewPort::new();
self.add_observer(Sequence2Index::new(port.inner())); self.add_observer(Sequence2Index::new(port.inner()));
port.into_outer() port.into_outer()
@ -50,24 +50,15 @@ where SrcView: SequenceView + ?Sized + 'static {
impl<SrcView> IndexView<usize> for Sequence2Index<SrcView> impl<SrcView> IndexView<usize> for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where SrcView: SequenceView + ?Sized + 'static {
type Item = Option<SrcView::Item>; type Item = SrcView::Item;
fn get(&self, key: &usize) -> Self::Item { fn get(&self, key: &usize) -> Option<Self::Item> {
if let Some(v) = self.src_view.as_ref() { self.src_view.as_ref()?.get(key)
if *key < v.len().unwrap_or(usize::MAX) {
return Some(v.get(*key));
}
}
None
} }
fn area(&self) -> Option<Vec<usize>> { fn area(&self) -> Option<Vec<usize>> {
if let Some(v) = self.src_view.as_ref() { let len = self.src_view.as_ref()?.len()?;
if let Some(len) = v.len() { Some((0 .. len).collect())
return Some((0 .. len).collect());
}
}
None
} }
} }

View file

@ -65,8 +65,9 @@ where T: Clone + Send + Sync + 'static {
*l += 1; *l += 1;
}, },
VecDiff::Remove(idx) => { VecDiff::Remove(idx) => {
self.cast.notify(&idx); let mut l = self.cur_len.write().unwrap();
*self.cur_len.write().unwrap() -= 1; *l -= 1;
self.cast.notify_each(*idx .. *l+1);
}, },
VecDiff::Insert{ idx, val: _ } => { VecDiff::Insert{ idx, val: _ } => {
let mut l = self.cur_len.write().unwrap(); let mut l = self.cur_len.write().unwrap();
@ -89,9 +90,10 @@ impl<T> SequenceView for VecSequence<T>
where T: Clone + Send + Sync + 'static { where T: Clone + Send + Sync + 'static {
type Item = T; type Item = T;
fn get(&self, idx: usize) -> T { fn get(&self, idx: &usize) -> Option<T> {
self.data.as_ref().unwrap() self.data.as_ref()?
.read().unwrap()[idx].clone() .read().unwrap()
.get(*idx).cloned()
} }
fn len(&self) -> Option<usize> { fn len(&self) -> Option<usize> {

View file

@ -26,7 +26,7 @@ pub struct StringEditorState {
impl ImplIndexView for StringEditorState { impl ImplIndexView for StringEditorState {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = Option<TerminalAtom>; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let data = self.data.read().unwrap(); let data = self.data.read().unwrap();

View file

@ -55,7 +55,7 @@ pub struct TerminalCompositeView {
impl ImplIndexView for TerminalCompositeView { impl ImplIndexView for TerminalCompositeView {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = Option<TerminalAtom>; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let mut atom = None; let mut atom = None;

View file

@ -18,7 +18,7 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub trait TerminalView = GridView<Item = Option<TerminalAtom>>; pub trait TerminalView = GridView<Item = TerminalAtom>;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>