use { std::{ cmp::{max}, any::Any, sync::{Arc, Weak}, }, async_std::{ stream::StreamExt }, std::sync::RwLock, crate::{ core::{View, Observer, ObserverExt, OuterViewPort, channel::{channel, ChannelData, ChannelSender, ChannelReceiver}}, singleton::{SingletonView}, sequence::{SequenceView}, index::{IndexView} } }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct ProjectionHelper { keepalive: Vec>, proj: Arc>>> } impl ProjectionHelper

{ pub fn new() -> Self { ProjectionHelper { keepalive: Vec::new(), proj: Arc::new(RwLock::new(Weak::new())) } } pub fn set_proj(&mut self, proj: &Arc>) { *self.proj.write().unwrap() = Arc::downgrade(proj); } // todo: make this functions generic over the View // this does currently not work because Observer is not implemented for ProjectionArg for *all* V. pub fn new_singleton_arg( &mut self, port: OuterViewPort>, notify: impl Fn(&mut P, &()) + Send + Sync + 'static ) -> Arc>>>> { let (view, obs) = self.new_arg(notify); port.add_observer(obs); view } pub fn new_sequence_arg( &mut self, port: OuterViewPort>, notify: impl Fn(&mut P, &usize) + Send + Sync + 'static ) -> Arc>>>> { let (view, obs) = self.new_arg(notify); port.add_observer(obs); view } pub fn new_index_arg( &mut self, port: OuterViewPort>, notify: impl Fn(&mut P, &Key) + Send + Sync + 'static ) -> Arc>>>> { let (view, obs) = self.new_arg(notify); port.add_observer(obs); view } pub fn new_arg< V: View + ?Sized + 'static >( &mut self, notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static ) -> ( Arc>>>, Arc>>> ) where V::Msg: Send + Sync { let (tx, mut rx) = channel::>(); let view = Arc::new(RwLock::new(None)); let arg = Arc::new(RwLock::new( ProjectionArg { src: view.clone(), sender: tx })); let proj = self.proj.clone(); async_std::task::spawn(async move { while let Some(msg) = rx.next().await { if let Some(proj) = proj.read().unwrap().upgrade() { loop { if let Ok(p) = proj.try_write().as_mut() { notify(&mut *p, &msg); break; } async_std::task::yield_now(); } } } }); self.keepalive.push(arg.clone()); (view, arg) } } /// Special Observer which can access the state of the projection on notify /// also handles the reset() and default behaviour of unitinitalized inputs pub struct ProjectionArg where V: View + ?Sized, D: ChannelData, D::IntoIter: Send + Sync { src: Arc>>>, sender: ChannelSender } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> impl Observer> for ProjectionArg, D> where D: ChannelData, D::IntoIter: Send + Sync { fn reset(&mut self, new_src: Option>>) { *self.src.write().unwrap() = new_src; self.notify(&()); } fn notify(&self, msg: &()) { self.sender.send(*msg); } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> impl Observer> for ProjectionArg, D> where D: ChannelData, D::IntoIter: Send + Sync { fn reset(&mut self, new_src: Option>>) { let old_len = self.src.len().unwrap_or(0); *self.src.write().unwrap() = new_src; let new_len = self.src.len().unwrap_or(0); self.notify_each(0 .. max(old_len, new_len)); } fn notify(&self, msg: &usize) { self.sender.send(*msg); } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> impl Observer> for ProjectionArg, D> where D: ChannelData, D::IntoIter: Send + Sync { fn reset(&mut self, new_src: Option>>) { let old_area = self.src.area(); *self.src.write().unwrap() = new_src; let new_area = self.src.area(); if let Some(area) = old_area { self.notify_each(area); } if let Some(area) = new_area { self.notify_each(area); } } fn notify(&self, msg: &Key) { self.sender.send(msg.clone()); } }