]> piware.de Git - learn-rust.git/blobdiff - src/lib.rs
Call Rust function from C: Skeleton
[learn-rust.git] / src / lib.rs
index b9ee526f5eeabddfa09e377c639fa41c88ef764c..b7e5eb8f1df11116f8d94fd31fb1afe29491d087 100644 (file)
@@ -1,5 +1,6 @@
 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();
@@ -48,3 +49,62 @@ pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
         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
+        }
+    }
+}