Various changes

This commit is contained in:
Pauan 2018-02-25 22:01:04 -10:00
parent 8d1395d293
commit 129a0ca09e
6 changed files with 1017 additions and 918 deletions

View File

@ -64,7 +64,7 @@ fn main() {
dominator::append_dom(&document().query_selector("body").unwrap().unwrap(),
html!("div", {
style("border", "10px solid blue");
children([
children(&mut [
text("Testing testing!!!"),
text(text_receiver.dynamic()),
@ -100,13 +100,13 @@ fn main() {
style("width", "50px");
style("height", "50px");
style("background-color", "red");
children([
children(&mut [
html!("div", {
style("width", "10px");
style("height", "10px");
style("background-color", "orange");
})
].as_mut());
]);
}),
html!("div", {
@ -114,13 +114,13 @@ fn main() {
style("height", "50px");
style("background-color", "red");
class(&foobar, true);
children([
children(&mut [
html!("div", {
style("width", "10px");
style("height", "10px");
style("background-color", "orange");
})
].as_mut());
]);
}),
Dom::with_state(Rc::new(vec![1, 2, 3]), |a| {
@ -139,7 +139,7 @@ fn main() {
html!("input", {
focused(true);
}),
].as_mut());
]);
})
);
}

View File

@ -3,911 +3,5 @@
extern crate futures;
extern crate discard;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::{Async, Poll, task};
use futures::future::{Future, IntoFuture};
use futures::stream::{Stream, ForEach};
use discard::{Discard, DiscardOnDrop};
// TODO add in Done to allow the Signal to end ?
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum State<A> {
Changed(A),
NotChanged,
}
impl<A> State<A> {
#[inline]
pub fn map<B, F>(self, f: F) -> State<B> where F: FnOnce(A) -> B {
match self {
State::Changed(value) => State::Changed(f(value)),
State::NotChanged => State::NotChanged,
}
}
}
pub trait Signal {
type Item;
fn poll(&mut self) -> State<Self::Item>;
#[inline]
fn to_stream(self) -> SignalStream<Self>
where Self: Sized {
SignalStream {
signal: self,
}
}
#[inline]
fn map<A, B>(self, callback: A) -> Map<Self, A>
where A: FnMut(Self::Item) -> B,
Self: Sized {
Map {
signal: self,
callback,
}
}
#[inline]
fn map2<A, B, C>(self, other: A, callback: B) -> Map2<Self, A, B>
where A: Signal,
B: FnMut(&mut Self::Item, &mut A::Item) -> C,
Self: Sized {
Map2 {
signal1: self,
signal2: other,
callback,
left: None,
right: None,
}
}
#[inline]
fn map_dedupe<A, B>(self, callback: A) -> MapDedupe<Self, A>
where A: FnMut(&mut Self::Item) -> B,
Self: Sized {
MapDedupe {
old_value: None,
signal: self,
callback,
}
}
#[inline]
fn filter_map<A, B>(self, callback: A) -> FilterMap<Self, A>
where A: FnMut(Self::Item) -> Option<B>,
Self: Sized {
FilterMap {
signal: self,
callback,
first: true,
}
}
#[inline]
fn flatten(self) -> Flatten<Self>
where Self::Item: Signal,
Self: Sized {
Flatten {
signal: self,
inner: None,
}
}
#[inline]
fn switch<A, B>(self, callback: A) -> Flatten<Map<Self, A>>
where A: FnMut(Self::Item) -> B,
B: Signal,
Self: Sized {
self.map(callback).flatten()
}
#[inline]
// TODO file Rust bug about bad error message when `callback` isn't marked as `mut`
fn for_each<F, U>(self, callback: F) -> ForEach<SignalStream<Self>, F, U>
where F: FnMut(Self::Item) -> U,
// TODO allow for errors ?
U: IntoFuture<Item = (), Error = ()>,
Self:Sized {
self.to_stream().for_each(callback)
}
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
pub struct Always<A> {
value: Option<A>,
}
impl<A> Signal for Always<A> {
type Item = A;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
match self.value.take() {
Some(value) => State::Changed(value),
None => State::NotChanged,
}
}
}
#[inline]
pub fn always<A>(value: A) -> Always<A> {
Always {
value: Some(value),
}
}
struct CancelableFutureState {
is_cancelled: bool,
task: Option<task::Task>,
}
pub struct CancelableFutureHandle {
state: Weak<RefCell<CancelableFutureState>>,
}
impl Discard for CancelableFutureHandle {
fn discard(self) {
if let Some(state) = self.state.upgrade() {
let mut borrow = state.borrow_mut();
borrow.is_cancelled = true;
if let Some(task) = borrow.task.take() {
drop(borrow);
task.notify();
}
}
}
}
pub struct CancelableFuture<A, B> {
state: Rc<RefCell<CancelableFutureState>>,
future: Option<A>,
when_cancelled: Option<B>,
}
impl<A, B> Future for CancelableFuture<A, B>
where A: Future,
B: FnOnce(A) -> A::Item {
type Item = A::Item;
type Error = A::Error;
// TODO should this inline ?
#[inline]
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let borrow = self.state.borrow();
if borrow.is_cancelled {
let future = self.future.take().unwrap();
let callback = self.when_cancelled.take().unwrap();
// TODO figure out how to call the callback immediately when discard is called, e.g. using two Rc<RefCell<>>
Ok(Async::Ready(callback(future)))
} else {
drop(borrow);
match self.future.as_mut().unwrap().poll() {
Ok(Async::NotReady) => {
self.state.borrow_mut().task = Some(task::current());
Ok(Async::NotReady)
},
a => a,
}
}
}
}
// TODO figure out a more efficient way to implement this
// TODO this should be implemented in the futures crate
#[inline]
pub fn cancelable_future<A, B>(future: A, when_cancelled: B) -> (DiscardOnDrop<CancelableFutureHandle>, CancelableFuture<A, B>)
where A: Future,
B: FnOnce(A) -> A::Item {
let state = Rc::new(RefCell::new(CancelableFutureState {
is_cancelled: false,
task: None,
}));
let cancel_handle = DiscardOnDrop::new(CancelableFutureHandle {
state: Rc::downgrade(&state),
});
let cancel_future = CancelableFuture {
state,
future: Some(future),
when_cancelled: Some(when_cancelled),
};
(cancel_handle, cancel_future)
}
pub struct SignalStream<A> {
signal: A,
}
impl<A: Signal> Stream for SignalStream<A> {
type Item = A::Item;
// TODO use Void instead ?
type Error = ();
#[inline]
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(match self.signal.poll() {
State::Changed(value) => Async::Ready(Some(value)),
State::NotChanged => Async::NotReady,
})
}
}
pub struct Map<A, B> {
signal: A,
callback: B,
}
impl<A, B, C> Signal for Map<A, B>
where A: Signal,
B: FnMut(A::Item) -> C {
type Item = C;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
self.signal.poll().map(|value| (self.callback)(value))
}
}
pub struct Map2<A: Signal, B: Signal, C> {
signal1: A,
signal2: B,
callback: C,
left: Option<A::Item>,
right: Option<B::Item>,
}
impl<A, B, C, D> Signal for Map2<A, B, C>
where A: Signal,
B: Signal,
C: FnMut(&mut A::Item, &mut B::Item) -> D {
type Item = D;
// TODO inline this ?
fn poll(&mut self) -> State<Self::Item> {
match self.signal1.poll() {
State::Changed(mut left) => {
let output = match self.signal2.poll() {
State::Changed(mut right) => {
let output = State::Changed((self.callback)(&mut left, &mut right));
self.right = Some(right);
output
},
State::NotChanged => match self.right {
Some(ref mut right) => State::Changed((self.callback)(&mut left, right)),
None => State::NotChanged,
},
};
self.left = Some(left);
output
},
State::NotChanged => match self.left {
Some(ref mut left) => match self.signal2.poll() {
State::Changed(mut right) => {
let output = State::Changed((self.callback)(left, &mut right));
self.right = Some(right);
output
},
State::NotChanged => State::NotChanged,
},
None => State::NotChanged,
},
}
}
}
pub struct MapDedupe<A: Signal, B> {
old_value: Option<A::Item>,
signal: A,
callback: B,
}
impl<A, B, C> Signal for MapDedupe<A, B>
where A: Signal,
A::Item: PartialEq,
// TODO should this use Fn instead ?
B: FnMut(&A::Item) -> C {
type Item = C;
// TODO should this use #[inline] ?
fn poll(&mut self) -> State<Self::Item> {
loop {
match self.signal.poll() {
State::Changed(mut value) => {
let has_changed = match self.old_value {
Some(ref old_value) => *old_value != value,
None => true,
};
if has_changed {
let output = (self.callback)(&mut value);
self.old_value = Some(value);
return State::Changed(output);
}
},
State::NotChanged => return State::NotChanged,
}
}
}
}
pub struct FilterMap<A, B> {
signal: A,
callback: B,
first: bool,
}
impl<A, B, C> Signal for FilterMap<A, B>
where A: Signal,
B: FnMut(A::Item) -> Option<C> {
type Item = Option<C>;
// TODO should this use #[inline] ?
#[inline]
fn poll(&mut self) -> State<Self::Item> {
loop {
match self.signal.poll() {
State::Changed(value) => match (self.callback)(value) {
Some(value) => {
self.first = false;
return State::Changed(Some(value));
},
None => {
if self.first {
self.first = false;
return State::Changed(None);
}
},
},
State::NotChanged => return State::NotChanged,
}
}
}
}
pub struct Flatten<A: Signal> {
signal: A,
inner: Option<A::Item>,
}
impl<A> Signal for Flatten<A>
where A: Signal,
A::Item: Signal {
type Item = <<A as Signal>::Item as Signal>::Item;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
match self.signal.poll() {
State::Changed(mut inner) => {
let poll = inner.poll();
self.inner = Some(inner);
poll
},
State::NotChanged => match self.inner {
Some(ref mut inner) => inner.poll(),
None => State::NotChanged,
},
}
}
}
// TODO verify that this is correct
pub mod unsync {
use super::{Signal, State};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::task;
struct Inner<A> {
value: Option<A>,
task: Option<task::Task>,
}
pub struct Sender<A> {
inner: Weak<RefCell<Inner<A>>>,
}
impl<A> Sender<A> {
pub fn set(&self, value: A) -> Result<(), A> {
if let Some(inner) = self.inner.upgrade() {
let mut inner = inner.borrow_mut();
inner.value = Some(value);
if let Some(task) = inner.task.take() {
drop(inner);
task.notify();
}
Ok(())
} else {
Err(value)
}
}
}
#[derive(Clone)]
pub struct Receiver<A> {
inner: Rc<RefCell<Inner<A>>>,
}
impl<A> Signal for Receiver<A> {
type Item = A;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
let mut inner = self.inner.borrow_mut();
// TODO is this correct ?
match inner.value.take() {
Some(value) => State::Changed(value),
None => {
inner.task = Some(task::current());
State::NotChanged
},
}
}
}
pub fn mutable<A>(initial_value: A) -> (Sender<A>, Receiver<A>) {
let inner = Rc::new(RefCell::new(Inner {
value: Some(initial_value),
task: None,
}));
let sender = Sender {
inner: Rc::downgrade(&inner),
};
let receiver = Receiver {
inner,
};
(sender, receiver)
}
}
// TODO should this be hidden from the docs ?
#[doc(hidden)]
#[inline]
pub fn pair_clone<'a, 'b, A: Clone, B: Clone>(left: &'a mut A, right: &'b mut B) -> (A, B) {
(left.clone(), right.clone())
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_clone {
($name:ident) => {
::std::clone::Clone::clone($name)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_rc_new {
($value:expr) => {
$crate::Signal::map($value, ::std::rc::Rc::new)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map2 {
($f:expr, $old_pair:pat, $old_expr:expr, { $($lets:stmt);* }, let $name:ident: $t:ty = $value:expr;) => {
$crate::Signal::map2(
$old_expr,
__internal_map_rc_new!($value),
|&mut $old_pair, $name| {
$($lets;)*
let $name: $t = __internal_map_clone!($name);
$f
}
)
};
($f:expr, $old_pair:pat, $old_expr:expr, { $($lets:stmt);* }, let $name:ident: $t:ty = $value:expr; $($args:tt)+) => {
__internal_map2!(
$f,
($old_pair, ref mut $name),
$crate::Signal::map2(
$old_expr,
__internal_map_rc_new!($value),
$crate::pair_clone
),
{ $($lets;)* let $name: $t = __internal_map_clone!($name) },
$($args)+
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map {
($f:expr, let $name:ident: $t:ty = $value:expr;) => {
$crate::Signal::map($value, |$name| {
let $name: $t = ::std::rc::Rc::new($name);
$f
})
};
($f:expr, let $name1:ident: $t1:ty = $value1:expr;
let $name2:ident: $t2:ty = $value2:expr;) => {
$crate::Signal::map2(
__internal_map_rc_new!($value1),
__internal_map_rc_new!($value2),
|$name1, $name2| {
let $name1: $t1 = __internal_map_clone!($name1);
let $name2: $t2 = __internal_map_clone!($name2);
$f
}
)
};
($f:expr, let $name:ident: $t:ty = $value:expr; $($args:tt)+) => {
__internal_map2!(
$f,
ref mut $name,
__internal_map_rc_new!($value),
{ let $name: $t = __internal_map_clone!($name) },
$($args)+
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_lets {
($f:expr, { $($lets:tt)* },) => {
__internal_map!($f, $($lets)*)
};
($f:expr, { $($lets:tt)* }, let $name:ident: $t:ty = $value:expr, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: $t = $value; }, $($args)*)
};
($f:expr, { $($lets:tt)* }, let $name:ident = $value:expr, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: ::std::rc::Rc<_> = $value; }, $($args)*)
};
($f:expr, { $($lets:tt)* }, $name:ident, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: ::std::rc::Rc<_> = $name; }, $($args)*)
};
}
// TODO this is pretty inefficient, it iterates over the token tree one token at a time
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_split {
(($($before:tt)*), => $f:expr) => {
__internal_map_lets!($f, {}, $($before)*,)
};
(($($before:tt)*), $t:tt $($after:tt)*) => {
__internal_map_split!(($($before)* $t), $($after)*)
};
}
#[macro_export]
macro_rules! map_rc {
($($input:tt)*) => { __internal_map_split!((), $($input)*) };
}
#[cfg(test)]
mod tests {
#[test]
fn map_macro_ident_1() {
let a = super::always(1);
let mut s = map_rc!(a => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_2() {
let a = super::always(1);
let b = super::always(2);
let mut s = map_rc!(a, b => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_3() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let mut s = map_rc!(a, b, c => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_4() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let d = super::always(4);
let mut s = map_rc!(a, b, c, d => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_5() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let d = super::always(4);
let e = super::always(5);
let mut s = map_rc!(a, b, c, d, e => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_1() {
let a2 = super::always(1);
let mut s = map_rc!(let a = a2 => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_2() {
let a2 = super::always(1);
let b2 = super::always(2);
let mut s = map_rc!(let a = a2, let b = b2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_3() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_4() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2, let d = d2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_5() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let e2 = super::always(5);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2, let d = d2, let e = e2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_1() {
let a2 = super::always(1);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2 => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_2() {
let a2 = super::always(1);
let b2 = super::always(2);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_3() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_4() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2,
let d: ::std::rc::Rc<u32> = d2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_5() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let e2 = super::always(5);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2,
let d: ::std::rc::Rc<u32> = d2,
let e: ::std::rc::Rc<u32> = e2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
}
pub mod signal;
pub mod signal_list;

908
signals/src/signal.rs Normal file
View File

@ -0,0 +1,908 @@
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::{Async, Poll, task};
use futures::future::{Future, IntoFuture};
use futures::stream::{Stream, ForEach};
use discard::{Discard, DiscardOnDrop};
// TODO add in Done to allow the Signal to end ?
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum State<A> {
Changed(A),
NotChanged,
}
impl<A> State<A> {
#[inline]
pub fn map<B, F>(self, f: F) -> State<B> where F: FnOnce(A) -> B {
match self {
State::Changed(value) => State::Changed(f(value)),
State::NotChanged => State::NotChanged,
}
}
}
pub trait Signal {
type Item;
fn poll(&mut self) -> State<Self::Item>;
#[inline]
fn to_stream(self) -> SignalStream<Self>
where Self: Sized {
SignalStream {
signal: self,
}
}
#[inline]
fn map<A, B>(self, callback: A) -> Map<Self, A>
where A: FnMut(Self::Item) -> B,
Self: Sized {
Map {
signal: self,
callback,
}
}
#[inline]
fn map2<A, B, C>(self, other: A, callback: B) -> Map2<Self, A, B>
where A: Signal,
B: FnMut(&mut Self::Item, &mut A::Item) -> C,
Self: Sized {
Map2 {
signal1: self,
signal2: other,
callback,
left: None,
right: None,
}
}
#[inline]
fn map_dedupe<A, B>(self, callback: A) -> MapDedupe<Self, A>
where A: FnMut(&mut Self::Item) -> B,
Self: Sized {
MapDedupe {
old_value: None,
signal: self,
callback,
}
}
#[inline]
fn filter_map<A, B>(self, callback: A) -> FilterMap<Self, A>
where A: FnMut(Self::Item) -> Option<B>,
Self: Sized {
FilterMap {
signal: self,
callback,
first: true,
}
}
#[inline]
fn flatten(self) -> Flatten<Self>
where Self::Item: Signal,
Self: Sized {
Flatten {
signal: self,
inner: None,
}
}
#[inline]
fn switch<A, B>(self, callback: A) -> Flatten<Map<Self, A>>
where A: FnMut(Self::Item) -> B,
B: Signal,
Self: Sized {
self.map(callback).flatten()
}
#[inline]
// TODO file Rust bug about bad error message when `callback` isn't marked as `mut`
fn for_each<F, U>(self, callback: F) -> ForEach<SignalStream<Self>, F, U>
where F: FnMut(Self::Item) -> U,
// TODO allow for errors ?
U: IntoFuture<Item = (), Error = ()>,
Self:Sized {
self.to_stream().for_each(callback)
}
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
pub struct Always<A> {
value: Option<A>,
}
impl<A> Signal for Always<A> {
type Item = A;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
match self.value.take() {
Some(value) => State::Changed(value),
None => State::NotChanged,
}
}
}
#[inline]
pub fn always<A>(value: A) -> Always<A> {
Always {
value: Some(value),
}
}
struct CancelableFutureState {
is_cancelled: bool,
task: Option<task::Task>,
}
pub struct CancelableFutureHandle {
state: Weak<RefCell<CancelableFutureState>>,
}
impl Discard for CancelableFutureHandle {
fn discard(self) {
if let Some(state) = self.state.upgrade() {
let mut borrow = state.borrow_mut();
borrow.is_cancelled = true;
if let Some(task) = borrow.task.take() {
drop(borrow);
task.notify();
}
}
}
}
pub struct CancelableFuture<A, B> {
state: Rc<RefCell<CancelableFutureState>>,
future: Option<A>,
when_cancelled: Option<B>,
}
impl<A, B> Future for CancelableFuture<A, B>
where A: Future,
B: FnOnce(A) -> A::Item {
type Item = A::Item;
type Error = A::Error;
// TODO should this inline ?
#[inline]
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let borrow = self.state.borrow();
if borrow.is_cancelled {
let future = self.future.take().unwrap();
let callback = self.when_cancelled.take().unwrap();
// TODO figure out how to call the callback immediately when discard is called, e.g. using two Rc<RefCell<>>
Ok(Async::Ready(callback(future)))
} else {
drop(borrow);
match self.future.as_mut().unwrap().poll() {
Ok(Async::NotReady) => {
self.state.borrow_mut().task = Some(task::current());
Ok(Async::NotReady)
},
a => a,
}
}
}
}
// TODO figure out a more efficient way to implement this
// TODO this should be implemented in the futures crate
#[inline]
pub fn cancelable_future<A, B>(future: A, when_cancelled: B) -> (DiscardOnDrop<CancelableFutureHandle>, CancelableFuture<A, B>)
where A: Future,
B: FnOnce(A) -> A::Item {
let state = Rc::new(RefCell::new(CancelableFutureState {
is_cancelled: false,
task: None,
}));
let cancel_handle = DiscardOnDrop::new(CancelableFutureHandle {
state: Rc::downgrade(&state),
});
let cancel_future = CancelableFuture {
state,
future: Some(future),
when_cancelled: Some(when_cancelled),
};
(cancel_handle, cancel_future)
}
pub struct SignalStream<A> {
signal: A,
}
impl<A: Signal> Stream for SignalStream<A> {
type Item = A::Item;
// TODO use Void instead ?
type Error = ();
#[inline]
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(match self.signal.poll() {
State::Changed(value) => Async::Ready(Some(value)),
State::NotChanged => Async::NotReady,
})
}
}
pub struct Map<A, B> {
signal: A,
callback: B,
}
impl<A, B, C> Signal for Map<A, B>
where A: Signal,
B: FnMut(A::Item) -> C {
type Item = C;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
self.signal.poll().map(|value| (self.callback)(value))
}
}
pub struct Map2<A: Signal, B: Signal, C> {
signal1: A,
signal2: B,
callback: C,
left: Option<A::Item>,
right: Option<B::Item>,
}
impl<A, B, C, D> Signal for Map2<A, B, C>
where A: Signal,
B: Signal,
C: FnMut(&mut A::Item, &mut B::Item) -> D {
type Item = D;
// TODO inline this ?
fn poll(&mut self) -> State<Self::Item> {
match self.signal1.poll() {
State::Changed(mut left) => {
let output = match self.signal2.poll() {
State::Changed(mut right) => {
let output = State::Changed((self.callback)(&mut left, &mut right));
self.right = Some(right);
output
},
State::NotChanged => match self.right {
Some(ref mut right) => State::Changed((self.callback)(&mut left, right)),
None => State::NotChanged,
},
};
self.left = Some(left);
output
},
State::NotChanged => match self.left {
Some(ref mut left) => match self.signal2.poll() {
State::Changed(mut right) => {
let output = State::Changed((self.callback)(left, &mut right));
self.right = Some(right);
output
},
State::NotChanged => State::NotChanged,
},
None => State::NotChanged,
},
}
}
}
pub struct MapDedupe<A: Signal, B> {
old_value: Option<A::Item>,
signal: A,
callback: B,
}
impl<A, B, C> Signal for MapDedupe<A, B>
where A: Signal,
A::Item: PartialEq,
// TODO should this use Fn instead ?
B: FnMut(&A::Item) -> C {
type Item = C;
// TODO should this use #[inline] ?
fn poll(&mut self) -> State<Self::Item> {
loop {
match self.signal.poll() {
State::Changed(mut value) => {
let has_changed = match self.old_value {
Some(ref old_value) => *old_value != value,
None => true,
};
if has_changed {
let output = (self.callback)(&mut value);
self.old_value = Some(value);
return State::Changed(output);
}
},
State::NotChanged => return State::NotChanged,
}
}
}
}
pub struct FilterMap<A, B> {
signal: A,
callback: B,
first: bool,
}
impl<A, B, C> Signal for FilterMap<A, B>
where A: Signal,
B: FnMut(A::Item) -> Option<C> {
type Item = Option<C>;
// TODO should this use #[inline] ?
#[inline]
fn poll(&mut self) -> State<Self::Item> {
loop {
match self.signal.poll() {
State::Changed(value) => match (self.callback)(value) {
Some(value) => {
self.first = false;
return State::Changed(Some(value));
},
None => {
if self.first {
self.first = false;
return State::Changed(None);
}
},
},
State::NotChanged => return State::NotChanged,
}
}
}
}
pub struct Flatten<A: Signal> {
signal: A,
inner: Option<A::Item>,
}
impl<A> Signal for Flatten<A>
where A: Signal,
A::Item: Signal {
type Item = <<A as Signal>::Item as Signal>::Item;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
match self.signal.poll() {
State::Changed(mut inner) => {
let poll = inner.poll();
self.inner = Some(inner);
poll
},
State::NotChanged => match self.inner {
Some(ref mut inner) => inner.poll(),
None => State::NotChanged,
},
}
}
}
// TODO verify that this is correct
pub mod unsync {
use super::{Signal, State};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use futures::task;
struct Inner<A> {
value: Option<A>,
task: Option<task::Task>,
}
pub struct Sender<A> {
inner: Weak<RefCell<Inner<A>>>,
}
impl<A> Sender<A> {
pub fn set(&self, value: A) -> Result<(), A> {
if let Some(inner) = self.inner.upgrade() {
let mut inner = inner.borrow_mut();
inner.value = Some(value);
if let Some(task) = inner.task.take() {
drop(inner);
task.notify();
}
Ok(())
} else {
Err(value)
}
}
}
#[derive(Clone)]
pub struct Receiver<A> {
inner: Rc<RefCell<Inner<A>>>,
}
impl<A> Signal for Receiver<A> {
type Item = A;
#[inline]
fn poll(&mut self) -> State<Self::Item> {
let mut inner = self.inner.borrow_mut();
// TODO is this correct ?
match inner.value.take() {
Some(value) => State::Changed(value),
None => {
inner.task = Some(task::current());
State::NotChanged
},
}
}
}
pub fn mutable<A>(initial_value: A) -> (Sender<A>, Receiver<A>) {
let inner = Rc::new(RefCell::new(Inner {
value: Some(initial_value),
task: None,
}));
let sender = Sender {
inner: Rc::downgrade(&inner),
};
let receiver = Receiver {
inner,
};
(sender, receiver)
}
}
// TODO should this be hidden from the docs ?
#[doc(hidden)]
#[inline]
pub fn pair_clone<'a, 'b, A: Clone, B: Clone>(left: &'a mut A, right: &'b mut B) -> (A, B) {
(left.clone(), right.clone())
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_clone {
($name:ident) => {
::std::clone::Clone::clone($name)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_rc_new {
($value:expr) => {
$crate::signal::Signal::map($value, ::std::rc::Rc::new)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map2 {
($f:expr, $old_pair:pat, $old_expr:expr, { $($lets:stmt);* }, let $name:ident: $t:ty = $value:expr;) => {
$crate::signal::Signal::map2(
$old_expr,
__internal_map_rc_new!($value),
|&mut $old_pair, $name| {
$($lets;)*
let $name: $t = __internal_map_clone!($name);
$f
}
)
};
($f:expr, $old_pair:pat, $old_expr:expr, { $($lets:stmt);* }, let $name:ident: $t:ty = $value:expr; $($args:tt)+) => {
__internal_map2!(
$f,
($old_pair, ref mut $name),
$crate::signal::Signal::map2(
$old_expr,
__internal_map_rc_new!($value),
$crate::signal::pair_clone
),
{ $($lets;)* let $name: $t = __internal_map_clone!($name) },
$($args)+
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map {
($f:expr, let $name:ident: $t:ty = $value:expr;) => {
$crate::signal::Signal::map($value, |$name| {
let $name: $t = ::std::rc::Rc::new($name);
$f
})
};
($f:expr, let $name1:ident: $t1:ty = $value1:expr;
let $name2:ident: $t2:ty = $value2:expr;) => {
$crate::signal::Signal::map2(
__internal_map_rc_new!($value1),
__internal_map_rc_new!($value2),
|$name1, $name2| {
let $name1: $t1 = __internal_map_clone!($name1);
let $name2: $t2 = __internal_map_clone!($name2);
$f
}
)
};
($f:expr, let $name:ident: $t:ty = $value:expr; $($args:tt)+) => {
__internal_map2!(
$f,
ref mut $name,
__internal_map_rc_new!($value),
{ let $name: $t = __internal_map_clone!($name) },
$($args)+
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_lets {
($f:expr, { $($lets:tt)* },) => {
__internal_map!($f, $($lets)*)
};
($f:expr, { $($lets:tt)* }, let $name:ident: $t:ty = $value:expr, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: $t = $value; }, $($args)*)
};
($f:expr, { $($lets:tt)* }, let $name:ident = $value:expr, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: ::std::rc::Rc<_> = $value; }, $($args)*)
};
($f:expr, { $($lets:tt)* }, $name:ident, $($args:tt)*) => {
__internal_map_lets!($f, { $($lets)* let $name: ::std::rc::Rc<_> = $name; }, $($args)*)
};
}
// TODO this is pretty inefficient, it iterates over the token tree one token at a time
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_map_split {
(($($before:tt)*), => $f:expr) => {
__internal_map_lets!($f, {}, $($before)*,)
};
(($($before:tt)*), $t:tt $($after:tt)*) => {
__internal_map_split!(($($before)* $t), $($after)*)
};
}
#[macro_export]
macro_rules! map_rc {
($($input:tt)*) => { __internal_map_split!((), $($input)*) };
}
#[cfg(test)]
mod tests {
#[test]
fn map_macro_ident_1() {
let a = super::always(1);
let mut s = map_rc!(a => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_2() {
let a = super::always(1);
let b = super::always(2);
let mut s = map_rc!(a, b => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_3() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let mut s = map_rc!(a, b, c => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_4() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let d = super::always(4);
let mut s = map_rc!(a, b, c, d => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_ident_5() {
let a = super::always(1);
let b = super::always(2);
let c = super::always(3);
let d = super::always(4);
let e = super::always(5);
let mut s = map_rc!(a, b, c, d, e => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_1() {
let a2 = super::always(1);
let mut s = map_rc!(let a = a2 => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_2() {
let a2 = super::always(1);
let b2 = super::always(2);
let mut s = map_rc!(let a = a2, let b = b2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_3() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_4() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2, let d = d2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_5() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let e2 = super::always(5);
let mut s = map_rc!(let a = a2, let b = b2, let c = c2, let d = d2, let e = e2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
});
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_1() {
let a2 = super::always(1);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2 => {
let a: ::std::rc::Rc<u32> = a;
*a + 1
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(2));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_2() {
let a2 = super::always(1);
let b2 = super::always(2);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
*a + *b
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(3));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_3() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
*a + *b + *c
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(6));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_4() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2,
let d: ::std::rc::Rc<u32> = d2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
*a + *b + *c + *d
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(10));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
#[test]
fn map_macro_let_type_5() {
let a2 = super::always(1);
let b2 = super::always(2);
let c2 = super::always(3);
let d2 = super::always(4);
let e2 = super::always(5);
let mut s = map_rc! {
let a: ::std::rc::Rc<u32> = a2,
let b: ::std::rc::Rc<u32> = b2,
let c: ::std::rc::Rc<u32> = c2,
let d: ::std::rc::Rc<u32> = d2,
let e: ::std::rc::Rc<u32> = e2 => {
let a: ::std::rc::Rc<u32> = a;
let b: ::std::rc::Rc<u32> = b;
let c: ::std::rc::Rc<u32> = c;
let d: ::std::rc::Rc<u32> = d;
let e: ::std::rc::Rc<u32> = e;
*a + *b + *c + *d + *e
}
};
assert_eq!(super::Signal::poll(&mut s), super::State::Changed(15));
assert_eq!(super::Signal::poll(&mut s), super::State::NotChanged);
}
}

View File

@ -0,0 +1,97 @@
use futures::Async;
//use std::iter::Iterator;
#[derive(Debug, Clone)]
pub enum ListChange<A> {
Replace {
values: Vec<A>,
},
InsertAt {
index: usize,
value: A,
},
RemoveAt {
index: usize,
},
Swap {
old_index: usize,
new_index: usize,
},
Push {
value: A,
},
Pop {},
Clear {},
}
impl<A> ListChange<A> {
// TODO inline this ?
fn map<B, F>(self, mut callback: F) -> ListChange<B> where F: FnMut(A) -> B {
match self {
// TODO figure out a more efficient way of implementing this
ListChange::Replace { values } => ListChange::Replace { values: values.into_iter().map(callback).collect() },
ListChange::InsertAt { index, value } => ListChange::InsertAt { index, value: callback(value) },
ListChange::RemoveAt { index } => ListChange::RemoveAt { index },
ListChange::Swap { old_index, new_index } => ListChange::Swap { old_index, new_index },
ListChange::Push { value } => ListChange::Push { value: callback(value) },
ListChange::Pop {} => ListChange::Pop {},
ListChange::Clear {} => ListChange::Clear {},
}
}
}
pub trait SignalList {
type Item;
fn poll(&mut self) -> Async<Option<ListChange<Self::Item>>>;
#[inline]
fn map<A, F>(self, callback: F) -> Map<Self, F>
where F: FnMut(Self::Item) -> A,
Self: Sized {
Map {
signal: self,
callback,
}
}
/*#[inline]
fn filter_map<A, F>(self, callback: F) -> Map<Self, F>
where F: FnMut(Self::Item) -> A,
Self: Sized {
Map {
signal: self,
callback,
}
}*/
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
pub struct Map<A, B> {
signal: A,
callback: B,
}
impl<A, B, F> SignalList for Map<A, F>
where A: SignalList,
F: FnMut(A::Item) -> B {
type Item = B;
#[inline]
fn poll(&mut self) -> Async<Option<ListChange<Self::Item>>> {
self.signal.poll().map(|some| some.map(|change| change.map(|value| (self.callback)(value))))
}
}

View File

@ -194,7 +194,7 @@ pub fn insert_children_signal<A, B, C>(element: &A, callbacks: &mut Callbacks, s
}
#[inline]
pub fn insert_children_slice<A: INode>(element: &A, callbacks: &mut Callbacks, value: &mut [Dom]) {
pub fn insert_children_iter<'a, A: INode, B: IntoIterator<Item = &'a mut Dom>>(element: &A, callbacks: &mut Callbacks, value: B) {
for dom in value.into_iter() {
callbacks.after_insert.append(&mut dom.callbacks.after_insert);
callbacks.after_remove.append(&mut dom.callbacks.after_remove);

View File

@ -92,10 +92,10 @@ impl Focused for bool {
}
// TODO figure out how to make this owned rather than &mut
impl<'a> Children for &'a mut [Dom] {
impl<'a, A: IntoIterator<Item = &'a mut Dom>> Children for A {
#[inline]
fn insert_children<A: INode>(self, element: &A, callbacks: &mut Callbacks) {
operations::insert_children_slice(element, callbacks, self)
fn insert_children<B: INode>(self, element: &B, callbacks: &mut Callbacks) {
operations::insert_children_iter(element, callbacks, self)
}
}