X-Git-Url: https://piware.de/gitweb/?p=learn-rust.git;a=blobdiff_plain;f=src%2Flib.rs;h=fe3b71b286640b29919d465a9fd25f55a002b42b;hp=b9ee526f5eeabddfa09e377c639fa41c88ef764c;hb=b6a408eb8944df04d6c6e876a9a00f6c425f47f1;hpb=cf414916b6551e102ebf120866ef461d47c535bd diff --git a/src/lib.rs b/src/lib.rs index b9ee526..fe3b71b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ use std::fs::File; use std::io::prelude::*; +use std::collections::HashMap; pub fn read_file(path: &str) -> Result { let mut s = String::new(); @@ -48,3 +49,39 @@ 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 +where + T: Fn(A) -> V, + A: Eq + Copy + std::hash::Hash, + V: Copy, +{ + calc: T, + values: HashMap, +} + +impl Cacher +where + T: Fn(A) -> V, + A: Eq + Copy + std::hash::Hash, + V: Copy, +{ + pub fn new(calc: T) -> Cacher { + 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 + } + } + } +}