move VecBuffer and views into separate vec module
This commit is contained in:
parent
30a3df180b
commit
835a0bf08e
19 changed files with 461 additions and 397 deletions
|
@ -5,7 +5,7 @@ use {
|
||||||
ViewPort,
|
ViewPort,
|
||||||
TypeDict
|
TypeDict
|
||||||
},
|
},
|
||||||
sequence::{VecBuffer},
|
vec::{VecBuffer},
|
||||||
integer::{RadixProjection}
|
integer::{RadixProjection}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,7 +100,7 @@ where V::Msg: Clone {
|
||||||
|
|
||||||
impl<V: View + ?Sized> UpdateTask for ViewPort<V> where V::Msg: Clone + Send + Sync{
|
impl<V: View + ?Sized> UpdateTask for ViewPort<V> where V::Msg: Clone + Send + Sync{
|
||||||
fn update(&self) {
|
fn update(&self) {
|
||||||
let mut v = {
|
let v = {
|
||||||
let t = self.update_hooks.read().unwrap();
|
let t = self.update_hooks.read().unwrap();
|
||||||
t.iter().cloned().collect::<Vec<_>>()
|
t.iter().cloned().collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use {
|
use {
|
||||||
async_std::stream::StreamExt,
|
|
||||||
std::{
|
std::{
|
||||||
sync::{Arc},
|
sync::Arc,
|
||||||
collections::{HashMap, HashSet}
|
collections::HashMap
|
||||||
},
|
},
|
||||||
std::sync::RwLock,
|
std::sync::RwLock,
|
||||||
cgmath::{Point2, Vector2},
|
cgmath::{Point2, Vector2},
|
||||||
|
@ -10,7 +9,6 @@ use {
|
||||||
core::{
|
core::{
|
||||||
View, Observer, ObserverBroadcast, ObserverExt,
|
View, Observer, ObserverBroadcast, ObserverExt,
|
||||||
ViewPort, InnerViewPort, OuterViewPort,
|
ViewPort, InnerViewPort, OuterViewPort,
|
||||||
channel::{ChannelSender, ChannelReceiver},
|
|
||||||
port::UpdateTask
|
port::UpdateTask
|
||||||
},
|
},
|
||||||
grid::{GridView, GridWindowIterator},
|
grid::{GridView, GridWindowIterator},
|
||||||
|
@ -21,7 +19,7 @@ use {
|
||||||
|
|
||||||
impl<Item> OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>
|
impl<Item> OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>
|
||||||
where Item: 'static{
|
where Item: 'static{
|
||||||
pub fn flatten(&self) -> OuterViewPort<dyn GridView<Item = Item>> {
|
pub fn flatten(&self) -> OuterViewPort<dyn GridView<Item = Item> + 'static> {
|
||||||
let port = ViewPort::new();
|
let port = ViewPort::new();
|
||||||
port.add_update_hook(Arc::new(self.0.clone()));
|
port.add_update_hook(Arc::new(self.0.clone()));
|
||||||
Flatten::new(self.clone(), port.inner());
|
Flatten::new(self.clone(), port.inner());
|
||||||
|
@ -177,7 +175,7 @@ where Item: 'static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_limit = self.limit;
|
//let old_limit = self.limit;
|
||||||
self.limit = Point2::new(
|
self.limit = Point2::new(
|
||||||
(0 .. top_range.end.x as usize).map(|x| col_widths[x]).sum(),
|
(0 .. top_range.end.x as usize).map(|x| col_widths[x]).sum(),
|
||||||
(0 .. top_range.end.y as usize).map(|y| row_heights[y]).sum()
|
(0 .. top_range.end.y as usize).map(|y| row_heights[y]).sum()
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
use {
|
use {
|
||||||
std::sync::Arc,
|
cgmath::Vector2,
|
||||||
cgmath::{Point2, Vector2},
|
|
||||||
std::sync::RwLock,
|
|
||||||
crate::{
|
crate::{
|
||||||
core::{
|
core::OuterViewPort,
|
||||||
OuterViewPort
|
grid::GridView
|
||||||
},
|
|
||||||
grid::{GridView}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
impl<Item> OuterViewPort<dyn GridView<Item = Item>>
|
impl<Item> OuterViewPort<dyn GridView<Item = Item>>
|
||||||
where Item: 'static {
|
where Item: 'static {
|
||||||
|
|
|
@ -2,7 +2,8 @@ use {
|
||||||
std::sync::{Arc, RwLock},
|
std::sync::{Arc, RwLock},
|
||||||
crate::{
|
crate::{
|
||||||
core::{InnerViewPort, OuterViewPort},
|
core::{InnerViewPort, OuterViewPort},
|
||||||
sequence::{SequenceView, VecBuffer},
|
sequence::SequenceView,
|
||||||
|
vec::VecBuffer,
|
||||||
projection::ProjectionHelper
|
projection::ProjectionHelper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,8 @@ use {
|
||||||
InnerViewPort,
|
InnerViewPort,
|
||||||
OuterViewPort
|
OuterViewPort
|
||||||
},
|
},
|
||||||
sequence::{SequenceView, VecBuffer}
|
sequence::SequenceView,
|
||||||
|
vec::VecBuffer
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,11 @@ impl ImplIndexView for LeveledTermView {
|
||||||
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
|
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
|
||||||
self.src.get(pos).map(
|
self.src.get(pos).map(
|
||||||
|a| a.add_style_front(
|
|a| a.add_style_front(
|
||||||
if self.level > 0 {
|
if self.level > 1 {
|
||||||
TerminalStyle::bold(true)
|
TerminalStyle::bold(true)
|
||||||
.add(TerminalStyle::bg_color((0, 0, 0)))
|
.add(TerminalStyle::bg_color((0, 0, 0)))
|
||||||
|
} else if self.level > 0 {
|
||||||
|
TerminalStyle::bg_color((40, 40, 40))
|
||||||
} else {
|
} else {
|
||||||
TerminalStyle::bold(false)
|
TerminalStyle::bold(false)
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub mod singleton;
|
||||||
pub mod index;
|
pub mod index;
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
pub mod sequence;
|
pub mod sequence;
|
||||||
|
pub mod vec;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
pub mod integer;
|
pub mod integer;
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
|
||||||
port.get_view_arc()
|
port.get_view_arc()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_index_arg<Key: Hash + Eq + Clone + Send + Sync + 'static, Item: 'static>(
|
pub fn new_index_arg<Key: Hash + Eq + Clone + Send + Sync + std::fmt::Debug + 'static, Item: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
|
port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
|
||||||
notify: impl Fn(&mut P, &Key) + Send + Sync + 'static
|
notify: impl Fn(&mut P, &Key) + Send + Sync + 'static
|
||||||
|
@ -87,7 +87,7 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
|
||||||
(tx, rx): (ChannelSender<D>, ChannelReceiver<D>)
|
(tx, rx): (ChannelSender<D>, ChannelReceiver<D>)
|
||||||
)
|
)
|
||||||
-> Arc<RwLock<ProjectionArg<P, V, D>>>
|
-> Arc<RwLock<ProjectionArg<P, V, D>>>
|
||||||
where V::Msg: Send + Sync,
|
where V::Msg: Send + Sync + std::fmt::Debug,
|
||||||
D::IntoIter: Send + Sync + 'static
|
D::IntoIter: Send + Sync + 'static
|
||||||
{
|
{
|
||||||
let arg = Arc::new(RwLock::new(
|
let arg = Arc::new(RwLock::new(
|
||||||
|
@ -124,18 +124,22 @@ impl<P, V, D> UpdateTask for ProjectionArg<P, V, D>
|
||||||
where P: Send + Sync + 'static,
|
where P: Send + Sync + 'static,
|
||||||
V: View + ?Sized,
|
V: View + ?Sized,
|
||||||
D: ChannelData<Item = V::Msg>,
|
D: ChannelData<Item = V::Msg>,
|
||||||
D::IntoIter: Send + Sync
|
D::IntoIter: Send + Sync,
|
||||||
|
V::Msg: std::fmt::Debug
|
||||||
{
|
{
|
||||||
fn update(&self) {
|
fn update(&self) {
|
||||||
if let Some(p) = self.proj.read().unwrap().upgrade() {
|
if let Some(p) = self.proj.read().unwrap().upgrade() {
|
||||||
if let Some(data) = self.rx.try_recv() {
|
if let Some(data) = self.rx.try_recv() {
|
||||||
for msg in data {
|
for msg in data {
|
||||||
|
//eprintln!("proj update {:?}", msg);
|
||||||
(self.notify)(
|
(self.notify)(
|
||||||
&mut *p.write().unwrap(),
|
&mut *p.write().unwrap(),
|
||||||
&msg
|
&msg
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("proj update: upgrade fail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +148,8 @@ impl<P, V, D> UpdateTask for RwLock<ProjectionArg<P, V, D>>
|
||||||
where P: Send + Sync + 'static,
|
where P: Send + Sync + 'static,
|
||||||
V: View + ?Sized,
|
V: View + ?Sized,
|
||||||
D: ChannelData<Item = V::Msg>,
|
D: ChannelData<Item = V::Msg>,
|
||||||
D::IntoIter: Send + Sync
|
D::IntoIter: Send + Sync,
|
||||||
|
V::Msg: std::fmt::Debug
|
||||||
{
|
{
|
||||||
fn update(&self) {
|
fn update(&self) {
|
||||||
self.read().unwrap().update();
|
self.read().unwrap().update();
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use {
|
use {
|
||||||
async_std::stream::StreamExt,
|
|
||||||
std::{
|
std::{
|
||||||
sync::{Arc},
|
sync::Arc,
|
||||||
collections::{BTreeMap, HashSet}
|
collections::BTreeMap
|
||||||
},
|
},
|
||||||
std::sync::RwLock,
|
std::sync::RwLock,
|
||||||
crate::{
|
crate::{
|
||||||
core::{
|
core::{
|
||||||
View, Observer, ObserverBroadcast, ObserverExt,
|
View, Observer, ObserverBroadcast, ObserverExt,
|
||||||
ViewPort, InnerViewPort, OuterViewPort,
|
ViewPort, InnerViewPort, OuterViewPort,
|
||||||
channel::{ChannelSender, ChannelReceiver},
|
|
||||||
port::UpdateTask
|
port::UpdateTask
|
||||||
},
|
},
|
||||||
sequence::SequenceView,
|
sequence::SequenceView,
|
||||||
|
@ -144,7 +142,7 @@ where Item: 'static
|
||||||
let mut dirty_idx = Vec::new();
|
let mut dirty_idx = Vec::new();
|
||||||
let mut cur_offset = 0;
|
let mut cur_offset = 0;
|
||||||
|
|
||||||
for (chunk_idx, chunk) in self.chunks.iter_mut() {
|
for (_chunk_idx, chunk) in self.chunks.iter_mut() {
|
||||||
let old_offset = chunk.offset;
|
let old_offset = chunk.offset;
|
||||||
chunk.offset = cur_offset;
|
chunk.offset = cur_offset;
|
||||||
chunk.len = chunk.view.len().unwrap_or(0);
|
chunk.len = chunk.view.len().unwrap_or(0);
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
|
|
||||||
pub mod seq2idx;
|
pub mod seq2idx;
|
||||||
pub mod vec_buffer;
|
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod filter;
|
pub mod filter;
|
||||||
pub mod flatten;
|
pub mod flatten;
|
||||||
|
|
||||||
pub use {
|
pub use seq2idx::{Sequence2Index};
|
||||||
seq2idx::{Sequence2Index},
|
|
||||||
vec_buffer::{VecBuffer, VecSequence}
|
|
||||||
};
|
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
|
|
@ -1,362 +0,0 @@
|
||||||
use {
|
|
||||||
std::{
|
|
||||||
sync::Arc,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
io::Write
|
|
||||||
},
|
|
||||||
std::sync::RwLock,
|
|
||||||
async_std::{
|
|
||||||
io::{Read, ReadExt},
|
|
||||||
stream::{StreamExt}
|
|
||||||
},
|
|
||||||
serde::{Serialize, Deserialize, de::DeserializeOwned},
|
|
||||||
crate::{
|
|
||||||
core::{View, Observer, ObserverExt, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort},
|
|
||||||
sequence::SequenceView,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
pub enum VecDiff<T> {
|
|
||||||
Clear,
|
|
||||||
Push(T),
|
|
||||||
Remove(usize),
|
|
||||||
Insert{ idx: usize, val: T },
|
|
||||||
Update{ idx: usize, val: T }
|
|
||||||
}
|
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
||||||
|
|
||||||
impl<T> View for Vec<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
type Msg = VecDiff<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
||||||
|
|
||||||
/// Adapter View implementing `Sequence` for `Vec`
|
|
||||||
pub struct VecSequence<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
cur_len: usize,
|
|
||||||
data: Option<Arc<RwLock<Vec<T>>>>,
|
|
||||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>>
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialization Observer for `Vec`
|
|
||||||
pub struct VecBinWriter<T, W>
|
|
||||||
where T: Clone + Send + Sync + 'static,
|
|
||||||
W: Write + Send + Sync {
|
|
||||||
data: Option<Arc<RwLock<Vec<T>>>>,
|
|
||||||
out: RwLock<W>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VecJsonWriter<T, W>
|
|
||||||
where T: Clone + Send + Sync + 'static,
|
|
||||||
W: Write + Send + Sync {
|
|
||||||
data: Option<Arc<RwLock<Vec<T>>>>,
|
|
||||||
out: RwLock<W>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> OuterViewPort<RwLock<Vec<T>>>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
pub fn to_sequence(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
|
||||||
let port = ViewPort::new();
|
|
||||||
port.add_update_hook(Arc::new(self.0.clone()));
|
|
||||||
|
|
||||||
let vec_seq = VecSequence::new(port.inner());
|
|
||||||
self.add_observer(vec_seq.clone());
|
|
||||||
port.into_outer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> OuterViewPort<RwLock<Vec<T>>>
|
|
||||||
where T: Clone + Serialize + Send + Sync + 'static {
|
|
||||||
pub fn serialize_bin<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecBinWriter<T, W>>> {
|
|
||||||
let writer = Arc::new(RwLock::new(
|
|
||||||
VecBinWriter {
|
|
||||||
data: None,
|
|
||||||
out: RwLock::new(out),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
self.add_observer(writer.clone());
|
|
||||||
writer
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serialize_json<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecJsonWriter<T, W>>> {
|
|
||||||
let writer = Arc::new(RwLock::new(
|
|
||||||
VecJsonWriter {
|
|
||||||
data: None,
|
|
||||||
out: RwLock::new(out),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
self.add_observer(writer.clone());
|
|
||||||
writer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl<T, W> Observer<RwLock<Vec<T>>> for VecBinWriter<T, W>
|
|
||||||
where T: Clone + Serialize + Send + Sync + 'static,
|
|
||||||
W: Write + Send + Sync
|
|
||||||
{
|
|
||||||
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
|
||||||
self.data = view;
|
|
||||||
let mut out = self.out.write().unwrap();
|
|
||||||
|
|
||||||
out.write(&bincode::serialized_size(&VecDiff::<T>::Clear).unwrap().to_le_bytes()).expect("");
|
|
||||||
out.write(&bincode::serialize(&VecDiff::<T>::Clear).unwrap()).expect("");
|
|
||||||
|
|
||||||
if let Some(data) = self.data.as_ref() {
|
|
||||||
for x in data.read().unwrap().iter() {
|
|
||||||
out.write(&bincode::serialized_size(&VecDiff::Push(x)).unwrap().to_le_bytes()).expect("");
|
|
||||||
out.write(&bincode::serialize(&VecDiff::Push(x)).unwrap()).expect("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.flush().expect("");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn notify(&mut self, diff: &VecDiff<T>) {
|
|
||||||
let mut out = self.out.write().unwrap();
|
|
||||||
out.write(&bincode::serialized_size(diff).unwrap().to_le_bytes()).expect("");
|
|
||||||
out.write(&bincode::serialize(diff).unwrap()).expect("");
|
|
||||||
out.flush().expect("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, W> Observer<RwLock<Vec<T>>> for VecJsonWriter<T, W>
|
|
||||||
where T: Clone + Serialize + Send + Sync + 'static,
|
|
||||||
W: Write + Send + Sync
|
|
||||||
{
|
|
||||||
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
|
||||||
self.data = view;
|
|
||||||
|
|
||||||
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::<T>::Clear).unwrap().as_bytes()).expect("");
|
|
||||||
self.out.write().unwrap().write(b"\n").expect("");
|
|
||||||
|
|
||||||
if let Some(data) = self.data.as_ref() {
|
|
||||||
for x in data.read().unwrap().iter() {
|
|
||||||
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::Push(x)).unwrap().as_bytes()).expect("");
|
|
||||||
self.out.write().unwrap().write(b"\n").expect("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.out.write().unwrap().flush().expect("");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn notify(&mut self, diff: &VecDiff<T>) {
|
|
||||||
self.out.write().unwrap().write(serde_json::to_string(diff).unwrap().as_bytes()).expect("");
|
|
||||||
self.out.write().unwrap().write(b"\n").expect("");
|
|
||||||
self.out.write().unwrap().flush().expect("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecSequence<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
pub fn new(
|
|
||||||
port: InnerViewPort<dyn SequenceView<Item = T>>
|
|
||||||
) -> Arc<RwLock<Self>> {
|
|
||||||
let seq = Arc::new(RwLock::new(
|
|
||||||
VecSequence {
|
|
||||||
cur_len: 0,
|
|
||||||
data: None,
|
|
||||||
cast: port.get_broadcast()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
port.set_view(Some(seq.clone()));
|
|
||||||
seq
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Observer<RwLock<Vec<T>>> for VecSequence<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
|
||||||
let old_len = self.cur_len;
|
|
||||||
self.data = view;
|
|
||||||
self.cur_len =
|
|
||||||
if let Some(data) = self.data.as_ref() {
|
|
||||||
data.read().unwrap().len()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
self.cast.notify_each(0 .. std::cmp::max(old_len, self.cur_len));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn notify(&mut self, diff: &VecDiff<T>) {
|
|
||||||
match diff {
|
|
||||||
VecDiff::Clear => {
|
|
||||||
self.cast.notify_each(0 .. self.cur_len);
|
|
||||||
self.cur_len = 0
|
|
||||||
},
|
|
||||||
VecDiff::Push(_) => {
|
|
||||||
self.cast.notify(&self.cur_len);
|
|
||||||
self.cur_len += 1;
|
|
||||||
},
|
|
||||||
VecDiff::Remove(idx) => {
|
|
||||||
self.cast.notify_each(*idx .. self.cur_len);
|
|
||||||
self.cur_len -= 1;
|
|
||||||
},
|
|
||||||
VecDiff::Insert{ idx, val: _ } => {
|
|
||||||
self.cur_len += 1;
|
|
||||||
self.cast.notify_each(*idx .. self.cur_len);
|
|
||||||
},
|
|
||||||
VecDiff::Update{ idx, val: _ } => {
|
|
||||||
self.cast.notify(&idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> View for VecSequence<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
type Msg = usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SequenceView for VecSequence<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
type Item = T;
|
|
||||||
|
|
||||||
fn get(&self, idx: &usize) -> Option<T> {
|
|
||||||
self.data.as_ref()?
|
|
||||||
.read().unwrap()
|
|
||||||
.get(*idx).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> Option<usize> {
|
|
||||||
Some(self.cur_len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct VecBuffer<T>
|
|
||||||
where T: Clone + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
data: Arc<RwLock<Vec<T>>>,
|
|
||||||
cast: Arc<RwLock<ObserverBroadcast<RwLock<Vec<T>>>>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecBuffer<T>
|
|
||||||
where T: DeserializeOwned + Clone + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
pub async fn from_json<R: Read + async_std::io::Read + Unpin>(&mut self, read: R) {
|
|
||||||
let mut bytes = read.bytes();
|
|
||||||
let mut s = String::new();
|
|
||||||
while let Some(Ok(b)) = bytes.next().await {
|
|
||||||
match b {
|
|
||||||
b'\n' => {
|
|
||||||
if s.len() > 0 {
|
|
||||||
let diff = serde_json::from_str::<VecDiff<T>>(&s).expect("error parsing json");
|
|
||||||
self.apply_diff(diff);
|
|
||||||
s.clear();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
c => {
|
|
||||||
s.push(c as char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecBuffer<T>
|
|
||||||
where T: Clone + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
pub fn with_data(
|
|
||||||
data: Vec<T>,
|
|
||||||
port: InnerViewPort<RwLock<Vec<T>>>
|
|
||||||
) -> Self {
|
|
||||||
let data = Arc::new(RwLock::new(data));
|
|
||||||
port.set_view(Some(data.clone()));
|
|
||||||
VecBuffer { data, cast: port.get_broadcast() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
|
|
||||||
VecBuffer::with_data(Vec::new(), port)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn apply_diff(&mut self, diff: VecDiff<T>) {
|
|
||||||
let mut data = self.data.write().unwrap();
|
|
||||||
match &diff {
|
|
||||||
VecDiff::Clear => { data.clear(); },
|
|
||||||
VecDiff::Push(val) => { data.push(val.clone()); },
|
|
||||||
VecDiff::Remove(idx) => { data.remove(*idx); },
|
|
||||||
VecDiff::Insert{ idx, val } => { data.insert(*idx, val.clone()); },
|
|
||||||
VecDiff::Update{ idx, val } => { data[*idx] = val.clone(); }
|
|
||||||
}
|
|
||||||
drop(data);
|
|
||||||
|
|
||||||
self.cast.notify(&diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.data.read().unwrap().len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, idx: usize) -> T {
|
|
||||||
self.data.read().unwrap()[idx].clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.apply_diff(VecDiff::Clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, val: T) {
|
|
||||||
self.apply_diff(VecDiff::Push(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(&mut self, idx: usize) {
|
|
||||||
self.apply_diff(VecDiff::Remove(idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&mut self, idx: usize, val: T) {
|
|
||||||
self.apply_diff(VecDiff::Insert{ idx, val });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, idx: usize, val: T) {
|
|
||||||
self.apply_diff(VecDiff::Update{ idx, val });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut(&mut self, idx: usize) -> MutableVecAccess<T> {
|
|
||||||
MutableVecAccess {
|
|
||||||
buf: self.clone(),
|
|
||||||
idx,
|
|
||||||
val: self.get(idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
||||||
|
|
||||||
pub struct MutableVecAccess<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
buf: VecBuffer<T>,
|
|
||||||
idx: usize,
|
|
||||||
val: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for MutableVecAccess<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
|
||||||
&self.val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for MutableVecAccess<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Drop for MutableVecAccess<T>
|
|
||||||
where T: Clone + Send + Sync + 'static {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.buf.update(self.idx, self.val.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
core::{ViewPort, OuterViewPort},
|
core::{ViewPort, OuterViewPort},
|
||||||
singleton::{SingletonView, SingletonBuffer},
|
singleton::{SingletonView, SingletonBuffer},
|
||||||
sequence::VecBuffer,
|
vec::VecBuffer,
|
||||||
terminal::{TerminalView}
|
terminal::{TerminalView}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub trait TerminalView = GridView<Item = TerminalAtom>;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
sequence::VecBuffer,
|
vec::VecBuffer,
|
||||||
core::{ViewPort, OuterViewPort}
|
core::{ViewPort, OuterViewPort}
|
||||||
},
|
},
|
||||||
cgmath::Point2
|
cgmath::Point2
|
||||||
|
@ -32,7 +32,7 @@ use {
|
||||||
|
|
||||||
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
|
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
|
||||||
let label_port = ViewPort::new();
|
let label_port = ViewPort::new();
|
||||||
let label = VecBuffer::with_data(s.chars().collect(), label_port.inner());
|
let _label = VecBuffer::with_data(s.chars().collect(), label_port.inner());
|
||||||
label_port.outer()
|
label_port.outer()
|
||||||
.to_sequence()
|
.to_sequence()
|
||||||
.map(|c| TerminalAtom::from(c))
|
.map(|c| TerminalAtom::from(c))
|
||||||
|
|
129
nested/src/vec/buffer.rs
Normal file
129
nested/src/vec/buffer.rs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
use {
|
||||||
|
std::{
|
||||||
|
sync::Arc,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
},
|
||||||
|
std::sync::RwLock,
|
||||||
|
crate::{
|
||||||
|
core::{View, Observer, ObserverBroadcast, InnerViewPort},
|
||||||
|
vec::VecDiff
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
impl<T> View for Vec<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
type Msg = VecDiff<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct VecBuffer<T>
|
||||||
|
where T: Clone + Send + Sync + 'static
|
||||||
|
{
|
||||||
|
data: Arc<RwLock<Vec<T>>>,
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<RwLock<Vec<T>>>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> VecBuffer<T>
|
||||||
|
where T: Clone + Send + Sync + 'static
|
||||||
|
{
|
||||||
|
pub fn with_data(
|
||||||
|
data: Vec<T>,
|
||||||
|
port: InnerViewPort<RwLock<Vec<T>>>
|
||||||
|
) -> Self {
|
||||||
|
let data = Arc::new(RwLock::new(data));
|
||||||
|
port.set_view(Some(data.clone()));
|
||||||
|
VecBuffer { data, cast: port.get_broadcast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
|
||||||
|
VecBuffer::with_data(Vec::new(), port)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_diff(&mut self, diff: VecDiff<T>) {
|
||||||
|
let mut data = self.data.write().unwrap();
|
||||||
|
match &diff {
|
||||||
|
VecDiff::Clear => { data.clear(); },
|
||||||
|
VecDiff::Push(val) => { data.push(val.clone()); },
|
||||||
|
VecDiff::Remove(idx) => { data.remove(*idx); },
|
||||||
|
VecDiff::Insert{ idx, val } => { data.insert(*idx, val.clone()); },
|
||||||
|
VecDiff::Update{ idx, val } => { data[*idx] = val.clone(); }
|
||||||
|
}
|
||||||
|
drop(data);
|
||||||
|
|
||||||
|
self.cast.notify(&diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.data.read().unwrap().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, idx: usize) -> T {
|
||||||
|
self.data.read().unwrap()[idx].clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.apply_diff(VecDiff::Clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, val: T) {
|
||||||
|
self.apply_diff(VecDiff::Push(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, idx: usize) {
|
||||||
|
self.apply_diff(VecDiff::Remove(idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, idx: usize, val: T) {
|
||||||
|
self.apply_diff(VecDiff::Insert{ idx, val });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, idx: usize, val: T) {
|
||||||
|
self.apply_diff(VecDiff::Update{ idx, val });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self, idx: usize) -> MutableVecAccess<T> {
|
||||||
|
MutableVecAccess {
|
||||||
|
buf: self.clone(),
|
||||||
|
idx,
|
||||||
|
val: self.get(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct MutableVecAccess<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
buf: VecBuffer<T>,
|
||||||
|
idx: usize,
|
||||||
|
val: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for MutableVecAccess<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DerefMut for MutableVecAccess<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Drop for MutableVecAccess<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.buf.update(self.idx, self.val.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
25
nested/src/vec/mod.rs
Normal file
25
nested/src/vec/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
pub mod buffer;
|
||||||
|
pub mod vec2seq;
|
||||||
|
pub mod vec2json;
|
||||||
|
pub mod vec2bin;
|
||||||
|
|
||||||
|
pub use {
|
||||||
|
buffer::VecBuffer
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
use {
|
||||||
|
serde::{Serialize, Deserialize}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub enum VecDiff<T> {
|
||||||
|
Clear,
|
||||||
|
Push(T),
|
||||||
|
Remove(usize),
|
||||||
|
Insert{ idx: usize, val: T },
|
||||||
|
Update{ idx: usize, val: T }
|
||||||
|
}
|
||||||
|
|
67
nested/src/vec/vec2bin.rs
Normal file
67
nested/src/vec/vec2bin.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use {
|
||||||
|
std::{
|
||||||
|
sync::Arc,
|
||||||
|
io::Write
|
||||||
|
},
|
||||||
|
std::sync::RwLock,
|
||||||
|
serde::Serialize,
|
||||||
|
crate::{
|
||||||
|
core::{Observer, OuterViewPort},
|
||||||
|
vec::VecDiff
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
/// Serialization Observer for `Vec`
|
||||||
|
pub struct VecBinWriter<T, W>
|
||||||
|
where T: Clone + Send + Sync + 'static,
|
||||||
|
W: Write + Send + Sync {
|
||||||
|
data: Option<Arc<RwLock<Vec<T>>>>,
|
||||||
|
out: RwLock<W>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> OuterViewPort<RwLock<Vec<T>>>
|
||||||
|
where T: Clone + Serialize + Send + Sync + 'static {
|
||||||
|
pub fn serialize_bin<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecBinWriter<T, W>>> {
|
||||||
|
let writer = Arc::new(RwLock::new(
|
||||||
|
VecBinWriter {
|
||||||
|
data: None,
|
||||||
|
out: RwLock::new(out),
|
||||||
|
}
|
||||||
|
));
|
||||||
|
self.add_observer(writer.clone());
|
||||||
|
writer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, W> Observer<RwLock<Vec<T>>> for VecBinWriter<T, W>
|
||||||
|
where T: Clone + Serialize + Send + Sync + 'static,
|
||||||
|
W: Write + Send + Sync
|
||||||
|
{
|
||||||
|
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
||||||
|
self.data = view;
|
||||||
|
let mut out = self.out.write().unwrap();
|
||||||
|
|
||||||
|
out.write(&bincode::serialized_size(&VecDiff::<T>::Clear).unwrap().to_le_bytes()).expect("");
|
||||||
|
out.write(&bincode::serialize(&VecDiff::<T>::Clear).unwrap()).expect("");
|
||||||
|
|
||||||
|
if let Some(data) = self.data.as_ref() {
|
||||||
|
for x in data.read().unwrap().iter() {
|
||||||
|
out.write(&bincode::serialized_size(&VecDiff::Push(x)).unwrap().to_le_bytes()).expect("");
|
||||||
|
out.write(&bincode::serialize(&VecDiff::Push(x)).unwrap()).expect("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flush().expect("");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify(&mut self, diff: &VecDiff<T>) {
|
||||||
|
let mut out = self.out.write().unwrap();
|
||||||
|
out.write(&bincode::serialized_size(diff).unwrap().to_le_bytes()).expect("");
|
||||||
|
out.write(&bincode::serialize(diff).unwrap()).expect("");
|
||||||
|
out.flush().expect("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
91
nested/src/vec/vec2json.rs
Normal file
91
nested/src/vec/vec2json.rs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
use {
|
||||||
|
std::{
|
||||||
|
sync::Arc,
|
||||||
|
io::Write
|
||||||
|
},
|
||||||
|
std::sync::RwLock,
|
||||||
|
async_std::{
|
||||||
|
io::{Read, ReadExt},
|
||||||
|
stream::{StreamExt}
|
||||||
|
},
|
||||||
|
serde::{Serialize, de::DeserializeOwned},
|
||||||
|
crate::{
|
||||||
|
core::{Observer, OuterViewPort},
|
||||||
|
vec::{VecDiff, VecBuffer}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct VecJsonWriter<T, W>
|
||||||
|
where T: Clone + Send + Sync + 'static,
|
||||||
|
W: Write + Send + Sync {
|
||||||
|
data: Option<Arc<RwLock<Vec<T>>>>,
|
||||||
|
out: RwLock<W>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> OuterViewPort<RwLock<Vec<T>>>
|
||||||
|
where T: Clone + Serialize + Send + Sync + 'static {
|
||||||
|
pub fn serialize_json<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecJsonWriter<T, W>>> {
|
||||||
|
let writer = Arc::new(RwLock::new(
|
||||||
|
VecJsonWriter {
|
||||||
|
data: None,
|
||||||
|
out: RwLock::new(out),
|
||||||
|
}
|
||||||
|
));
|
||||||
|
self.add_observer(writer.clone());
|
||||||
|
writer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, W> Observer<RwLock<Vec<T>>> for VecJsonWriter<T, W>
|
||||||
|
where T: Clone + Serialize + Send + Sync + 'static,
|
||||||
|
W: Write + Send + Sync
|
||||||
|
{
|
||||||
|
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
||||||
|
self.data = view;
|
||||||
|
|
||||||
|
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::<T>::Clear).unwrap().as_bytes()).expect("");
|
||||||
|
self.out.write().unwrap().write(b"\n").expect("");
|
||||||
|
|
||||||
|
if let Some(data) = self.data.as_ref() {
|
||||||
|
for x in data.read().unwrap().iter() {
|
||||||
|
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::Push(x)).unwrap().as_bytes()).expect("");
|
||||||
|
self.out.write().unwrap().write(b"\n").expect("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.out.write().unwrap().flush().expect("");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify(&mut self, diff: &VecDiff<T>) {
|
||||||
|
self.out.write().unwrap().write(serde_json::to_string(diff).unwrap().as_bytes()).expect("");
|
||||||
|
self.out.write().unwrap().write(b"\n").expect("");
|
||||||
|
self.out.write().unwrap().flush().expect("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> VecBuffer<T>
|
||||||
|
where T: DeserializeOwned + Clone + Send + Sync + 'static
|
||||||
|
{
|
||||||
|
pub async fn from_json<R: Read + async_std::io::Read + Unpin>(&mut self, read: R) {
|
||||||
|
let mut bytes = read.bytes();
|
||||||
|
let mut s = String::new();
|
||||||
|
while let Some(Ok(b)) = bytes.next().await {
|
||||||
|
match b {
|
||||||
|
b'\n' => {
|
||||||
|
if s.len() > 0 {
|
||||||
|
let diff = serde_json::from_str::<VecDiff<T>>(&s).expect("error parsing json");
|
||||||
|
self.apply_diff(diff);
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
c => {
|
||||||
|
s.push(c as char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
115
nested/src/vec/vec2seq.rs
Normal file
115
nested/src/vec/vec2seq.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
use {
|
||||||
|
std::{
|
||||||
|
sync::Arc,
|
||||||
|
},
|
||||||
|
std::sync::RwLock,
|
||||||
|
crate::{
|
||||||
|
core::{View, Observer, ObserverExt, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort},
|
||||||
|
sequence::SequenceView,
|
||||||
|
vec::VecDiff
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
/// Adapter View implementing `Sequence` for `Vec`
|
||||||
|
pub struct VecSequence<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
cur_len: usize,
|
||||||
|
data: Option<Arc<RwLock<Vec<T>>>>,
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> VecSequence<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
pub fn new(
|
||||||
|
port: InnerViewPort<dyn SequenceView<Item = T>>
|
||||||
|
) -> Arc<RwLock<Self>> {
|
||||||
|
let seq = Arc::new(RwLock::new(
|
||||||
|
VecSequence {
|
||||||
|
cur_len: 0,
|
||||||
|
data: None,
|
||||||
|
cast: port.get_broadcast()
|
||||||
|
}
|
||||||
|
));
|
||||||
|
port.set_view(Some(seq.clone()));
|
||||||
|
seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Observer<RwLock<Vec<T>>> for VecSequence<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
|
||||||
|
let old_len = self.cur_len;
|
||||||
|
self.data = view;
|
||||||
|
self.cur_len =
|
||||||
|
if let Some(data) = self.data.as_ref() {
|
||||||
|
data.read().unwrap().len()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cast.notify_each(0 .. std::cmp::max(old_len, self.cur_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify(&mut self, diff: &VecDiff<T>) {
|
||||||
|
match diff {
|
||||||
|
VecDiff::Clear => {
|
||||||
|
self.cast.notify_each(0 .. self.cur_len);
|
||||||
|
self.cur_len = 0
|
||||||
|
},
|
||||||
|
VecDiff::Push(_) => {
|
||||||
|
self.cast.notify(&self.cur_len);
|
||||||
|
self.cur_len += 1;
|
||||||
|
},
|
||||||
|
VecDiff::Remove(idx) => {
|
||||||
|
self.cast.notify_each(*idx .. self.cur_len);
|
||||||
|
self.cur_len -= 1;
|
||||||
|
},
|
||||||
|
VecDiff::Insert{ idx, val: _ } => {
|
||||||
|
self.cur_len += 1;
|
||||||
|
self.cast.notify_each(*idx .. self.cur_len);
|
||||||
|
},
|
||||||
|
VecDiff::Update{ idx, val: _ } => {
|
||||||
|
self.cast.notify(&idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> View for VecSequence<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
type Msg = usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SequenceView for VecSequence<T>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn get(&self, idx: &usize) -> Option<T> {
|
||||||
|
self.data.as_ref()?
|
||||||
|
.read().unwrap()
|
||||||
|
.get(*idx).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> Option<usize> {
|
||||||
|
Some(self.cur_len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
impl<T> OuterViewPort<RwLock<Vec<T>>>
|
||||||
|
where T: Clone + Send + Sync + 'static {
|
||||||
|
pub fn to_sequence(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
||||||
|
let port = ViewPort::new();
|
||||||
|
port.add_update_hook(Arc::new(self.0.clone()));
|
||||||
|
|
||||||
|
let vec_seq = VecSequence::new(port.inner());
|
||||||
|
self.add_observer(vec_seq.clone());
|
||||||
|
port.into_outer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue