diff --git a/.idea/misc.xml b/.idea/misc.xml
index 69ba99e..37d23de 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -34,6 +34,7 @@
+
diff --git a/.idea/rust.iml b/.idea/rust.iml
index 8f1c362..0da18db 100644
--- a/.idea/rust.iml
+++ b/.idea/rust.iml
@@ -137,9 +137,14 @@
+
+
+
+
+
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 3883477..1f70177 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -13,7 +13,48 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -193,7 +245,7 @@
-
+
@@ -212,6 +264,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -232,16 +294,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -271,11 +323,11 @@
+
-
@@ -313,9 +365,10 @@
+
-
-
+
+
@@ -323,7 +376,7 @@
-
+
@@ -331,7 +384,7 @@
-
+
@@ -345,24 +398,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -785,5 +820,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/blog/Cargo.toml b/blog/Cargo.toml
new file mode 100644
index 0000000..c299135
--- /dev/null
+++ b/blog/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "blog"
+version = "0.1.0"
+authors = ["Timothy Warren "]
+edition = "2018"
+
+[dependencies]
diff --git a/blog/src/lib.rs b/blog/src/lib.rs
new file mode 100644
index 0000000..87947cf
--- /dev/null
+++ b/blog/src/lib.rs
@@ -0,0 +1,81 @@
+pub struct Post {
+ state: Option>,
+ content: String,
+}
+
+impl Post {
+ pub fn new() -> Post {
+ Post {
+ state: Some(Box::new(Draft {})),
+ content: String::new(),
+ }
+ }
+
+ pub fn add_text(&mut self, text: &str) {
+ self.content.push_str(text);
+ }
+
+ pub fn content(&self) -> &str {
+ self.state.as_ref().unwrap().content(&self)
+ }
+
+ pub fn request_review(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.request_review())
+ }
+ }
+
+ pub fn approve(&mut self) {
+ if let Some(s) = self.state.take() {
+ self.state = Some(s.approve())
+ }
+ }
+}
+
+trait State {
+ fn request_review(self: Box) -> Box;
+ fn approve(self: Box) -> Box;
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ ""
+ }
+}
+
+struct Draft {}
+
+impl State for Draft {
+ fn request_review(self: Box) -> Box {
+ Box::new(PendingReview {})
+ }
+
+ fn approve(self: Box) -> Box {
+ self
+ }
+}
+
+struct PendingReview {}
+
+impl State for PendingReview {
+ fn request_review(self: Box) -> Box {
+ self
+ }
+
+ fn approve(self: Box) -> Box {
+ Box::new(Published {})
+ }
+}
+
+struct Published {}
+
+impl State for Published {
+ fn request_review(self: Box) -> Box {
+ self
+ }
+
+ fn approve(self: Box) -> Box {
+ self
+ }
+
+ fn content<'a>(&self, post: &'a Post) -> &'a str {
+ &post.content
+ }
+}
diff --git a/blog/src/main.rs b/blog/src/main.rs
new file mode 100644
index 0000000..14b4c08
--- /dev/null
+++ b/blog/src/main.rs
@@ -0,0 +1,14 @@
+use blog::Post;
+
+fn main() {
+ let mut post = Post::new();
+
+ post.add_text("I ate a salad for lunch today");
+ assert_eq!("", post.content());
+
+ post.request_review();
+ assert_eq!("", post.content());
+
+ post.approve();
+ assert_eq!("I ate a salad for lunch today", post.content());
+}