use std::{borrow::Borrow, cell::UnsafeCell};
use std::rc::Rc;
use std::fmt::{self, Debug};
use std::ops::{Not, Add, Sub, Mul, Div, BitAnd, BitOr, BitXor, Index, Neg, Rem, Shl, Shr};
use std::cmp::PartialEq;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use crate::{PropertyLastValue, traits::StreamExt};
use crate::StreamRc;
use crate::TryIter;
use crate::priv_traits::*;
use crate::sender_rc::SenderInner;
use crate::Parameter;
use crate::SenderRc;
#[cfg(feature = "async")]
use crate::ReceiverAsync;
#[must_use = "Dropping a Property unsubscribes it and all the chain until the origin sender"]
#[derive(Clone)]
pub struct Property<'a, T: Clone + 'a>{
parent: StreamRc<'a,T>,
on_value: StreamRc<'a,T>,
value: Rc<UnsafeCell<T>>,
}
impl<'a, T: Clone + 'a> Property<'a,T>{
pub fn from_parent<S: Into<StreamRc<'a,T>>>(parent: S, initial: T) -> Property<'a,T>{
let parent = parent.into();
let value = Rc::new(UnsafeCell::new(initial));
let value_cpy = value.clone();
let on_value = parent.clone()
.on_value(move |t| unsafe { *value_cpy.get() = t });
Property{
parent,
on_value: on_value.into(),
value,
}
}
pub fn new(initial: T) -> Property<'a,T>{
let value = Rc::new(UnsafeCell::new(initial));
let value_cpy = value.clone();
let parent = StreamRc::never();
let on_value = parent.clone()
.on_value(move |t| unsafe { *value_cpy.get() = t });
Property{
parent,
on_value: on_value.into(),
value,
}
}
pub fn swap_parent<S: Into<StreamRc<'a,T>>>(&mut self, parent: S){
let parent = parent.into();
let value_cpy = self.value.clone();
let on_value = parent.clone()
.on_value(move |t| unsafe { *value_cpy.get() = t });
self.parent.swap_parent(parent);
self.on_value.swap_parent(on_value);
}
pub fn from_sender_stream<S: Into<StreamRc<'a,T>>>(sender: SenderRc<'a,T>, stream: S, initial: T) -> Property<'a,T>{
let parent = StreamRc::new(sender.into_inner());
let value = Rc::new(UnsafeCell::new(initial));
let value_cpy = value.clone();
let stream = stream.into();
let on_value = stream.on_value(move |t| unsafe { *value_cpy.get() = t });
Property{
parent,
on_value: on_value.into(),
value,
}
}
#[inline]
pub fn get(&self) -> &T{
unsafe{ &*self.value.get() }
}
pub fn into_inner(self) -> Result<T, Property<'a,T>>{
let parent = self.parent;
let on_value = self.on_value;
let cell = Rc::try_unwrap(self.value)
.map_err(move |v| Property{
parent,
on_value,
value: v,
})?;
Ok(cell.into_inner())
}
pub fn set(&mut self, t: T){
self.parent.send(t)
}
pub fn map<'b, T2: Clone, F: FnMut(T) -> T2 + 'a>(self, mut f: F) -> Property<'b,T2>
where
T: 'b,
'a: 'b
{
let initial = f(self.get().clone());
let parent = self.parent.map(f);
Property::from_parent(parent, initial)
}
pub fn inspect<'b, F: Fn(&T) + 'b>(self, f: F) -> Property<'b, T>
where
T: 'b,
'a: 'b
{
let initial = self.get().clone();
let parent = self.parent.inspect(f);
Property::from_parent(parent, initial)
}
pub fn filter<'b, F: FnMut(&T) -> bool + 'b>(self, f: F) -> Property<'b, T>
where
T: 'b,
'a: 'b
{
let initial = self.get().clone();
let parent = self.parent.filter(f);
Property::from_parent(parent, initial)
}
pub fn filter_by<'b, 'c>(self, b: Property<'b, bool>) -> Property<'c, T>
where
T: 'b,
'a: 'b,
'b: 'c
{
let initial = self.get().clone();
let parent = self.parent.filter_by(b);
Property::from_parent(parent, initial)
}
pub fn merge<'b, 'c>(self, b: Property<'b, T>) -> Property<'c, T>
where
T: 'b,
'a: 'b,
'b: 'c
{
let initial = self.get().clone();
let parent = self.parent.merge(b.stream());
Property::from_parent(parent, initial)
}
pub fn merge_stream<'b, 'c, S: StreamExt<'a, T>>(self, b: S) -> Property<'c, T>
where
T: 'b,
'a: 'b,
'b: 'c
{
let initial = self.get().clone();
let parent = self.parent.merge(b);
Property::from_parent(parent, initial)
}
pub fn zip<T2: Clone + 'a>(self, other: Property<'a,T2>) -> Property<'a, (T,T2)>{
let initial = (self.get().clone(), other.get().clone());
let sender = Rc::new(UnsafeCell::new(SenderInner::new()));
let other1 = other.clone();
let sender1 = sender.clone();
let parent1 = self.parent.clone().on_value(move |t|{
unsafe{ (*sender1.get()).send((t, other1.get().clone())) }
});
let sender2 = sender.clone();
let parent2 = other.parent.map(move |t|{
unsafe{ (*sender2.get()).send((self.get().clone(), t)) }
});
let parents = vec![parent1.into_remove(), parent2.into_remove()];
let parent = StreamRc::from_remove(parents, sender);
Property::from_parent(parent, initial)
}
pub fn stream(self) -> StreamRc<'a, T>{
self.on_value
}
pub fn is<'b>(&self, other: &Property<'b,T>) -> bool{
self.value.get() == other.value.get()
}
pub fn try_iter<'b>(self) -> TryIter<'b,T> where 'a: 'b{
let initial = self.get().clone();
TryIter::new_initial(self.parent, initial)
}
pub fn to_parameter<'b>(self) -> Parameter<'b,T> where 'a: 'b{
let initial = self.get().clone();
Parameter::from_parent(self.try_iter(), initial)
}
#[cfg(feature = "async")]
pub fn receiver_async<'b>(self) -> ReceiverAsync<'b,T> where 'a: 'b{
let initial = self.get().clone();
ReceiverAsync::new_initial(self.parent, initial)
}
pub fn into_property_last_value(self) -> PropertyLastValue<'a, T> {
let initial = self.get().clone();
let parent = self.parent;
PropertyLastValue::from_parent(parent, initial)
}
}
impl<'a> Property<'a,bool>{
pub fn switch<T: 'a + Clone, S: Into<::Stream<'a,T>>>(self, then: S, else_: S) -> ::Stream<'a,T>{
let then = then.into().filter_by(self.clone());
let else_ = else_.into().filter_by(!self);
then.merge(else_)
}
}
impl<'a,T: Clone> Property<'a,Vec<T>>{
pub fn push(&mut self, t: T){
let mut current = self.as_ref().clone();
current.push(t);
self.set(current);
}
pub fn remove(&mut self, idx: usize) -> T{
let mut current = self.as_ref().clone();
let t = current.remove(idx);
self.set(current);
t
}
}
impl<'a> Not for Property<'a,bool>{
type Output = Property<'a,bool>;
fn not(self) -> Property<'a,bool>{
self.map(Not::not)
}
}
impl<'a,T: Clone + PartialEq + 'a> Property<'a,T>{
pub fn dedup<'b>(self) -> Property<'b, T> where 'a: 'b{
let initial = self.get().clone();
let parent = self.parent.dedup();
Property::from_parent(parent, initial)
}
pub fn changed<'b>(self) -> crate::Stream<'b, ()> where 'a: 'b {
let mut current = self.get().clone();
self.parent.filter_map(move |next| if next != current {
current = next;
Some(())
}else{
None
})
}
}
impl<'a, T1: Clone + 'a, T2: Clone + 'a> Property<'a,(T1, T2)>{
pub fn unzip<'b>(self) -> (Property<'b, T1>, Property<'b, T2>) where 'a: 'b{
let initial1 = self.get().0.clone();
let initial2 = self.get().1.clone();
let parent1 = self.parent.clone().map(|(t1,t2)| t1);
let parent2 = self.parent.map(|(t1,t2)| t2);
(Property::from_parent(parent1, initial1), Property::from_parent(parent2, initial2))
}
}
impl<'a,T1: Clone + 'a,T2: Clone + 'a,T3: Clone + 'a> Property<'a,((T1,T2),T3)>{
pub fn flatten<'b>(self) -> Property<'b,(T1,T2,T3)> where 'a: 'b{
let ((t1,t2),t3) = self.get().clone();
let initial = (t1,t2,t3);
let parent = self.parent.map(|((t1,t2),t3)| (t1,t2,t3));
Property::from_parent(parent, initial)
}
}
impl<'a,T: Clone> AsRef<T> for Property<'a,T>{
fn as_ref(&self) -> &T{
unsafe{ &*self.value.get() }
}
}
impl<'a, T: 'a + Clone + Debug> Debug for Property<'a,T>{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result{
fmt.debug_struct("Property<T>")
.field("value", unsafe{ &*self.value.get() })
.finish()
}
}
impl<'a,T: Clone + Serialize + 'a> Serialize for Property<'a,T>{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>{
self.as_ref().serialize(serializer)
}
}
impl<'a, 'de, T: Clone + Deserialize<'de> + 'a> Deserialize<'de> for Property<'a,T>{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Property<'a,T>, D::Error>{
T::deserialize(deserializer).map(|t| Property::new(t))
}
}
impl<'a,T: Clone + Default> Default for Property<'a,T> {
fn default() -> Property<'a,T> {
Property::new(T::default())
}
}
impl<'a, T: PartialEq + Clone> PartialEq for Property<'a, T> {
fn eq(&self, other: &Property<'a,T>) -> bool {
unsafe{ *self.value.get() == *other.value.get() }
}
}
impl<'a, T: Eq + Clone> Eq for Property<'a, T>{}
impl<'a, T: PartialEq + Clone> PartialEq<T> for Property<'a, T> {
fn eq(&self, other: &T) -> bool{
unsafe{ *self.value.get() == *other }
}
}
impl<'a, T: Add + Clone> Add for Property<'a,T>
where <T as Add>::Output: Clone
{
type Output = Property<'a, <T as Add>::Output>;
fn add(self, other: Property<'a, T>) -> Property<'a, <T as Add>::Output> {
self.zip(other).map(|(a, b)| a + b)
}
}
impl<'a, T: Add + Clone> Add<T> for Property<'a,T>
where <T as Add>::Output: Clone
{
type Output = Property<'a, <T as Add>::Output>;
fn add(self, other: T) -> Property<'a, <T as Add>::Output> {
self.map(move |a| a + other.clone())
}
}
impl<'a, T: Sub + Clone> Sub for Property<'a,T>
where <T as Sub>::Output: Clone
{
type Output = Property<'a, <T as Sub>::Output>;
fn sub(self, other: Property<'a, T>) -> Property<'a, <T as Sub>::Output> {
self.zip(other).map(|(a, b)| a - b)
}
}
impl<'a, T: Sub + Clone> Sub<T> for Property<'a,T>
where <T as Sub>::Output: Clone
{
type Output = Property<'a, <T as Sub>::Output>;
fn sub(self, other: T) -> Property<'a, <T as Sub>::Output> {
self.map(move |a| a - other.clone())
}
}
impl<'a, T: Mul + Clone> Mul for Property<'a,T>
where <T as Mul>::Output: Clone
{
type Output = Property<'a, <T as Mul>::Output>;
fn mul(self, other: Property<'a, T>) -> Property<'a, <T as Mul>::Output> {
self.zip(other).map(|(a, b)| a * b)
}
}
impl<'a, T: Mul + Clone> Mul<T> for Property<'a,T>
where <T as Mul>::Output: Clone
{
type Output = Property<'a, <T as Mul>::Output>;
fn mul(self, other: T) -> Property<'a, <T as Mul>::Output> {
self.map(move |a| a * other.clone())
}
}
impl<'a, T: Div + Clone> Div for Property<'a,T>
where <T as Div>::Output: Clone
{
type Output = Property<'a, <T as Div>::Output>;
fn div(self, other: Property<'a, T>) -> Property<'a, <T as Div>::Output> {
self.zip(other).map(|(a, b)| a / b)
}
}
impl<'a, T: Div + Clone> Div<T> for Property<'a,T>
where <T as Div>::Output: Clone
{
type Output = Property<'a, <T as Div>::Output>;
fn div(self, other: T) -> Property<'a, <T as Div>::Output> {
self.map(move |a| a / other.clone())
}
}
impl<'a, T: BitAnd + Clone> BitAnd for Property<'a,T>
where <T as BitAnd>::Output: Clone
{
type Output = Property<'a, <T as BitAnd>::Output>;
fn bitand(self, other: Property<'a, T>) -> Property<'a, <T as BitAnd>::Output> {
self.zip(other).map(|(a, b)| a & b)
}
}
impl<'a, T: BitAnd + Clone> BitAnd<T> for Property<'a,T>
where <T as BitAnd>::Output: Clone
{
type Output = Property<'a, <T as BitAnd>::Output>;
fn bitand(self, other: T) -> Property<'a, <T as BitAnd>::Output> {
self.map(move |a| a & other.clone())
}
}
impl<'a, T: BitOr + Clone> BitOr for Property<'a,T>
where <T as BitOr>::Output: Clone
{
type Output = Property<'a, <T as BitOr>::Output>;
fn bitor(self, other: Property<'a, T>) -> Property<'a, <T as BitOr>::Output> {
self.zip(other).map(|(a, b)| a | b)
}
}
impl<'a, T: BitOr + Clone> BitOr<T> for Property<'a,T>
where <T as BitOr>::Output: Clone
{
type Output = Property<'a, <T as BitOr>::Output>;
fn bitor(self, other: T) -> Property<'a, <T as BitOr>::Output> {
self.map(move |a| a | other.clone())
}
}
impl<'a, T: BitXor + Clone> BitXor for Property<'a,T>
where <T as BitXor>::Output: Clone
{
type Output = Property<'a, <T as BitXor>::Output>;
fn bitxor(self, other: Property<'a, T>) -> Property<'a, <T as BitXor>::Output> {
self.zip(other).map(|(a, b)| a ^ b)
}
}
impl<'a, T: BitXor + Clone> BitXor<T> for Property<'a,T>
where <T as BitXor>::Output: Clone
{
type Output = Property<'a, <T as BitXor>::Output>;
fn bitxor(self, other: T) -> Property<'a, <T as BitXor>::Output> {
self.map(move |a| a ^ other.clone())
}
}
impl<'a, T: Rem + Clone> Rem for Property<'a,T>
where <T as Rem>::Output: Clone
{
type Output = Property<'a, <T as Rem>::Output>;
fn rem(self, other: Property<'a, T>) -> Property<'a, <T as Rem>::Output> {
self.zip(other).map(|(a, b)| a % b)
}
}
impl<'a, T: Rem + Clone> Rem<T> for Property<'a,T>
where <T as Rem>::Output: Clone
{
type Output = Property<'a, <T as Rem>::Output>;
fn rem(self, other: T) -> Property<'a, <T as Rem>::Output> {
self.map(move |a| a % other.clone())
}
}
impl<'a, T: Shl + Clone> Shl for Property<'a,T>
where <T as Shl>::Output: Clone
{
type Output = Property<'a, <T as Shl>::Output>;
fn shl(self, other: Property<'a, T>) -> Property<'a, <T as Shl>::Output> {
self.zip(other).map(|(a, b)| a << b)
}
}
impl<'a, T: Shl + Clone> Shl<T> for Property<'a,T>
where <T as Shl>::Output: Clone
{
type Output = Property<'a, <T as Shl>::Output>;
fn shl(self, other: T) -> Property<'a, <T as Shl>::Output> {
self.map(move |a| a << other.clone())
}
}
impl<'a, T: Shr + Clone> Shr for Property<'a,T>
where <T as Shr>::Output: Clone
{
type Output = Property<'a, <T as Shr>::Output>;
fn shr(self, other: Property<'a, T>) -> Property<'a, <T as Shr>::Output> {
self.zip(other).map(|(a, b)| a >> b)
}
}
impl<'a, T: Shr + Clone> Shr<T> for Property<'a,T>
where <T as Shr>::Output: Clone
{
type Output = Property<'a, <T as Shr>::Output>;
fn shr(self, other: T) -> Property<'a, <T as Shr>::Output> {
self.map(move |a| a >> other.clone())
}
}
impl<'a, T: Neg + Clone> Neg for Property<'a,T>
where <T as Neg>::Output: Clone
{
type Output = Property<'a, <T as Neg>::Output>;
fn neg(self) -> Property<'a, <T as Neg>::Output> {
self.map(|a| -a)
}
}
impl<'a, T: Index<U> + Clone, U: Clone> Index<U> for Property<'a,T> {
type Output = <T as Index<U>>::Output;
fn index(&self, index: U) -> &<T as Index<U>>::Output{
self.get().index(index)
}
}
impl<'a, T: Clone> From<T> for Property<'a,T>{
fn from(t: T) -> Property<'a, T>{
Property::new(t)
}
}
impl<'a, T: Clone> Borrow<T> for Property<'a, T>{
fn borrow(&self) -> &T {
self.get()
}
}