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