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}