computation_types/
black_box.rs

1use core::fmt;
2use std::marker::PhantomData;
3
4use crate::{impl_core_ops, Computation, ComputationFn, NamedArgs, Names};
5
6/// See [`Computation::black_box`].
7#[derive(Clone, Copy, Debug)]
8pub struct BlackBox<A, F, FDim, FItem>
9where
10    Self: Computation,
11{
12    pub child: A,
13    pub f: F,
14    pub(super) f_dim: PhantomData<FDim>,
15    pub(super) f_item: PhantomData<FItem>,
16}
17
18impl<A, F, FDim, FItem> BlackBox<A, F, FDim, FItem>
19where
20    Self: Computation,
21{
22    pub fn new(child: A, f: F) -> Self {
23        Self {
24            child,
25            f,
26            f_dim: PhantomData,
27            f_item: PhantomData,
28        }
29    }
30}
31
32impl<A, F, FDim, FItem> Computation for BlackBox<A, F, FDim, FItem>
33where
34    A: Computation,
35{
36    type Dim = FDim;
37    type Item = FItem;
38}
39
40impl<A, F, FDim, FItem> ComputationFn for BlackBox<A, F, FDim, FItem>
41where
42    Self: Computation,
43    A: ComputationFn,
44    BlackBox<A::Filled, F, FDim, FItem>: Computation,
45{
46    type Filled = BlackBox<A::Filled, F, FDim, FItem>;
47
48    fn fill(self, named_args: NamedArgs) -> Self::Filled {
49        BlackBox {
50            child: self.child.fill(named_args),
51            f: self.f,
52            f_dim: self.f_dim,
53            f_item: self.f_item,
54        }
55    }
56
57    fn arg_names(&self) -> Names {
58        self.child.arg_names()
59    }
60}
61
62impl_core_ops!(BlackBox<A, F, FDim, FItem>);
63
64impl<A, F, FDim, FItem> fmt::Display for BlackBox<A, F, FDim, FItem>
65where
66    Self: Computation,
67    A: fmt::Display,
68{
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "f({})", self.child)
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use proptest::prelude::*;
77    use test_strategy::proptest;
78
79    use crate::{peano::Zero, val, Computation};
80
81    #[proptest]
82    fn black_box_should_display(x: i32) {
83        let inp = val!(x);
84        prop_assert_eq!(
85            inp.black_box::<_, Zero, i32>(|x: i32| x + 1).to_string(),
86            format!("f({})", inp)
87        );
88    }
89}