These are chat archives for rust-lang/rust

13th
Aug 2017
stevensonmt
@stevensonmt
Aug 13 2017 20:10

So I am struggling a bit with the last section of chapter 17. Trying to accomplish the instructions

Only allow adding text content when a post is in the Draft state

My approach is to implement fn add_text for the State trait and define it such that only the Draft state can append text to the content string. I'm getting a lifetime error that I can't figure out how to fix. The error is cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements

Relevant code below:

pub struct Post {
    state: Option<Box<State>>,
    content: String,
}
    pub fn add_text(&mut self, text: &str) {
            // self.content.push_str(text);
        if let Some(s) = self.state.take() {
            let ref c = self.content;
            self.content = String::from(Some(s.add_text(c, text)).unwrap())
        }
    }
trait State {
    fn add_text(&mut self, c: &String, text: &str) -> &str;
}

struct Draft {}

impl State for Draft {
    fn add_text(&mut self, c: &String, text: &str) -> &str {
        c.push_str(text);
        c
    }
}
and fn add_text for all other states simply returns c without appending anything.
Suggestions?
Denis Lisov
@tanriol
Aug 13 2017 20:17
Why does add_text return the text at all?
stevensonmt
@stevensonmt
Aug 13 2017 20:22
Post::add_text does not, but Draft::add_text does need to so that the Post.content can be updated.
The other approach, which probably makes more sense, would be to query the Post.state and only update the content field if the state field reflects Draft, but I'm not sure how to access that.
Denis Lisov
@tanriol
Aug 13 2017 20:26
Furthermore, I'd probably expect add_text to return an error if trying to modify a non-draft, so it should likely return a Result
stevensonmt
@stevensonmt
Aug 13 2017 20:27
Yes, that's true. In fact I have written it to print a message to the console that only content of Draft posts can be updated. I was trying to minimize the complexity as much as possible.
tanriol @tanriol starts reading the book to check what it suggests
stevensonmt
@stevensonmt
Aug 13 2017 20:30
Yes, the chapter goes on to show how to restructure the code entirely. Perhaps my difficulties are the point of the suggested exercises in the middle of the section.
Denis Lisov
@tanriol
Aug 13 2017 20:38
What are you trying to do in State::add_text?
stevensonmt
@stevensonmt
Aug 13 2017 20:42
Following the pattern that other methods implemented for the trait had. Forces implementation for other states so that it should not panic if called for a state other than Draft.
Denis Lisov
@tanriol
Aug 13 2017 20:46
Are you trying to modify the content in-place (push_str) or just to return the new content?
stevensonmt
@stevensonmt
Aug 13 2017 20:47
since I'm moving the functionality out of a Post and into State, it should return the new content.
Denis Lisov
@tanriol
Aug 13 2017 20:50
Then it needs to return a String, I suppose... however, that's not the best idea. What about
trait State {
    fn add_text(&self, content: &mut String, text: &str) -> Result<(), MyError>;
}
impl State for Draft {
    fn add_text(&self, content: &mut String, text: &str) -> Result<(), MyError> {
        content.push_str(text);
        Ok(())
    }
}
stevensonmt
@stevensonmt
Aug 13 2017 20:57
Thanks. I'll play with that. On first pass I'm getting a does not have a constant size known at compile-time error for the Error use.