std_reset/traits/of_to/mod.rs
1//! Трейты для преобразования типов.
2//!
3//! Трейты [`Of`]/[`To`] являются заменой [`From`]/[`Into`] из стандартной библиотеки и имеют более функциональный вид.
4//!
5//! Данная реализация [`From`]/[`Into`] может быть полензна, когда мы хотим сохранить функциональный стиль, при том что у нашего типа есть множество реализаций трейта [`From`].
6//!
7//! # Стандартная реализация с [`From`]/[`Into`]
8//! Когда у типа `TypeInto` появляется более одной реализации типажа [`From`], нам необходимо указать компилятору, какую из реализаций мы используем в данный момент.
9//! В стандартной реализации [`From`]/[`Into`] это можно сделать с помощью следующих конструкций:
10//! - `<TypeFrom as Into<TypeInto>>::`
11//! - `Into::<TypeInto>>::`
12//! , где `TypeFrom` - тип, который укзан в реализации как `impl From<TypeFrom> for TypeInto`.
13//!
14//! ## Пример
15//! ```
16//! struct Rubles;
17//! struct Euros;
18//! struct Dollars;
19//!
20//! impl From<Rubles> for Dollars {
21//! fn from(value: Rubles) -> Self {
22//! Dollars
23//! }
24//! }
25//!
26//! impl From<Euros> for Dollars {
27//! fn from(value: Euros) -> Self {
28//! Dollars
29//! }
30//! }
31//!
32//! fn from_into() {
33//! let dollars = <Euros as Into<Dollars>>::into(Euros);
34//! let dollars = Into::<Dollars>::into(Euros);
35//! }
36//! ```
37//!
38//! # Реализацис c [`Of`]/[`To`]
39//!
40//! Для того чтобы указать компилятору сигнатуру опрделеной реализации трейта, мы можем указать границы не только для самого трейта (высокий уровень), но и для функций этого трейта (низкий уровень).
41//! Так в трейте [`To`], generic типа, в который мы выполняем преобразование, указывается для метода `to`.
42//! Теперь, чтобы указать конкртеную реализацию, нам достаточно конретизировать метод трейта:
43//! - `TypeFrom.to::<TypeInto>()`
44//!
45//! ## Пример
46//! ```
47//! # use std_reset::prelude::{Of, To};
48//! #
49//! # struct Rubles;
50//! # struct Euros;
51//! # struct Dollars;
52//! #
53//! impl Of<Rubles> for Dollars {
54//! fn of(value: Rubles) -> Self {
55//! Dollars
56//! }
57//! }
58//!
59//! impl Of<Euros> for Dollars {
60//! fn of(value: Euros) -> Self {
61//! Dollars
62//! }
63//! }
64//!
65//! fn of_to() {
66//! let dollars = Rubles.to::<Dollars>();
67//! let dollars = Euros.to::<Dollars>();
68//! }
69//! ```
70pub trait Of<F, Output = Self>: To {
71 fn of(value: F) -> Output;
72}
73
74pub trait To {
75 fn to<I: Of<Self>>(self) -> I
76 where
77 Self: Sized;
78}
79
80impl<F> To for F {
81 fn to<I: Of<F>>(self) -> I {
82 I::of(self)
83 }
84}
85
86
87impl<F, I> Of<Vec<F>> for Vec<I>
88where
89 I: Of<F>,
90{
91 fn of(vec: Vec<F>) -> Self {
92 vec.into_iter().map(I::of).collect()
93 }
94}
95
96impl<F: Clone, I> Of<&Vec<F>> for Vec<I>
97where
98 I: Of<F>,
99{
100 fn of(vec: &Vec<F>) -> Self {
101 vec.into_iter().cloned().map(I::of).collect()
102 }
103}