1 use std::collections::HashMap;
3 use std::io::prelude::*;
5 pub fn read_file(path: &str) -> Result<String, std::io::Error> {
6 let mut s = String::new();
7 File::open(path)?.read_to_string(&mut s)?;
11 // needs Copy trait, good for simple types
12 pub fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
13 let mut result = list[0];
22 // expensive for large strings, don't use that
23 pub fn largest_clone<T: PartialOrd + Clone>(list: &[T]) -> T {
24 let mut result = list[0].clone();
33 // good for everything, but more expensive for simple types
34 pub fn largest_ref<T: PartialOrd>(list: &[T]) -> &T {
35 let mut result = &list[0];
44 pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
45 if x.len() > y.len() {
52 /// Wrap and cache an expensive calculation
54 /// This calls a closure just once for every distinct argument. Any subsequent
55 /// call to `.value()` with the same argument uses the cached value.
56 pub struct Cacher<T, A, V>
59 A: Eq + Copy + std::hash::Hash,
63 values: HashMap<A, V>,
66 impl<T, A, V> Cacher<T, A, V>
69 A: Eq + Copy + std::hash::Hash,
72 pub fn new(calc: T) -> Cacher<T, A, V> {
75 values: HashMap::new(),
79 pub fn value(&mut self, arg: A) -> V {
80 match self.values.get(&arg) {
83 let v = (self.calc)(arg);
84 self.values.insert(arg, v);
96 pub fn new() -> Counter5 {
101 impl Iterator for Counter5 {
104 fn next(&mut self) -> Option<Self::Item> {
115 state: Box<dyn State>,
120 pub fn new() -> Post {
122 state: Box::new(Draft {}),
123 content: String::new(),
127 pub fn add_text(&mut self, text: &str) {
128 self.content.push_str(text);
131 pub fn content(&self) -> &str {
132 self.state.content(self)
135 pub fn request_review(&mut self) {
136 self.state = self.state.request_review();
139 pub fn approve(&mut self) {
140 self.state = self.state.approve();
143 pub fn reject(&mut self) {
144 self.state = self.state.reject();
149 fn request_review(&self) -> Box<dyn State>;
150 fn approve(&mut self) -> Box<dyn State>;
151 fn reject(&self) -> Box<dyn State>;
153 #[allow(unused_variables)]
154 fn content<'a>(&self, post: &'a Post) -> &'a str {
160 impl State for Draft {
161 fn request_review(&self) -> Box<dyn State> {
162 Box::new(PendingReview { acks: 0 })
165 fn approve(&mut self) -> Box<dyn State> {
166 // don't change state
170 fn reject(&self) -> Box<dyn State> {
175 struct PendingReview {
179 impl State for PendingReview {
180 fn request_review(&self) -> Box<dyn State> {
181 Box::new(Self { acks: self.acks })
184 fn approve(&mut self) -> Box<dyn State> {
186 Box::new(Published {})
194 fn reject(&self) -> Box<dyn State> {
200 impl State for Published {
201 fn request_review(&self) -> Box<dyn State> {
205 fn approve(&mut self) -> Box<dyn State> {
206 Box::new(Published {})
209 fn reject(&self) -> Box<dyn State> {
213 fn content<'a>(&self, post: &'a Post) -> &'a str {
218 // state encoded as types; this is the "approved" state
224 pub fn new() -> TPostDraft {
226 content: String::new(),
230 pub fn content(&self) -> &str {
235 pub struct TPostDraft {
240 pub fn add_text(&mut self, text: &str) {
241 self.content.push_str(text);
244 pub fn request_review(self) -> TPostReview {
246 content: self.content,
251 pub struct TPostReview {
256 pub fn approve(self) -> TPost {
258 content: self.content,
262 pub fn reject(self) -> TPostDraft {
264 content: self.content,