+++ /dev/null
-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
- }
- }
-}