1use crate::*;
2pub trait Cast<T> {
7 fn cast(self) -> T;
23}
24
25impl<T: IsNone> Cast<Option<T>> for T {
26 #[inline]
27 fn cast(self) -> Option<T> {
28 if self.is_none() { None } else { Some(self) }
29 }
30}
31
32impl<T> Cast<T> for T {
33 #[inline(always)]
34 fn cast(self) -> T {
35 self
36 }
37}
38
39macro_rules! impl_numeric_cast {
40 (@ $T: ty => impl $U: ty ) => {
41 impl Cast<$U> for $T {
42 #[inline] fn cast(self) -> $U { self as $U }
43 }
44
45 impl Cast<Option<$U>> for $T {
46 #[inline] fn cast(self) -> Option<$U> {
47 if self.is_none() {
48 None
49 } else {
50 Some(self as $U)
51 }
52 }
53 }
54
55 impl Cast<Option<$U>> for Option<$T> {
56 #[inline] fn cast(self) -> Option<$U> {
57 self.map(|v| v.cast())
58 }
59 }
60
61 impl Cast<$U> for Option<$T> {
62 #[inline] fn cast(self) -> $U { self.map(|v| v as $U).unwrap_or_else(<$U as IsNone>::none)}
63 }
64 };
65
66 (@ $T: ty => { $( $U: ty ),* } ) => {$(
67 impl_numeric_cast!(@ $T => impl $U);
68 )*};
69
70 (@common_impl $T: ty => { $( $U: ty ),* } ) => {
71
72 impl Cast<bool> for $T {
74 #[inline] fn cast(self) -> bool {
75 let value = Cast::<i32>::cast(self);
76 if value == 0_i32 {
77 false
78 } else if value == 1 {
79 true
80 } else {
81 panic!("can not cast {value:?} to bool")
82 }
83 }
84 }
85
86 impl Cast<Option<bool>> for $T {
87 #[inline] fn cast(self) -> Option<bool> {
88 if self.is_none() {
89 None
90 } else {
91 Some(self.cast())
92 }
93 }
94 }
95
96 impl Cast<bool> for Option<$T> {
97 #[inline] fn cast(self) -> bool {
98 self.expect("can not cast None to bool").cast()
99 }
100 }
101
102 impl Cast<Option<bool>> for Option<$T> {
103 #[inline] fn cast(self) -> Option<bool> {
104 self.map(|v| v.cast())
105 }
106 }
107
108 impl Cast<$T> for bool {
109 #[inline] fn cast(self) -> $T { (self as u8).cast() }
110 }
111
112 impl Cast<Option<$T>> for bool {
113 #[inline] fn cast(self) -> Option<$T> { Some((self as u8).cast()) }
114 }
115
116 impl Cast<$T> for Option<bool> {
117 #[inline] fn cast(self) -> $T {
118 if let Some(v) = self {
119 v.cast()
120 } else {
121 <$T as IsNone>::none()
122 }
123 }
124 }
125
126 impl Cast<Option<$T>> for Option<bool> {
127 #[inline] fn cast(self) -> Option<$T> { self.map(Cast::cast) }
128 }
129
130 impl Cast<String> for $T {
132 #[inline] fn cast(self) -> String { self.to_string() }
133 }
134
135 impl Cast<String> for Option<$T> {
136 #[inline] fn cast(self) -> String {
137 self.map(|v| v.to_string()).unwrap_or("None".to_string())
138 }
139 }
140
141 #[cfg(feature="time")]
142 impl<U: TimeUnitTrait> Cast<DateTime<U>> for $T {
143 #[inline] fn cast(self) -> DateTime<U> { Cast::<i64>::cast(self).into() }
144 }
145
146 #[cfg(feature="time")]
147 impl Cast<TimeDelta> for $T {
148 #[inline] fn cast(self) -> TimeDelta { Cast::<i64>::cast(self).into() }
149 }
150
151 #[cfg(feature="time")]
152 impl Cast<Time> for $T {
153 #[inline] fn cast(self) -> Time { Cast::<i64>::cast(self).into() }
154 }
155
156
157 #[cfg(feature="time")]
158 impl<U: TimeUnitTrait> Cast<DateTime<U>> for Option<$T> {
159 #[inline] fn cast(self) -> DateTime<U> { self.map(|v| v.cast()).unwrap_or(DateTime::nat()) }
160 }
161
162 #[cfg(feature="time")]
163 impl Cast<TimeDelta> for Option<$T> {
164 #[inline] fn cast(self) -> TimeDelta { self.map(|v| v.cast()).unwrap_or(TimeDelta::nat()) }
165 }
166
167 #[cfg(feature="time")]
168 impl Cast<Time> for Option<$T> {
169 #[inline] fn cast(self) -> Time { self.map(|v| v.cast()).unwrap_or(Time::nat()) }
170 }
171 };
172
173 ($T: ty => { $( $U: ty ),* } ) => {
174 impl Cast<$T> for Option<$T> {
175 #[inline(always)]
176 fn cast(self) -> $T {
177 self.unwrap_or_else(<$T as IsNone>::none)
178 }
179 }
180 impl_numeric_cast!(@common_impl $T => { $( $U ),* });
181 impl_numeric_cast!(@ $T => { $( $U),* });
182 };
183
184 (nocommon $T: ty => { $( $U: ty ),* } ) => {
185 impl_numeric_cast!(@ $T => { $( $U),* });
186 };
187}
188
189impl Cast<String> for bool {
190 #[inline]
191 fn cast(self) -> String {
192 self.to_string()
193 }
194}
195
196impl Cast<bool> for Option<bool> {
197 #[inline]
198 fn cast(self) -> bool {
199 if let Some(v) = self {
200 v
201 } else {
202 panic!("Should not cast None to bool")
203 }
204 }
205}
206
207#[cfg(feature = "time")]
208impl<U: TimeUnitTrait> Cast<DateTime<U>> for bool {
209 #[inline]
210 fn cast(self) -> DateTime<U> {
211 panic!("Should not cast bool to datetime")
212 }
213}
214
215#[cfg(feature = "time")]
216impl Cast<TimeDelta> for bool {
217 #[inline]
218 fn cast(self) -> TimeDelta {
219 panic!("Should not cast bool to timedelta")
220 }
221}
222
223#[cfg(feature = "time")]
224impl Cast<Time> for bool {
225 #[inline]
226 fn cast(self) -> Time {
227 panic!("Should not cast bool to time")
228 }
229}
230
231impl Cast<String> for Option<bool> {
232 #[inline]
233 fn cast(self) -> String {
234 format!("{:?}", self)
235 }
236}
237
238#[cfg(feature = "time")]
239impl<U: TimeUnitTrait> Cast<DateTime<U>> for Option<bool> {
240 #[inline]
241 fn cast(self) -> DateTime<U> {
242 panic!("Should not cast option bool to datetime")
243 }
244}
245
246#[cfg(feature = "time")]
247impl Cast<TimeDelta> for Option<bool> {
248 #[inline]
249 fn cast(self) -> TimeDelta {
250 panic!("Should not cast option bool to timedelta")
251 }
252}
253
254#[cfg(feature = "time")]
255impl Cast<Time> for Option<bool> {
256 #[inline]
257 fn cast(self) -> Time {
258 panic!("Should not cast option bool to time")
259 }
260}
261
262#[cfg(feature = "time")]
263macro_rules! impl_time_cast {
264 ($($T: ty),*) => {
265 $(
266 impl<U: TimeUnitTrait> Cast<$T> for DateTime<U> {
267 #[inline] fn cast(self) -> $T { Cast::<i64>::cast(self).cast() }
268 }
269
270 impl<U: TimeUnitTrait> Cast<Option<$T>> for DateTime<U> {
271 #[inline] fn cast(self) -> Option<$T> {
272 if self.is_none() {
273 None
274 } else {
275 Some(self.cast())
276 }
277 }
278 }
279
280
281 impl Cast<$T> for TimeDelta {
282 #[inline] fn cast(self) -> $T { Cast::<i64>::cast(self).cast() }
283 }
284
285 impl Cast<Option<$T>> for TimeDelta {
286 #[inline] fn cast(self) -> Option<$T> {
287 if self.is_none() {
288 None
289 } else {
290 Some(self.cast())
291 }
292 }
293 }
294
295 impl Cast<$T> for Time {
296 #[inline] fn cast(self) -> $T { Cast::<i64>::cast(self).cast() }
297 }
298
299 impl Cast<Option<$T>> for Time {
300 #[inline] fn cast(self) -> Option<$T> {
301 if self.is_none() {
302 None
303 } else {
304 Some(self.cast())
305 }
306 }
307 }
308 )*
309 };
310}
311
312#[cfg(feature = "time")]
313impl<U: TimeUnitTrait> Cast<i64> for DateTime<U> {
314 #[inline(always)]
315 fn cast(self) -> i64 {
316 self.into_i64()
317 }
318}
319
320#[cfg(feature = "time")]
321impl<U: TimeUnitTrait> Cast<Option<i64>> for DateTime<U> {
322 #[inline(always)]
323 fn cast(self) -> Option<i64> {
324 self.into_opt_i64()
325 }
326}
327
328#[cfg(feature = "time")]
329impl Cast<i64> for TimeDelta {
330 #[inline]
331 fn cast(self) -> i64 {
332 let months = self.months;
333 if months != 0 {
334 panic!("not support cast TimeDelta to i64 when months is not zero")
335 } else {
336 self.inner.num_microseconds().unwrap_or(i64::MIN)
337 }
338 }
339}
340
341#[cfg(feature = "time")]
342impl Cast<Option<i64>> for TimeDelta {
343 #[inline]
344 fn cast(self) -> Option<i64> {
345 let months = self.months;
346 if months != 0 {
347 panic!("not support cast TimeDelta to i64 when months is not zero")
348 } else {
349 self.inner.num_microseconds().map(Some).unwrap_or(None)
350 }
351 }
352}
353
354#[cfg(feature = "time")]
355impl Cast<i64> for Time {
356 #[inline]
357 fn cast(self) -> i64 {
358 self.0
359 }
360}
361
362#[cfg(feature = "time")]
363impl Cast<Option<i64>> for Time {
364 #[inline]
365 fn cast(self) -> Option<i64> {
366 if self.is_none() { None } else { Some(self.0) }
367 }
368}
369
370impl_numeric_cast!(u8 => { u64, f32, f64, i32, i64, usize, isize });
371impl_numeric_cast!(u64 => { u8, f32, f64, i32, i64, usize, isize });
372impl_numeric_cast!(i64 => { u8, f32, f64, i32, u64, usize, isize });
373impl_numeric_cast!(i32 => { u8, f32, f64, i64, u64, usize, isize });
374impl_numeric_cast!(f32 => { u8, f64, i32, i64, u64, usize, isize });
375impl_numeric_cast!(f64 => { u8, f32, i32, i64, u64, usize, isize });
376impl_numeric_cast!(usize => { u8, f32, f64, i32, i64, u64, isize });
377impl_numeric_cast!(isize => { u8, f32, f64, i32, i64, u64, usize });
378#[cfg(feature = "time")]
382impl_time_cast!(u8, u64, f32, f64, i32, usize, isize, bool);
383
384macro_rules! impl_cast_from_string {
385 ($($T: ty),*) => {
386 $(
387 impl Cast<$T> for String {
388 #[inline] fn cast(self) -> $T { self.parse().expect("Parse string error") }
389 }
390
391 impl Cast<$T> for &str {
392 #[inline] fn cast(self) -> $T { self.parse().expect("Parse string error") }
393 }
394
395 impl Cast<Option<$T>> for String {
396 #[inline]
397 fn cast(self) -> Option<$T> {
398 if self == "None" {
399 None
400 } else {
401 Some(self.cast())
402 }
403 }
404 }
405
406 impl Cast<Option<$T>> for &str {
407 #[inline]
408 fn cast(self) -> Option<$T> {
409 if self == "None" {
410 None
411 } else {
412 Some(self.cast())
413 }
414 }
415 }
416 )*
417 };
418}
419
420impl_cast_from_string!(
421 u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64, char, bool
422);
423
424impl Cast<String> for &str {
425 #[inline]
426 fn cast(self) -> String {
427 self.to_string()
428 }
429}
430
431#[cfg(feature = "time")]
432impl<U: TimeUnitTrait> Cast<String> for DateTime<U>
433where
434 CrDateTime<Utc>: From<DateTime<U>>,
435{
436 fn cast(self) -> String {
437 format!("{:?}", self)
438 }
439}
440
441#[cfg(feature = "time")]
442impl<U: TimeUnitTrait> Cast<DateTime<U>> for String
443where
444 DateTime<U>: From<CrDateTime<Utc>>,
445{
446 #[inline]
447 fn cast(self) -> DateTime<U> {
448 self.parse().expect("Parse string to datetime error")
449 }
450}
451
452#[cfg(feature = "time")]
453impl<U: TimeUnitTrait> Cast<DateTime<U>> for &str
454where
455 DateTime<U>: From<CrDateTime<Utc>>,
456{
457 #[inline]
458 fn cast(self) -> DateTime<U> {
459 self.parse().expect("Parse str to datetime error")
460 }
461}
462
463#[cfg(feature = "time")]
464impl Cast<String> for TimeDelta {
465 #[inline]
466 fn cast(self) -> String {
467 format!("{:?}", self)
468 }
469}
470
471#[cfg(feature = "time")]
472impl<U: TimeUnitTrait> Cast<TimeDelta> for DateTime<U> {
473 #[inline(always)]
474 fn cast(self) -> TimeDelta {
475 unreachable!()
476 }
477}
478
479#[cfg(feature = "time")]
480impl<U: TimeUnitTrait> Cast<DateTime<U>> for TimeDelta {
481 #[inline(always)]
482 fn cast(self) -> DateTime<U> {
483 unreachable!()
484 }
485}
486
487#[cfg(feature = "time")]
488impl Cast<TimeDelta> for &str {
489 #[inline(always)]
490 fn cast(self) -> TimeDelta {
491 TimeDelta::parse(self).expect("Parse str to timedelta error")
492 }
493}
494
495#[cfg(feature = "time")]
496impl Cast<TimeDelta> for String {
497 #[inline(always)]
498 fn cast(self) -> TimeDelta {
499 TimeDelta::parse(&self).expect("Parse string to timedelta error")
500 }
501}
502
503#[cfg(feature = "time")]
504macro_rules! time_unit_cast {
508 ($($unit: ident => ($($to_unit: ident),*)),*) => {
509 $($(impl Cast<DateTime<unit::$to_unit>> for DateTime<unit::$unit> {
510 #[inline(always)]
511 fn cast(self) -> DateTime<unit::$to_unit> {
512 self.into_unit::<unit::$to_unit>()
513 }
514 })*)*
515 };
523}
524
525#[cfg(feature = "time")]
526time_unit_cast!(
528 Millisecond => (Microsecond, Second, Nanosecond),
529 Microsecond => (Millisecond, Second, Nanosecond),
530 Second => (Millisecond, Microsecond, Nanosecond),
531 Nanosecond => (Millisecond, Microsecond, Second)
532);
533
534#[cfg(test)]
535mod tests {
536 use super::*;
537 #[test]
538 fn test_option_cast() {
539 let a = Some(1_usize);
540 let a: i32 = a.cast();
541 assert_eq!(a, 1);
542
543 let b: Option<usize> = None;
544 let b: f64 = b.cast();
545 assert!(b.is_nan());
546
547 let c: Option<usize> = Some(3);
548 let c: usize = c.cast();
549 assert_eq!(c, 3);
550
551 let d = Some(1usize);
552 let d: bool = d.cast();
553 assert!(d);
554
555 let e = Some(2i32);
556 let e: Option<f64> = e.cast();
557 assert_eq!(e, Some(2.0));
558 }
559}