mod run_batch; use run_batch::RunBatch;
use crate::at::Cps;
#[cfg(feature="batch_rt")]
use alloc::vec::Vec;
#[cfg(feature="batch_rt")]
use alloc::boxed::Box;
#[must_use]
pub struct CpsBatch<CPS, L> {
cps: CPS,
list: L,
}
#[cfg(feature="batch_rt")]
pub type FnBoxRt<V, R> = Box<dyn FnOnce(&mut V, Option<R>) -> R>;
#[cfg(feature="batch_ct")]
impl<CPS> CpsBatch<CPS, ()> where
CPS: Cps
{
pub fn run(self) -> Option<()> { None }
pub fn add<F, R>(self, f: F) -> CpsBatch<CPS, ((), F)>
where F: FnOnce(&mut CPS::View, ()) -> R
{
CpsBatch { cps: self.cps, list: (self.list, f) }
}
}
#[cfg(feature="batch_ct")]
impl<CPS,Prev,F,R> CpsBatch<CPS, (Prev, F)> where
CPS: Cps,
(Prev,F): RunBatch<CPS::View, Output=R>,
{
pub fn run(self) -> Option<R> {
let list = self.list;
self.cps.access(|v| list.run(v))
}
pub fn add<G, S>(self, g: G) -> CpsBatch<CPS, ((Prev, F), G)>
where G: FnOnce(&mut CPS::View, R) -> S
{
CpsBatch { cps: self.cps, list: (self.list, g) }
}
pub fn pop(self, dst: Option<&mut Option<F>>) -> CpsBatch<CPS, Prev> {
let (prev, f) = self.list;
if let Some(place) = dst { *place = Some(f); }
CpsBatch { cps: self.cps, list: prev }
}
pub fn clear(self) -> CpsBatch<CPS, ()> {
CpsBatch { cps: self.cps, list: () }
}
}
#[cfg(feature="batch_ct")]#[test]
fn test_ct_batch_editing() {
use crate::Cps;
let mut foo = 1;
foo.batch_ct()
.add(|x, _| { *x += 1; })
.add(|x, _| { *x += 1; })
.pop(None)
.run();
assert!(foo == 2);
foo.batch_ct()
.add(|x, _| { *x += 1; })
.add(|x, _| { *x += 1; })
.clear()
.run();
assert!(foo == 2);
}
#[cfg(feature="batch_rt")]
impl<CPS: Cps, R> CpsBatch<CPS, Vec<FnBoxRt<CPS::View, R>>> {
pub fn run(self) -> Option<R> {
let list = self.list;
if list.len() == 0 { return None; }
self.cps.access(|v| list.run(v)).map(|x| x.unwrap())
}
pub fn add<F>(mut self, f: F) -> Self where
F: FnOnce(&mut CPS::View, Option<R>) -> R + 'static
{
self.list.push(Box::new(f));
self
}
pub fn pop(mut self, dst: Option<&mut Option<FnBoxRt<CPS::View, R>>>) -> Self
{
let maybe_f = self.list.pop();
if let Some(place) = dst { *place = maybe_f; }
self
}
pub fn clear(mut self) -> Self {
self.list.clear();
self
}
pub fn edit(&mut self) -> &mut Vec<FnBoxRt<CPS::View, R>> {
&mut self.list
}
}
#[cfg(feature="batch_rt")]#[test]
fn test_rt_batch_editing() {
use crate::Cps;
let mut foo = 1;
foo.batch_rt()
.add(|x, _| { *x += 1; })
.add(|x, _| { *x += 1; })
.pop(None)
.run();
assert!(foo == 2);
foo.batch_rt()
.add(|x, _| { *x += 1; })
.add(|x, _| { *x += 1; })
.clear()
.run();
assert!(foo == 2);
let mut maybe_f = None;
foo.batch_rt()
.add(|x, _| { *x += 1; })
.add(|x, _| { *x += 1; })
.pop(Some(&mut maybe_f))
.run();
assert!(foo == 3);
maybe_f.unwrap()(&mut foo, None);
assert!(foo == 4);
}
#[cfg(feature="batch_ct")]
pub fn new_batch_ct<CPS: Cps>(cps: CPS) -> CpsBatch<CPS, ()> {
CpsBatch { cps: cps, list: () }
}
#[cfg(feature="batch_rt")]
pub fn new_batch_rt<CPS, V, R>(cps: CPS) -> CpsBatch<CPS, Vec<FnBoxRt<V,R>>> where
CPS: Cps<View=V>,
V: ?Sized
{
CpsBatch { cps: cps, list: Vec::new() }
}
#[must_use]
pub trait Batch<R>: Sized {
fn run(self) -> Option<R>;
}
#[cfg(feature="batch_ct")]
impl<CPS: Cps> Batch<()> for CpsBatch<CPS, ()> {
fn run(self) -> Option<()> {
self.run()
}
}
#[cfg(feature="batch_ct")]
impl<CPS: Cps, Prev, F, R> Batch<R> for CpsBatch<CPS, (Prev, F)> where
CPS: Cps,
(Prev,F): RunBatch<CPS::View, Output=R>
{
fn run(self) -> Option<R> {
self.run()
}
}
#[cfg(feature="batch_rt")]
impl<CPS: Cps, R> Batch<R> for CpsBatch<CPS, Vec<FnBoxRt<CPS::View, R>>> {
fn run(self) -> Option<R> {
self.run()
}
}
#[cfg(feature="batch_ct")]#[must_use]
pub trait BatchCt<V: ?Sized, R>: Batch<R> {
type CPS: Cps<View=V>;
type List: RunBatch<V, Output=R>;
fn add<G, S>(self, g: G) -> CpsBatch<Self::CPS, (Self::List, G)> where
G: FnOnce(&mut V, R) -> S;
fn clear(self) -> CpsBatch<Self::CPS, ()>;
fn run(self) -> Option<R> {
<Self as Batch<R>>::run(self)
}
}
#[cfg(feature="batch_ct")]
impl<CPS: Cps> BatchCt<CPS::View, ()> for CpsBatch<CPS, ()> {
type CPS = CPS;
type List = ();
fn add<G, S>(self, g: G) -> CpsBatch<CPS, (Self::List, G)> where
G: FnOnce(&mut CPS::View, ()) -> S
{
self.add(g)
}
fn clear(self) -> CpsBatch<CPS, ()> {
self
}
}
#[cfg(feature="batch_ct")]
impl<CPS, Prev, F, R> BatchCt<CPS::View, R> for CpsBatch<CPS, (Prev, F)> where
CPS: Cps,
(Prev,F): RunBatch<CPS::View, Output=R>
{
type CPS = CPS;
type List = (Prev, F);
fn add<G, S>(self, g: G) -> CpsBatch<CPS, (Self::List, G)> where
G: FnOnce(&mut CPS::View, R) -> S
{
self.add(g)
}
fn clear(self) -> CpsBatch<CPS, ()> {
self.clear()
}
}
#[cfg(feature="batch_rt")]#[must_use]
pub trait BatchRt<View: ?Sized, R>: Batch<R> {
fn add<G>(self, g: G) -> Self
where G: FnOnce(&mut View, Option<R>) -> R + 'static;
fn clear(self) -> Self;
fn pop(self, dst: Option<&mut Option<FnBoxRt<View, R>>>) -> Self;
fn edit(&mut self) -> &mut Vec<FnBoxRt<View, R>>;
fn run(self) -> Option<R> {
<Self as Batch<R>>::run(self)
}
}
#[cfg(feature="batch_rt")]
impl<CPS: Cps, R> BatchRt<CPS::View, R> for
CpsBatch<CPS, Vec<FnBoxRt<CPS::View, R>>>
{
fn add<G>(self, g: G) -> Self
where G: FnOnce(&mut CPS::View, Option<R>) -> R + 'static
{
self.add(g)
}
fn clear(self) -> Self {
self.clear()
}
fn pop(self, dst: Option<&mut Option<FnBoxRt<CPS::View, R>>>) -> Self {
self.pop(dst)
}
fn edit(&mut self) -> &mut Vec<FnBoxRt<CPS::View, R>> {
self.edit()
}
}