lang-extension 1.3.0

Rust Lang Extension
Documentation
use std::any::type_name;
use std::fmt;
use std::sync::Arc;

use crate::any::*;
use crate::ops::function::*;
use crate::*;

pub trait RawValueFilter: Value + Sync + Send {
    fn filter_raw(&self, value: Box<dyn Value>) -> Option<Box<dyn Value>>;

    as_trait!(RawValueFilter);
    as_boxed!(RawValueFilter);
}

boxed_value_trait!(RawValueFilter);

pub trait ValueFilter<V: ?Sized + ValueConstraint>: RawValueFilter {
    fn filter(&self, value: Box<V>) -> Option<Box<V>>;

    as_boxed!(ValueFilter<V>);
}

boxed_value_trait!(ValueFilter<V: ?Sized + ValueConstraint>);

#[derive(Clone)]
pub struct DefaultValueFilter<V: ?Sized + ValueConstraint> {
    filter: Function<Box<V>, Option<Box<V>>>,
}

impl<V: ?Sized + ValueConstraint> DefaultValueFilter<V> {
    pub fn new(filter: Box<dyn Fn(Box<V>) -> Option<Box<V>>>) -> Self {
        Self::wrap(Arc::new(filter))
    }

    pub fn wrap(filter: Arc<Box<dyn Fn(Box<V>) -> Option<Box<V>>>>) -> Self {
        Self { filter: filter }
    }
}

impl<V: ?Sized + ValueConstraint> ValueFilter<V> for DefaultValueFilter<V> {
    fn filter(&self, value: Box<V>) -> Option<Box<V>> {
        self.filter.as_ref()(value)
    }

    as_boxed!(impl ValueFilter<V>);
}

impl<V: ?Sized + ValueConstraint> PartialEq for DefaultValueFilter<V> {
    fn eq(&self, other: &Self) -> bool {
        self.filter.as_ref().reference_equals(other.filter.as_ref())
    }
}

impl<V: ?Sized + ValueConstraint> Eq for DefaultValueFilter<V> {}

impl<V: ?Sized + ValueConstraint> fmt::Debug for DefaultValueFilter<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} {{ filter: {} }}",
            type_name::<DefaultValueFilter<V>>(),
            self.filter.type_name()
        )
    }
}

unsafe impl<V: ?Sized + ValueConstraint> Sync for DefaultValueFilter<V> {}
unsafe impl<V: ?Sized + ValueConstraint> Send for DefaultValueFilter<V> {}

impl<V: ?Sized + ValueConstraint> RawValueFilter for DefaultValueFilter<V> {
    fn filter_raw(&self, value: Box<dyn Value>) -> Option<Box<dyn Value>> {
        match value.as_ref().as_any_ref().downcast_ref::<V>() {
            Some(value) => self.filter.as_ref()(Box::new(value.clone()))
                .map(|v| Value::clone_boxed(v.as_ref())),
            None => None,
        }
    }

    as_trait!(impl RawValueFilter);
    as_boxed!(impl RawValueFilter);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn value_filter_test() {
        let filter =
            DefaultValueFilter::<i32>::new(Box::new(|v| if *v > 10 { Some(v) } else { None }));
        let v = filter.filter(Box::new(10));
        assert_eq!(None, v);
        let v = filter.filter(Box::new(11));
        assert_eq!(Box::new(11), v.unwrap());
        let v = RawValueFilter::filter_raw(&filter, Box::new(11));
        let expected: Box<dyn Value> = Box::new(11);
        assert_eq!(&expected, &v.unwrap());
    }
}