How to do it...

  1. In the bin folder, create a file called conversion.rs.

  2. Add the following code and run it with cargo run --bin conversion:

1    use std::ops::MulAssign; 
2 use std::fmt::Display;
3
4 // This structure doubles all elements it stores
5 #[derive(Debug)]
6 struct DoubleVec<T>(Vec<T>);
7
8
9 // Allowing conversion from a Vec<T>,
10 // where T is multipliable with an integer
11 impl<T> From<Vec<T>> for DoubleVec<T>
12 where
13 T: MulAssign<i32>,
14 {
15 fn from(mut vec: Vec<T>) -> Self {
16 for elem in &mut vec {
17 *elem *= 2;
18 }
19 DoubleVec(vec)
20 }
21 }
22
23 // Allowing conversion from a slice of Ts
24 // where T is again multipliable with an integer
25 impl<'a, T> From<&'a [T]> for DoubleVec<T>
26 where
27 T: MulAssign<i32> + Clone,
28 {
29 fn from(slice: &[T]) -> Self {
30 // Vec<T: MulAssign<i32>> automatically
31 // implements Into<DoubleVec<T>>
32 slice.to_vec().into()
33 }
34 }
35
36 // Allowing conversion from a &DoubleVec<T> to a &Vec<T>
37 impl<T> AsRef<Vec<T>> for DoubleVec<T> {
38 fn as_ref(&self) -> &Vec<T> {
39 &self.0
40 }
41 }
42
43
44 fn main() {
45 // The following three are equivalent
46 let hello_world = "Hello World".to_string();
47 let hello_world: String = "Hello World!".into();
48 let hello_world = String::from("Hello World!");
49
50 // Vec<u8> implements From<&str>
51 // so hello_world_bytes has the value b"Hello World!"
52 let hello_world_bytes: Vec<u8> = "Hello World!".into();
53 let hello_world_bytes = Vec::<u8>::from("Hello World!");
54
55 // We can convert a Vec<T: MulAssign<i32>> into a DoubleVec
56 let vec = vec![1, 2, 3];
57 let double_vec = DoubleVec::from(vec);
58 println!("Creating a DoubleVec from a Vec: {:?}",
double_vec);
59
60 // Vec<T: MulAssign<i32>> automatically implements
Into<DoubleVec<T>>
61 let vec = vec![1, 2, 3];
62 let double_vec: DoubleVec<_> = vec.into();
63 println!("Converting a Vec into a DoubleVec: {:?}",
double_vec);
64
65 // A reference to DoubleVec can be converted to a reference
to Vec
66 // Which in turn dereferences to a slice
67 print_elements(double_vec.as_ref());
68
69 // The standard library provides From<T> for Option<T>
70 // You can design your API in an ergonomic way thanks to this
71 easy_public_func(Some(1337), Some(123), None);
72 ergonomic_public_func(1337, 123, None);
73 }
74
75
76 fn print_elements<T>(slice: &[T])
77 where
78 T: Display,
79 {
80 for elem in slice {
81 print!("{} ", elem);
82 }
83 println!();
84 }
85
86
87 // Easily written but cumbersome to use
88 fn easy_public_func(foo: Option<i32>, bar: Option<i32>, baz:
Option<i32>) {
89 println!(
90 "easy_public_func = foo: {:?}, bar: {:?}, baz: {:?}",
91 foo,
92 bar,
93 baz
94 );
95 }
96
97
98 // This is quite some extra typing, so it's only worth to do
for
99 // public functions with many optional parameters
100 fn ergonomic_public_func<Foo, Bar, Baz>(foo: Foo, bar: Bar,
baz: Baz)
101 where
102 Foo: Into<Option<i32>>,
103 Bar: Into<Option<i32>>,
104 Baz: Into<Option<i32>>,
105 {
106 let foo: Option<i32> = foo.into();
107 let bar: Option<i32> = bar.into();
108 let baz: Option<i32> = baz.into();
109
110 println!(
111 "ergonomic_public_func = foo: {:?}, bar: {:?}, baz: {:?}",
112 foo,
113 bar,
114 baz
115 );
116 }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.183.210