Skip to content

Instantly share code, notes, and snippets.

@megaherz
Created October 13, 2022 08:15

Revisions

  1. megaherz created this gist Oct 13, 2022.
    95 changes: 95 additions & 0 deletions blog.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    mod blog {
    pub struct Post {
    state: Option<Box<dyn State>>,
    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<Self>) -> Box<dyn State>;
    fn approve(self: Box<Self>) -> Box<dyn State>;
    fn content<'a>(&self, post: &'a Post) -> &'a str {
    ""
    }
    }

    struct Draft {}

    impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
    Box::new(PendingReview {})
    }
    fn approve(self: Box<Self>) -> Box<dyn State> {
    self
    }
    }

    struct PendingReview {}

    impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
    self
    }
    fn approve(self: Box<Self>) -> Box<dyn State> {
    Box::new(Published {})
    }
    }

    struct Published {}

    impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
    self
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
    self
    }

    fn content<'a>(&self, post: &'a Post) -> &'a str {
    &post.content
    }
    }
    }

    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());
    }