]> piware.de Git - learn-rust.git/blob - concepts/src/main.rs
concepts: rustfmt
[learn-rust.git] / concepts / src / main.rs
1 mod lib;
2 mod word_utils;
3
4 use std::collections::HashMap;
5 use std::fs::{self, File};
6 use std::io::{prelude::*, ErrorKind};
7 use std::{sync, thread, time};
8
9 use lib::*;
10 use word_utils::{first_word, second_word};
11
12 fn test_strings() {
13     let s = String::from("Hello world");
14     println!("first word: '{}'", first_word(&s));
15     println!("second word: '{}'", second_word(&s).unwrap());
16
17     let s2 = "hello dude blah";
18     println!(
19         "second word of single: '{}'",
20         second_word(s2).unwrap_or("(none)")
21     );
22
23     match second_word(s2) {
24         Some(w) => println!("match: second word of '{}' exists: {}", s2, w),
25         None => println!("match: second word of '{}' does not exist", s2),
26     }
27 }
28
29 fn test_vectors() {
30     let v1 = vec![1, 2, 3];
31     println!("statically initialized vector: {:?}", v1);
32
33     let mut v2: Vec<String> = Vec::new();
34     v2.push("Hello".to_string());
35     v2.push(String::from("world"));
36     println!("dynamically built vector: {:?}", v2);
37     println!("first element: {}", v2[0]);
38     for el in &mut v2 {
39         *el += "xx";
40     }
41     for el in &v2 {
42         println!("{}", el);
43     }
44 }
45
46 fn test_hashmaps() {
47     let mut scores = HashMap::new();
48     scores.insert("john", 10);
49     scores.insert("mary", 20);
50
51     println!("scores: {:?}", scores);
52
53     // hash map with .collect()
54     let persons = vec![("homer", 42), ("marge", 30)];
55     let collect_scores: HashMap<_, _> = persons.into_iter().collect();
56     println!("collect_scores: {:?}", collect_scores);
57
58     for (p, s) in &collect_scores {
59         println!("person {}: score {}", p, s);
60     }
61
62     println!("john's score: {}", scores.get("john").unwrap());
63     println!("jake's score: {}", scores.get("jake").unwrap_or(&-1));
64
65     // double scores
66     for (_, v) in scores.iter_mut() {
67         *v *= 2;
68     }
69     println!("scores after doubling: {:?}", scores);
70
71     // double scores of immutable hashmap (rebuild it)
72     let collect_scores: HashMap<_, _> = collect_scores
73         .into_iter()
74         .map(|(k, v)| (k, 2 * v))
75         .collect();
76     println!(
77         "collect_scores after rebuilding with doubling: {:?}",
78         collect_scores
79     );
80 }
81
82 fn test_files() {
83     if let Ok(mut f) = File::open("Cargo.toml") {
84         let mut contents = String::new();
85         match f.read_to_string(&mut contents) {
86             Ok(len) => println!(
87                 "successfully opened Cargo.toml: {:?}, contents {} bytes:\n{}\n----------",
88                 f, len, contents
89             ),
90             Err(e) => panic!("could not read file: {:?}", e),
91         }
92     } else {
93         println!("could not open Cargo.toml");
94     }
95
96     // alternative form, more specific error checking
97     let mut f = File::open("Cargo.toml").unwrap_or_else(|e| {
98         if e.kind() == ErrorKind::NotFound {
99             println!("Cargo.toml not found, falling back to /dev/null");
100             // need to return a File
101             File::open("/dev/null").unwrap()
102         } else {
103             panic!("Could not open Cargo.toml: {:?}", e);
104         }
105     });
106     let mut contents = String::new();
107     let len = f.read_to_string(&mut contents).unwrap_or_else(|e| {
108         panic!("Could not read file: {:?}", e);
109     });
110     println!("successfully opened Cargo.toml with unwrap_or_else: {:?}, contents {} bytes:\n{}\n----------", f, len, contents);
111
112     // using the '?' operator
113     match read_file("Cargo.toml") {
114         Ok(s) => println!("Cargo.toml contents:\n{}\n-------------", s),
115         Err(e) => println!("Could not open Cargo.toml: {:?}", e),
116     }
117
118     // using std API
119     match fs::read_to_string("Cargo.toml") {
120         Ok(s) => println!("Cargo.toml contents:\n{}\n-------------", s),
121         Err(e) => println!("Could not open Cargo.toml: {:?}", e),
122     }
123 }
124
125 fn test_generics() {
126     let num_list = vec![3, 42, -7, 100, 0];
127     println!("largest number: {}", largest(&num_list));
128     println!("num_list: {:?}", num_list);
129
130     let char_list = vec!['a', 'y', 'q', 'm'];
131     println!("largest char: {}", largest(&char_list));
132
133     let str_list = vec!["hello", "world", "blue", "planet"];
134     println!("largest str: {}", largest(&str_list));
135     println!("str_list: {:?}", str_list);
136
137     let string_list = vec!["aaaa".to_string(), "xxxxx".to_string(), "ffff".to_string()];
138     println!(
139         "largest string (with cloning): {}",
140         largest_clone(&string_list)
141     );
142     println!("largest string (with ref): {}", largest_ref(&string_list));
143     println!("string_list: {:?}", string_list);
144
145     let s1 = String::from("abcd");
146     let l;
147     {
148         let s2 = "efghi";
149         l = longest(&s1, s2);
150     }
151     println!("longest string: {}", l);
152 }
153
154 fn test_closures() {
155     let mut expensive_int_result = Cacher::new(|x| {
156         println!("calculating expensive int result for {}", x);
157         2 * x
158     });
159
160     println!(
161         "1st int call for value 1: {}",
162         expensive_int_result.value(1)
163     );
164     println!(
165         "2nd int call for value 1: {}",
166         expensive_int_result.value(1)
167     );
168     println!(
169         "1st int call for value 2: {}",
170         expensive_int_result.value(2)
171     );
172
173     let mut expensive_str_result = Cacher::new(|x: &str| {
174         println!("calculating expensive str result for {}", x);
175         x.len()
176     });
177
178     println!(
179         "1st int call for value abc: {}",
180         expensive_str_result.value("abc")
181     );
182     println!(
183         "2nd int call for value abc: {}",
184         expensive_str_result.value("abc")
185     );
186     println!(
187         "1st int call for value defg: {}",
188         expensive_str_result.value("defg")
189     );
190 }
191
192 fn test_iterators() {
193     let v1 = vec!["Hello", "good", "world"];
194     // implied default is .into_iter() which consumes v1
195     for s in v1.iter() {
196         println!("element: {}", s);
197     }
198     // can still use it now
199     println!("v1: {:?}", &v1);
200
201     // manual iteration
202     let mut v1_iter = v1.iter();
203     while let Some(e) = v1_iter.next() {
204         println!("while loop over iter: {}", e);
205     }
206
207     for l_element in v1.iter().filter(|x| x.contains('l')) {
208         println!("v1 element containing 'l': {}", l_element);
209     }
210
211     let v2 = vec![1, 2, 3];
212     let double_v2: Vec<_> = v2.iter().map(|x| x * 2).collect();
213     println!("doubled v2: {:?}", double_v2);
214
215     for i in v2.into_iter().map(|x| x * 3) {
216         println!("for loop triplicating v2: {}", i);
217     }
218
219     for i in Counter5::new() {
220         println!("Counter 5 value: {}", i);
221     }
222 }
223
224 fn test_threads() {
225     let t1 = thread::spawn(|| {
226         for i in 0..10 {
227             println!("hello #{} from thread", i);
228             thread::sleep(time::Duration::from_millis(1));
229         }
230     });
231
232     for i in 1..5 {
233         println!("hello #{} from main", i);
234         thread::sleep(time::Duration::from_millis(1));
235     }
236
237     t1.join().unwrap();
238
239     // message passing
240     let (tx1, rx) = sync::mpsc::channel();
241     let tx2 = tx1.clone();
242
243     let sender1 = thread::spawn(move || {
244         for s in ["hey", "from", "sender", "one"] {
245             tx1.send(s).expect("failed to send");
246             thread::sleep(time::Duration::from_millis(100));
247         }
248     });
249
250     let sender2 = thread::spawn(move || {
251         for s in ["Servus", "von", "Produzent", "zwei"] {
252             tx2.send(s).expect("failed to send");
253             thread::sleep(time::Duration::from_millis(100));
254         }
255     });
256
257     for received in rx {
258         println!("received {} from mpsc", received);
259     }
260
261     sender1.join().unwrap();
262     sender2.join().unwrap();
263
264     // shared state
265     let counter = sync::Arc::new(sync::Mutex::new(0));
266     let mut threads = vec![];
267     for _ in 0..10 {
268         let tc = sync::Arc::clone(&counter);
269         threads.push(thread::spawn(move || {
270             *tc.lock().unwrap() += 1;
271         }));
272     }
273
274     for t in threads {
275         t.join().unwrap();
276     }
277
278     println!("counter: {}", *counter.lock().unwrap());
279 }
280
281 fn test_dyn_traits() {
282     let text = "I ate a salad for lunch today";
283     let mut post = Post::new();
284     post.add_text(text);
285     assert_eq!("", post.content());
286
287     post.request_review();
288     assert_eq!("", post.content());
289
290     post.reject();
291     assert_eq!("", post.content());
292
293     post.request_review();
294     assert_eq!("", post.content());
295
296     post.approve(); // first
297     assert_eq!("", post.content());
298
299     post.approve(); // second
300     assert_eq!(text, post.content());
301
302     post.reject(); // no-op
303     assert_eq!(text, post.content());
304 }
305
306 fn test_state_types() {
307     let mut post = TPost::new();
308     post.add_text("I ate a salad for lunch");
309     let post = post.request_review();
310     let mut post = post.reject();
311     post.add_text(" today");
312     let post = post.request_review();
313     let post = post.approve();
314     assert_eq!(post.content(), "I ate a salad for lunch today");
315 }
316
317 fn main() {
318     test_strings();
319     test_vectors();
320     test_hashmaps();
321     test_files();
322     test_generics();
323     test_closures();
324     test_iterators();
325     test_threads();
326     test_dyn_traits();
327     test_state_types();
328 }