multi_param/
multi_param.rs

1/// Usage of [`FuncMap`] to "deeply" convert units, using independent type
2/// parameters for different units
3use funcmap::{FuncMap, TypeParam};
4use units::*;
5
6/// Example data structure illustrating the use of [`FuncMap`]
7/// `L` and `M` are meant to be units of length resp. mass from the [units]
8/// module below
9#[derive(FuncMap, Debug)]
10struct Measurements<L, M> {
11    lengths: Vec<L>,
12    masses: Vec<M>,
13}
14
15/// Aliases for the markers for the two type parameters of [`Measurements`]
16/// These are abstractions over the concrete indices `0` and `1`
17type LengthParam = TypeParam<0>;
18type MassParam = TypeParam<1>;
19
20impl<L, M> Measurements<L, M> {
21    fn into_base(self) -> Measurements<Meter, Kilogram>
22    where
23        L: Into<Meter>,
24        M: Into<Kilogram>,
25    {
26        // use `func_map_over` to specify the type parameter of `Measurements`
27        // over which the mapping is to be performed
28        self.func_map_over::<LengthParam, _>(Into::into)
29            .func_map_over::<MassParam, _>(Into::into)
30    }
31}
32
33fn main() {
34    let measurements = Measurements {
35        lengths: vec![Kilometer(5), Kilometer(42)],
36        masses: vec![Gram(1000), Gram(5000)],
37    };
38
39    println!("{:?}", measurements.into_base());
40}
41
42/// Helpers dealing with units
43mod units {
44    #[derive(Debug)]
45    #[allow(dead_code)]
46    pub struct Meter(pub u32);
47
48    #[derive(Debug)]
49    #[allow(dead_code)]
50    pub struct Kilometer(pub u32);
51
52    #[derive(Debug)]
53    #[allow(dead_code)]
54    pub struct Gram(pub u32);
55
56    #[derive(Debug)]
57    #[allow(dead_code)]
58    pub struct Kilogram(pub u32);
59
60    impl From<Kilometer> for Meter {
61        fn from(Kilometer(km): Kilometer) -> Self {
62            Self(km * 1000)
63        }
64    }
65
66    impl From<Gram> for Kilogram {
67        fn from(Gram(g): Gram) -> Self {
68            Self(g / 1000)
69        }
70    }
71}