hexga_math/convert/
cast.rs

1use super::*;
2
3
4
5/// Same semantics as the [`as`](https://practice.course.rs/type-conversions/as.html)
6/// keyword: `4f32 as u64`, and the [From] trait, but generic friendly.
7///
8/// One should always prefer implementing [`CastFrom`] over [`CastInto`] because implementing [`CastFrom`] automatically provides one with an implementation of [`CastInto`] thanks to the blanket implementation in the hexga_math library.
9///
10/// Like the [`as`](https://practice.course.rs/type-conversions/as.html) keyword, the result might lose some precision.
11///
12/// ```rust
13/// use hexga_math::prelude::*;
14///
15/// assert_eq!(i32::cast_from(12.3f32), 12);
16///
17/// let casted : i32 = 12.3f32.cast_into();
18/// assert_eq!(casted, 12i32);
19/// ```
20///
21/// Also work with composite type
22/// ```ignore
23/// use hexga_math::prelude::*;
24///
25/// let x = [1, 2i32];
26/// let y : [f32; 2] = x.cast_into(),
27/// assert_eq!(y, [1f32, 2f32]);
28///
29///
30/// let a = point2(1, 2);
31/// let b : Vec2 = a.cast_into(),
32/// assert_eq!(b, vec2(1., 2.));
33/// ```
34pub trait CastFrom<T>
35{
36    fn cast_from(value : T) -> Self;
37}
38impl<C1,C2> CastFrom<C2> for C1 where C1: Map, C2: Map<WithType<C1::Item> = Self>, C1::Item : CastFrom<C2::Item>
39{
40    fn cast_from(value : C2) -> Self
41    {
42        value.map(|v| C1::Item::cast_from(v))
43    }
44}
45
46
47/// Same semantics as the [`as`](https://practice.course.rs/type-conversions/as.html)
48/// keyword: `4f32 as u64`, and the [From] trait, but generic friendly.
49///
50/// One should always prefer implementing [`CastFrom`] over [`CastInto`] because implementing [`CastFrom`] automatically provides one with an implementation of [`CastInto`] thanks to the blanket implementation in the hexga_math library.
51///
52/// Like the [`as`](https://practice.course.rs/type-conversions/as.html) keyword, the result might lose some precision.
53///
54/// ```rust
55/// use hexga_math::prelude::*;
56///
57/// assert_eq!(i32::cast_from(12.3f32), 12);
58///
59/// let casted : i32 = 12.3f32.cast_into();
60/// assert_eq!(casted, 12i32);
61/// ```
62///
63/// Also work with composite type
64/// ```ignore
65/// use hexga_math::prelude::*;
66///
67/// let x = [1, 2i32];
68/// let y : [f32; 2] = x.cast_into(),
69/// assert_eq!(y, [1f32, 2f32]);
70///
71///
72/// let a = point2(1, 2);
73/// let b : Vec2 = a.cast_into(),
74/// assert_eq!(b, vec2(1., 2.));
75/// ```
76pub trait CastInto<T> : Sized
77{
78    fn cast_into(self) -> T;
79}
80impl<S,T> CastInto<T> for S where T:CastFrom<S>
81{
82    fn cast_into(self) -> T {
83        T::cast_from(self)
84    }
85}
86
87
88// Double recursive macro :)
89macro_rules! impl_cast_to
90{
91    ($src: ty, $dest: ty) =>
92    {
93        impl CastFrom<$src> for $dest
94        {
95            fn cast_from(value: $src) -> $dest { value as $dest }
96        }
97    };
98
99    ($cast_into: ty) =>
100    {
101        map_on_number!(impl_cast_to,$cast_into);
102    };
103}
104map_on_number!(impl_cast_to);
105
106
107map_on_integer!(
108    ($itself: ty) =>
109    {
110        impl CastFrom<bool> for $itself
111        {
112            fn cast_from(value: bool) -> $itself  { if value { 1 } else { 0 } }
113        }
114
115        impl CastFrom<$itself> for bool
116        {
117            fn cast_from(value: $itself) -> bool { value != (0) }
118        }
119    };
120);
121map_on_float!(
122    ($itself: ty) =>
123    {
124        impl CastFrom<bool> for $itself
125        {
126            fn cast_from(value: bool) -> $itself  { if value { 1. } else { 0. } }
127        }
128
129        impl CastFrom<$itself> for bool
130        {
131            fn cast_from(value: $itself) -> bool { value as $itself >= 0.5 }
132        }
133    };
134);
135impl CastFrom<bool> for bool { fn cast_from(value : bool) -> Self { value } }
136
137
138
139trait_marker!(
140    /// fX
141    CastIntoFloat: CastInto<f32> + ToF32<Output = f32> + CastInto<f64> + ToF64<Output = f64>
142);
143
144trait_marker!(
145    /// fX
146    CastFromFloat: CastFrom<f32> + CastFrom<f64>
147);
148
149trait_marker!(
150    /// fX
151    CastFloat: CastIntoFloat + CastFromFloat
152);
153
154trait_marker!(
155/// uX
156CastIntoIntegerUnsigned:
157    CastInto<u8 > + ToU8<Output = u8> +
158    CastInto<u16> + ToU16<Output = u16> +
159    CastInto<u32> + ToU32<Output = u32> +
160    CastInto<u64> + ToU64<Output = u64> +
161    CastInto<usize> + ToUSize<Output = usize> +
162);
163
164trait_marker!(
165/// uX
166CastFromIntegerUnsigned:
167    CastFrom<u8 > +
168    CastFrom<u16> +
169    CastFrom<u32> +
170    CastFrom<u64> +
171    CastFrom<usize>
172);
173
174
175trait_marker!(
176/// uX
177CastIntegerUnsigned: CastFromIntegerUnsigned + CastFromIntegerUnsigned
178);
179
180trait_marker!(
181/// iX
182CastIntoIntegerSigned:
183    CastInto<i8 > + ToI8<Output = i8> +
184    CastInto<i16> + ToI16<Output = i16> +
185    CastInto<i32> + ToI32<Output = i32> +
186    CastInto<i64> + ToI64<Output = i64> +
187    CastInto<isize> + ToISize<Output = isize>
188);
189
190
191trait_marker!(
192/// iX
193CastFromIntegerSigned:
194    CastFrom<i8 > +
195    CastFrom<i16> +
196    CastFrom<i32> +
197    CastFrom<i64> +
198    CastFrom<isize>
199);
200
201
202trait_marker!(
203/// iX
204CastIntegerSigned: CastFromIntegerSigned + CastFromIntegerUnsigned
205);
206
207trait_marker!(
208/// iX uX
209CastIntoInteger: CastIntoIntegerSigned + CastIntoIntegerUnsigned
210);
211
212trait_marker!(
213/// iX uX
214CastFromInteger: CastFromIntegerSigned + CastFromIntegerUnsigned
215);
216
217trait_marker!(
218/// iX uX
219CastInteger: CastIntoInteger + CastFromInteger
220);
221
222
223trait_marker!(
224/// bool
225CastIntoBool: CastInto<bool> + ToBool<Output = bool>
226);
227
228trait_marker!(
229/// bool
230CastFromBool: CastFrom<bool>
231);
232
233trait_marker!(
234/// bool
235CastBool: CastIntoBool + CastFromBool
236);
237
238trait_marker!(
239/// iX uX fX
240CastIntoNumber: CastIntoInteger + CastIntoFloat
241);
242
243trait_marker!(
244/// iX uX fX
245CastFromNumber: CastFromInteger + CastFromFloat
246);
247
248trait_marker!(
249/// iX uX fX
250CastNumber: CastInteger + CastFloat
251);
252
253trait_marker!(
254/// iX uX fX bool
255CastIntoPrimitive: CastIntoNumber + CastIntoBool
256);
257
258trait_marker!(
259/// iX uX fX bool
260CastFromPrimitive: CastFromNumber + CastFromBool
261);
262
263trait_marker!(
264/// iX uX fX bool
265CastPrimitive: CastIntoPrimitive + CastFromPrimitive
266);