108 lines
2.1 KiB
Rust
108 lines
2.1 KiB
Rust
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 reject(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
|
|
}
|
|
|
|
fn reject(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 {})
|
|
}
|
|
|
|
fn reject(self: Box<Self>) -> Box<dyn State> {
|
|
Box::new(Draft {})
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
fn reject(self: Box<Self>) -> Box<dyn State> {
|
|
self
|
|
}
|
|
}
|
|
|
|
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());
|
|
}
|