computation_types/
val.rs

1use core::fmt;
2use std::marker::PhantomData;
3
4use crate::{
5    impl_core_ops,
6    peano::{One, Suc, Two, Zero},
7    Computation, ComputationFn, NamedArgs, Names,
8};
9
10#[derive(Clone, Copy, Debug)]
11pub struct Val<Dim, T>
12where
13    Self: Computation,
14{
15    dim: PhantomData<Dim>,
16    pub inner: T,
17}
18
19pub type Val0<T> = Val<Zero, T>;
20pub type Val1<T> = Val<One, T>;
21pub type Val2<T> = Val<Two, T>;
22
23impl<Dim, T> Val<Dim, T>
24where
25    Self: Computation,
26{
27    pub fn new(value: T) -> Self {
28        Val {
29            dim: PhantomData,
30            inner: value,
31        }
32    }
33}
34
35#[macro_export]
36macro_rules! val {
37    ( $value:expr ) => {
38        $crate::Val0::new($value)
39    };
40}
41
42#[macro_export]
43macro_rules! val1 {
44    ( $value:expr ) => {
45        $crate::Val1::new($value)
46    };
47}
48
49#[macro_export]
50macro_rules! val2 {
51    ( $value:expr ) => {
52        $crate::Val2::new($value)
53    };
54}
55
56impl<T> Computation for Val<Zero, T> {
57    type Dim = Zero;
58    type Item = T;
59}
60
61impl<D, T> Computation for Val<Suc<D>, T>
62where
63    T: IntoIterator,
64{
65    type Dim = Suc<D>;
66    type Item = T::Item;
67}
68
69impl<D, T> ComputationFn for Val<D, T>
70where
71    Val<D, T>: Computation,
72{
73    type Filled = Self;
74
75    fn fill(self, _named_args: NamedArgs) -> Self::Filled {
76        self
77    }
78
79    fn arg_names(&self) -> Names {
80        Names::new()
81    }
82}
83
84impl_core_ops!(Val<Dim, T>);
85
86impl<T> fmt::Display for Val<Zero, T>
87where
88    T: fmt::Debug,
89{
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        self.inner.fmt(f)
92    }
93}
94
95impl<D, T> fmt::Display for Val<Suc<D>, T>
96where
97    Self: Computation,
98    T: fmt::Debug,
99{
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        write!(f, "{:?}", self.inner)
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use proptest::prelude::*;
108    use test_strategy::proptest;
109
110    #[proptest]
111    fn val_should_display_inner(x: i32) {
112        prop_assert_eq!(val!(x).to_string(), x.to_string())
113    }
114
115    #[proptest]
116    fn val1_should_display_items(xs: Vec<i32>) {
117        prop_assert_eq!(val1!(xs.clone()).to_string(), format!("{:?}", xs.clone()));
118    }
119}