]> piware.de Git - learn-rust.git/blobdiff - concepts/src/lib.rs
Move top-level files into concepts/
[learn-rust.git] / concepts / src / lib.rs
diff --git a/concepts/src/lib.rs b/concepts/src/lib.rs
new file mode 100644 (file)
index 0000000..b7e5eb8
--- /dev/null
@@ -0,0 +1,110 @@
+use std::fs::File;
+use std::io::prelude::*;
+use std::collections::HashMap;
+
+pub fn read_file(path: &str) -> Result<String, std::io::Error> {
+    let mut s = String::new();
+    File::open(path)?
+        .read_to_string(&mut s)?;
+    Ok(s)
+}
+
+// needs Copy trait, good for simple types
+pub fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
+    let mut result = list[0];
+    for &i in list {
+        if i > result {
+            result = i;
+        }
+    }
+    result
+}
+
+// expensive for large strings, don't use that
+pub fn largest_clone<T: PartialOrd + Clone>(list: &[T]) -> T {
+    let mut result = list[0].clone();
+    for i in list {
+        if *i > result {
+            result = i.clone();
+        }
+    }
+    result
+}
+
+// good for everything, but more expensive for simple types
+pub fn largest_ref<T: PartialOrd>(list: &[T]) -> &T {
+    let mut result = &list[0];
+    for i in list {
+        if i > result {
+            result = i;
+        }
+    }
+    result
+}
+
+pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+    if x.len() > y.len() {
+        x
+    } else {
+        y
+    }
+}
+
+/// Wrap and cache an expensive calculation
+///
+/// This calls a closure just once for every distinct argument. Any subsequent
+/// call to `.value()` with the same argument uses the cached value.
+pub struct Cacher<T, A, V>
+where
+    T: Fn(A) -> V,
+    A: Eq + Copy + std::hash::Hash,
+    V: Copy,
+{
+    calc: T,
+    values: HashMap<A, V>,
+}
+
+impl<T, A, V> Cacher<T, A, V>
+where
+    T: Fn(A) -> V,
+    A: Eq + Copy + std::hash::Hash,
+    V: Copy,
+{
+    pub fn new(calc: T) -> Cacher<T, A, V> {
+        Cacher { calc, values: HashMap::new() }
+    }
+
+    pub fn value(&mut self, arg: A) -> V {
+        match self.values.get(&arg) {
+            Some(v) => *v,
+            None => {
+                let v = (self.calc)(arg);
+                self.values.insert(arg, v);
+                v
+            }
+        }
+    }
+}
+
+pub struct Counter5 {
+    count: u32
+}
+
+impl Counter5 {
+    pub fn new() -> Counter5 {
+        Counter5 { count: 0 }
+    }
+}
+
+impl Iterator for Counter5 {
+    type Item = u32;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.count < 5 {
+            self.count += 1;
+            Some(self.count)
+        } else {
+            None
+        }
+    }
+}