pipebase/common/
project.rs

1/// Project input to Self
2pub trait Project<Rhs = Self> {
3    fn project(rhs: &Rhs) -> Self;
4}
5
6impl Project<bool> for bool {
7    fn project(from: &bool) -> bool {
8        *from
9    }
10}
11
12impl Project<i8> for i8 {
13    fn project(from: &i8) -> i8 {
14        *from
15    }
16}
17
18impl Project<u8> for u8 {
19    fn project(from: &u8) -> u8 {
20        *from
21    }
22}
23
24impl Project<i16> for i16 {
25    fn project(from: &i16) -> i16 {
26        *from
27    }
28}
29
30impl Project<u16> for u16 {
31    fn project(from: &u16) -> u16 {
32        *from
33    }
34}
35
36impl Project<i32> for i32 {
37    fn project(from: &i32) -> i32 {
38        *from
39    }
40}
41
42impl Project<u32> for u32 {
43    fn project(from: &u32) -> u32 {
44        *from
45    }
46}
47
48impl Project<isize> for isize {
49    fn project(from: &isize) -> isize {
50        *from
51    }
52}
53
54impl Project<usize> for usize {
55    fn project(from: &usize) -> usize {
56        *from
57    }
58}
59
60impl Project<i64> for i64 {
61    fn project(from: &i64) -> i64 {
62        *from
63    }
64}
65
66impl Project<u64> for u64 {
67    fn project(from: &u64) -> u64 {
68        *from
69    }
70}
71
72impl Project<i128> for i128 {
73    fn project(from: &i128) -> i128 {
74        *from
75    }
76}
77
78impl Project<u128> for u128 {
79    fn project(from: &u128) -> u128 {
80        *from
81    }
82}
83
84impl Project<f32> for f32 {
85    fn project(from: &f32) -> f32 {
86        *from
87    }
88}
89
90impl Project<f64> for f64 {
91    fn project(from: &f64) -> f64 {
92        *from
93    }
94}
95
96impl Project<char> for char {
97    fn project(from: &char) -> char {
98        *from
99    }
100}
101
102impl Project<String> for String {
103    fn project(from: &String) -> String {
104        from.clone()
105    }
106}
107
108impl<T, U: Project<T>> Project<Option<T>> for Option<U> {
109    fn project(from: &Option<T>) -> Option<U> {
110        from.as_ref().map(|t| U::project(t))
111    }
112}
113
114/// Project Fixed Size Array
115impl<T, U, const N: usize> Project<[T; N]> for [U; N]
116where
117    U: Project<T> + Default + Copy,
118{
119    fn project(from: &[T; N]) -> [U; N] {
120        let mut to: [U; N] = [U::default(); N];
121        for i in 0..N {
122            to[i] = U::project(&from[i])
123        }
124        to
125    }
126}
127
128/// Project Vec
129impl<T, U> Project<Vec<T>> for Vec<U>
130where
131    U: Project<T>,
132{
133    fn project(from: &Vec<T>) -> Vec<U> {
134        let to: Vec<U> = from.iter().map(|item| U::project(item)).collect();
135        to
136    }
137}
138
139#[cfg(test)]
140mod tests {
141
142    use crate::prelude::*;
143
144    #[derive(Debug)]
145    struct Record {
146        pub r0: i32,
147        pub r1: i32,
148    }
149
150    #[derive(Debug, Project)]
151    #[project(input = "self::Record")]
152    struct SwappedRecord {
153        #[project(from = "r1")]
154        pub r0: i32,
155        #[project(from = "r0")]
156        pub r1: i32,
157    }
158
159    #[test]
160    fn test_swap() {
161        let origin = Record { r0: 0, r1: 1 };
162        let swapped: SwappedRecord = Project::project(&origin);
163        assert_eq!(1, swapped.r0);
164        assert_eq!(0, swapped.r1);
165    }
166
167    #[derive(Debug, Project)]
168    #[project(input = "Record")]
169    struct RecordSumPlusOne {
170        #[project(alias = "r", expr = "let mut s = r.r0 + r.r1; s + 1")]
171        pub s: i32,
172    }
173
174    #[test]
175    fn test_sum_plus_one() {
176        let origin = Record { r0: 1, r1: 1 };
177        let sum = RecordSumPlusOne::project(&origin);
178        assert_eq!(3, sum.s);
179    }
180}