Skip to content

Instantly share code, notes, and snippets.

@mt-inside
Created February 11, 2019 21:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mt-inside/41e6ad0f63e983dde96e1cd3c8ce3256 to your computer and use it in GitHub Desktop.
Save mt-inside/41e6ad0f63e983dde96e1cd3c8ce3256 to your computer and use it in GitHub Desktop.
fn main() {
let mut post = Post::new();
post.add_text("This is a draft tweet");
println!("printable content: {}", post.content());
post.request_review();
println!("printable content: {}", post.content());
post.approve();
println!("printable content: {}", post.content());
post.reject();
println!("printable content: {}", post.content());
println!("fixing");
post.add_text("This is a betterer");
println!("printable content: {}", post.content());
post.request_review();
println!("printable content: {}", post.content());
post.approve();
println!("printable content: {}", post.content());
post.approve();
println!("printable content: {}", post.content());
post.reject();
println!("printable content: {}", post.content());
}
struct Post {
state: Option<Box<dyn State>>,
content: String,
}
impl Post {
fn new() -> Self {
Post {
state: Some(Box::new(Draft {})),
content: String::new(),
}
}
fn add_text(&mut self, text: &str) {
self.state.as_ref().unwrap().add_text(self, text);
}
fn _add_text(&mut self, text: &str) {
self.content.push_str(text);
}
fn content(&self) -> &str {
self.state.as_ref().unwrap().content(&self)
}
fn request_review(&mut self) {
println!("requesting review");
if let Some(s) = self.state.take() {
self.state = Some(s.request_review())
}
}
fn reject(&mut self) {
println!("rejecting!");
if let Some(s) = self.state.take() {
self.state = Some(s.reject())
}
}
fn approve(&mut self) {
println!("approving");
if let Some(s) = self.state.take() {
self.state = Some(s.approve())
}
}
}
trait State {
fn content<'a>(&self, _post: &'a Post) -> &'a str {
""
}
fn add_text(&self, _post: &mut Post, _text: &str) -> () {
()
}
fn request_review(self: Box<Self>) -> Box<dyn State>;
fn reject(self: Box<Self>) -> Box<dyn State>;
fn approve(self: Box<Self>) -> Box<dyn State>;
}
struct Draft {}
impl State for Draft {
fn add_text(&self, post: &mut Post, text: &str) -> () {
post._add_text(text);
}
fn request_review(self: Box<Self>) -> Box<dyn State> {
Box::new(PendingReview::new())
}
fn reject(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
self
}
}
struct PendingReview {
approvals: usize,
}
impl PendingReview {
fn new() -> Self {
PendingReview { approvals: 0 }
}
}
impl State for PendingReview {
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn reject(self: Box<Self>) -> Box<dyn State> {
Box::new(Draft {})
}
fn approve(mut self: Box<Self>) -> Box<dyn State> {
self.approvals += 1;
if self.approvals >= 2 {
Box::new(Published {})
} else {
self
}
}
}
struct Published {}
impl State for Published {
fn content<'a>(&self, post: &'a Post) -> &'a str {
&post.content
}
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn reject(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
self
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment