use std::fmt::{self, Debug, Formatter};
use std::ops::{Range, Sub};
use std::cell::UnsafeCell;
use std::rc::Rc;
use crate::{Property, PropertyLastValue, StreamRc, TryIter, Parameter};
use std::borrow::Borrow;
#[cfg(feature="numbers")]
use num_traits::{ToPrimitive,FromPrimitive};
use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
#[derive(Clone,Debug,Copy,Serialize,Deserialize)]
pub enum Scale{
Linear,
Log,
}
#[derive(Clone,Debug,Serialize,Deserialize)]
pub struct RangedPropertyMut<'a, T: Clone + 'static, R=T>{
property: Property<'a,T>,
scale: Scale,
range: Range<R>,
}
impl<'a, T:Clone, R:Clone> RangedPropertyMut<'a,T,R>{
pub fn new(value: T, range: Range<R>) -> RangedPropertyMut<'a,T,R>{
RangedPropertyMut{
property: Property::new(value),
scale: Scale::Linear,
range: range,
}
}
pub fn new_log_scale(v: T, range: Range<R>) -> RangedPropertyMut<'a,T,R>{
RangedPropertyMut{
property: Property::new(v),
scale: Scale::Log,
range: range,
}
}
pub fn from_property(property: Property<'a, T>, range: Range<R>) -> RangedPropertyMut<'a,T,R>{
RangedPropertyMut{
property,
scale: Scale::Linear,
range: range,
}
}
pub fn from_property_log_scale(property: Property<'a, T>, range: Range<R>) -> RangedPropertyMut<'a,T,R>{
RangedPropertyMut{
property,
scale: Scale::Log,
range: range,
}
}
pub fn range(&self) -> Range<R>{
self.range.clone()
}
pub fn by_ref(&self) -> &RangedPropertyMut<'a,T,R>{
self
}
#[inline]
pub fn min(&self) -> R{
self.range.start.clone()
}
#[inline]
pub fn max(&self) -> R{
self.range.end.clone()
}
pub fn get(&self) -> &T{
self.property.get()
}
pub fn set(&mut self, t: T){
self.property.set(t)
}
pub fn scale(&self) -> Scale{
self.scale
}
pub fn into_property(self) -> Property<'a,T>{
self.property
}
pub fn stream(self) -> StreamRc<'a,T>{
self.property.stream()
}
pub fn map<'b,T2:Clone,F:FnMut(T)->T2 + 'a>(self, f: F) -> RangedPropertyMut<'a,T2,R>{
RangedPropertyMut{
property: self.property.map(f),
scale: self.scale,
range: self.range
}
}
pub fn try_iter<'b>(self) -> TryIter<'b,T> where 'a: 'b{
self.property.try_iter()
}
pub fn to_parameter<'b>(self) -> Parameter<'b,T> where 'a: 'b{
self.property.to_parameter()
}
}
impl<'a,T:Clone, R:Clone> RangedPropertyMut<'a,T,R>{
pub fn to_const(self) -> RangedProperty<'a,T,R>{
RangedProperty::new(self.property, self.range)
}
}
impl<'a, T: Clone + 'a, R: Sub<Output=R> + Clone + 'static> RangedPropertyMut<'a, T,R>{
#[inline]
pub fn diff(&self) -> R{
self.max() - self.min()
}
}
#[cfg(feature="numbers")]
impl<'a, T, R> RangedPropertyMut<'a, T, R>
where T: Sub<Output=T> + Clone + ToPrimitive + FromPrimitive + 'static,
R: Clone + ToPrimitive + Sub<Output=R> + 'static
{
#[inline]
pub fn pct(&self) -> f64{
let pct = (self.as_ref().to_f64().unwrap() - self.min().to_f64().unwrap()) / self.diff().to_f64().unwrap();
match self.scale{
Scale::Linear => pct,
Scale::Log => pct.sqrt(),
}
}
#[inline]
pub fn set_pct(&mut self, pct: f64){
let pct = match self.scale{
Scale::Linear => pct,
Scale::Log => pct * pct,
};
let v = pct * self.diff().to_f64().unwrap() + self.min().to_f64().unwrap();
self.set(T::from_f64(v).unwrap());
}
}
impl<'a, T: Clone, R> AsRef<T> for RangedPropertyMut<'a,T,R>{
fn as_ref(&self) -> &T{
self.property.as_ref()
}
}
impl<'a, T: Clone, R> Borrow<T> for RangedPropertyMut<'a,T,R>{
fn borrow(&self) -> &T{
self.property.as_ref()
}
}
#[derive(Clone,Debug,Serialize,Deserialize)]
pub struct RangedPropertyLastValueMut<'a, T: Clone + 'static, R=T>{
property: PropertyLastValue<'a,T>,
scale: Scale,
range: Range<R>,
}
impl<'a, T:Clone, R:Clone> RangedPropertyLastValueMut<'a,T,R>{
pub fn new(value: T, range: Range<R>) -> RangedPropertyLastValueMut<'a,T,R>{
RangedPropertyLastValueMut{
property: PropertyLastValue::new(value),
scale: Scale::Linear,
range: range,
}
}
pub fn new_log_scale(v: T, range: Range<R>) -> RangedPropertyLastValueMut<'a,T,R>{
RangedPropertyLastValueMut{
property: PropertyLastValue::new(v),
scale: Scale::Log,
range: range,
}
}
pub fn from_property(property: PropertyLastValue<'a, T>, range: Range<R>) -> RangedPropertyLastValueMut<'a,T,R>{
RangedPropertyLastValueMut{
property,
scale: Scale::Linear,
range: range,
}
}
pub fn from_property_log_scale(property: PropertyLastValue<'a, T>, range: Range<R>) -> RangedPropertyLastValueMut<'a,T,R>{
RangedPropertyLastValueMut{
property,
scale: Scale::Log,
range: range,
}
}
pub fn range(&self) -> Range<R>{
self.range.clone()
}
pub fn by_ref(&self) -> &RangedPropertyLastValueMut<'a,T,R>{
self
}
#[inline]
pub fn min(&self) -> R{
self.range.start.clone()
}
#[inline]
pub fn max(&self) -> R{
self.range.end.clone()
}
pub fn get(&self) -> &T{
self.property.get()
}
pub fn set(&mut self, t: T){
self.property.set(t)
}
pub fn scale(&self) -> Scale{
self.scale
}
pub fn into_property(self) -> PropertyLastValue<'a,T>{
self.property
}
pub fn stream(self) -> StreamRc<'a,T>{
self.property.stream()
}
pub fn map<'b,T2:Clone,F:FnMut(T)->T2 + 'a>(self, f: F) -> RangedPropertyLastValueMut<'a,T2,R>{
RangedPropertyLastValueMut{
property: self.property.map(f),
scale: self.scale,
range: self.range
}
}
pub fn try_iter<'b>(self) -> TryIter<'b,T> where 'a: 'b{
self.property.try_iter()
}
pub fn to_parameter<'b>(self) -> Parameter<'b,T> where 'a: 'b{
self.property.to_parameter()
}
pub fn last_value(&mut self) -> Option<&T> {
self.property.last_value()
}
pub fn into_ranged_property_mut(self) -> RangedPropertyMut<'a, T, R> {
RangedPropertyMut{
property: self.property.into_property(),
scale: self.scale,
range: self.range,
}
}
}
impl<'a,T:Clone, R:Clone> RangedPropertyLastValueMut<'a,T,R>{
pub fn to_const(self) -> RangedProperty<'a,T,R>{
RangedProperty::new(self.property.into_property(), self.range)
}
}
impl<'a, T: Clone + 'a, R: Sub<Output=R> + Clone + 'static> RangedPropertyLastValueMut<'a, T,R>{
#[inline]
pub fn diff(&self) -> R{
self.max() - self.min()
}
}
#[cfg(feature="numbers")]
impl<'a, T, R> RangedPropertyLastValueMut<'a, T, R>
where T: Sub<Output=T> + Clone + ToPrimitive + FromPrimitive + 'static,
R: Clone + ToPrimitive + Sub<Output=R> + 'static
{
#[inline]
pub fn pct(&self) -> f64{
let pct = (self.as_ref().to_f64().unwrap() - self.min().to_f64().unwrap()) / self.diff().to_f64().unwrap();
match self.scale{
Scale::Linear => pct,
Scale::Log => pct.sqrt(),
}
}
#[inline]
pub fn set_pct(&mut self, pct: f64){
let pct = match self.scale{
Scale::Linear => pct,
Scale::Log => pct * pct,
};
let v = pct * self.diff().to_f64().unwrap() + self.min().to_f64().unwrap();
self.set(T::from_f64(v).unwrap());
}
}
impl<'a, T: Clone, R> AsRef<T> for RangedPropertyLastValueMut<'a,T,R>{
fn as_ref(&self) -> &T{
self.property.as_ref()
}
}
impl<'a, T: Clone, R> Borrow<T> for RangedPropertyLastValueMut<'a,T,R>{
fn borrow(&self) -> &T{
self.property.as_ref()
}
}
pub struct IterProperty<'a, T>{
iter: Iter<'a, T>,
last_value: UnsafeCell<Option<T>>,
}
impl<'a, T: PartialEq> PartialEq for IterProperty<'a, T>{
fn eq(&self, other: &IterProperty<'a,T>) -> bool{
unsafe{ *self.last_value.get() == *other.last_value.get() }
}
}
impl<'a, T: Debug> Debug for IterProperty<'a,T>{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.debug_struct("IterPara,eter")
.field("last_value", &self.last_value)
.finish()
}
}
impl<'a, T: Clone> IterProperty<'a,T>{
pub fn new<I: Iterator<Item=T> + 'a>(iter: I) -> IterProperty<'a,T>{
IterProperty{
iter: Iter{ iter: Rc::new(UnsafeCell::new(iter)) },
last_value: UnsafeCell::new(None),
}
}
#[inline]
fn update(&self){
let iter = unsafe{ &mut *self.iter.iter.get() };
if let Some(value) = iter.last() {
unsafe{ *self.last_value.get() = Some(value) }
}
}
pub fn iter(&self) -> Iter<'a,T>{
self.iter.clone()
}
}
#[derive(Clone)]
pub struct Iter<'a, T>{
iter: Rc<UnsafeCell<dyn Iterator<Item=T> + 'a>>,
}
impl<'a,T> Iterator for Iter<'a,T>{
type Item = T;
fn next(&mut self) -> Option<T>{
unsafe{ (*self.iter.get()).next() }
}
}
pub trait ConstProperty<'a, T: Clone>{
fn get(&self) -> Option<&T>;
fn iter(&self) -> Iter<'a,T>;
}
impl<'a, T: Clone> ConstProperty<'a,T> for IterProperty<'a,T>{
fn get(&self) -> Option<&T>{
self.update();
unsafe{ (*self.last_value.get()).as_ref() }
}
fn iter(&self) -> Iter<'a,T>{
(*self).iter()
}
}
impl<'a, T: Clone + 'a> ConstProperty<'a,T> for Property<'a,T>{
fn get(&self) -> Option<&T>{
Some(self.get())
}
fn iter(&self) -> Iter<'a,T>{
Iter{
iter: Rc::new(UnsafeCell::new(self.clone().try_iter()))
}
}
}
#[derive(Clone)]
pub struct RangedProperty<'a, T, R=T>{
param: Rc<dyn ConstProperty<'a,T> + 'a>,
scale: Scale,
range: Range<R>,
}
impl<'a, T: Clone + Debug, R: Debug> Debug for RangedProperty<'a,T,R>{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("RangedProperty")
.field("param", &self.param.get())
.field("scale", &self.scale)
.field("range", &self.range)
.finish()
}
}
impl<'a, T: Clone + 'a, R: Clone> RangedProperty<'a,T,R>{
pub fn from_iter<I: Iterator<Item=T> + 'a>(iter: I, range: Range<R>) -> RangedProperty<'a,T,R>{
RangedProperty{
param: Rc::new(IterProperty::new(iter)),
scale: Scale::Linear,
range: range
}
}
pub fn from_iter_log_scale<I: Iterator<Item=T> + 'a>(iter: I, range: Range<R>) -> RangedProperty<'a,T,R>{
RangedProperty{
param: Rc::new(IterProperty::new(iter)),
scale: Scale::Log,
range: range
}
}
pub fn new(property: Property<'a,T>, range: Range<R>) -> RangedProperty<'a,T,R>{
RangedProperty{
param: Rc::new(property),
scale: Scale::Linear,
range: range
}
}
pub fn new_log_scale(property: Property<'a,T>, range: Range<R>) -> RangedProperty<'a,T,R>{
RangedProperty{
param: Rc::new(property),
scale: Scale::Log,
range: range
}
}
pub fn range(&self) -> Range<R>{
self.range.clone()
}
pub fn by_ref(&self) -> &RangedProperty<'a,T,R>{
self
}
#[inline]
pub fn min(&self) -> R{
self.range.start.clone()
}
#[inline]
pub fn max(&self) -> R{
self.range.end.clone()
}
pub fn get(&self) -> Option<&T>{
self.param.get()
}
pub fn iter(&self) -> Iter<'a,T>{
self.param.iter()
}
}
impl<'a, T: Clone + 'a, R: Sub<Output=R> + Clone + 'static> RangedProperty<'a, T, R>{
#[inline]
pub fn diff(&self) -> R{
self.max() - self.min()
}
}
#[cfg(feature="numbers")]
impl<'a, T, R> RangedProperty<'a, T, R>
where T: Sub<Output=T> + Clone + ToPrimitive + FromPrimitive + 'static,
R:Clone + ToPrimitive + Sub<Output=R> + 'static
{
#[inline]
pub fn pct(&self) -> Option<f64>{
self.get().map(|v| {
let pct = (v.to_f64().unwrap() - self.min().to_f64().unwrap()) / self.diff().to_f64().unwrap();
match self.scale{
Scale::Linear => pct,
Scale::Log => pct.sqrt(),
}
})
}
}
impl<'a, T: Clone + Serialize + 'a, R: Clone + Serialize> Serialize for RangedProperty<'a,T,R>{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>{
let mut state = serializer.serialize_struct("RangedProperty", 3)?;
state.serialize_field("param", &self.get())?;
state.serialize_field("scale", &self.scale)?;
state.serialize_field("range", &self.range)?;
state.end()
}
}
impl<'a, T: PartialEq + Clone + 'a, R: PartialEq + Clone> PartialEq for RangedProperty<'a,T,R>{
fn eq(&self, other: &RangedProperty<'a,T,R>) -> bool{
self.get() == other.get() &&
self.range() == other.range()
}
}