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}