std_reset/traits/as_prim/
mod.rs

1//! Перобразование примитивных числовых типов через метод трейта [`AsPrim`] (замена опреатора `as`).
2//!
3//! # Стандартная реализация с оператором `as`.
4//! Изначально rust предоставляет нам возможность преобразования примитивных типов с помощью опреатора `as`.
5//! В следующих примерах показано, как опреатор `as` может сбивать с толку из-за своей семнтики:
6//! ```
7//! use core::f64::consts::PI;
8//!
9//! let radius = 10_i32;
10//! let circle_area = 2 as f64 * PI * radius as f64;
11//! ```
12//! Даже скобки не спасают:
13//! ```
14//! # use core::f64::consts::PI;
15//! # let radius = 10_i32;
16//! let circle_area = (2 as f64) * PI * (radius as f64);
17//! ```
18//! # Реализация AsPrim
19//!
20//! Трейт [`AsPrim`] и вспомогательные ему [`FromPrim`] и [`ToPrim`] преднозначены для того, чтобы добиться функционального стиля в преобразовании примитивных типов без оператора `as`.
21//!
22//! ```
23//! # use std_reset::prelude::AsPrim;
24//! # use core::f64::consts::PI;
25//! # let radius = 10_i32;
26//! let circle_area = 2.as_::<f64>() * PI * radius.as_::<f64>();
27//! let vec: Vec<f32> = vec![2.as_(), circle_area.as_(), 4_isize.as_()];
28//! ```
29//!
30//! Также вы можете использовать [`FromPrim`], как будто используете [`From`]:
31//! ```
32//! # use std_reset::traits::as_prim::FromPrim;
33//! let num = f64::as_from(10_i32);
34//!
35//! ```
36//! Или  использовать [`ToPrim`] для преобразования напрямую:
37//! ```
38//! # use std_reset::traits::as_prim::ToPrim;
39//! let num = 2.to_f32();
40//! ```
41
42use paste::paste;
43
44macro_rules! every_type_method {
45     ($($t:ty),+) => {
46         $(
47             paste! {
48                 fn [<to_ $t>](self) -> $t {
49                     self as $t
50                 }
51             }
52         )+
53     };
54 }
55
56macro_rules! impl_for_every_num_types {
57     ($($t:ty),+) => {
58         pub trait ToPrim: ToString {
59             $(
60                 paste! {
61                     fn [<to_ $t>](self) -> $t;
62                 }
63             )+
64         }
65         $(
66             impl ToPrim for $t {
67                 every_type_method!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64);
68             }
69         )+
70         $(
71             impl FromPrim for $t {
72                 paste! {
73                     fn as_from<F: ToPrim>(value: F) -> $t {
74                         value.[<to_ $t>]()
75                     }
76                 }
77             }
78         )+
79     }
80 }
81
82impl_for_every_num_types!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64);
83pub trait FromPrim: ToPrim {
84    fn as_from<F: ToPrim>(value: F) -> Self;
85}
86
87pub trait AsPrim: FromPrim {
88    fn as_<I: FromPrim>(self) -> I;
89}
90
91impl<F: FromPrim> AsPrim for F {
92    fn as_<I: FromPrim>(self) -> I {
93        I::as_from::<F>(self)
94    }
95}