Reputation: 11
just starting out on my adventures in Rust and trying to figure out the right way to create and return an enum that should take ownership of a &str string slice created from a String passed into the method. I don't think lifetime annotations in and of themselves will solve the problem since the original string argument will go out of scope at the end of the function block regardless. Any help would be much appreciated.
pub enum PubSubMessage {
// For now I won't worry about subbing/unsubbing to an array of channels
SUBSCRIBE { channel: &str },
UNSUBSCRIBE { channel: &str },
PUBLISH { channel: &str, msg: &str},
PSUBSCRIBE { pattern: &str },
PUNSUBSCRIBE { pattern: &str},
}
pub fn parse_message(msg: String) -> Result<PubSubMessage, String> {
let msg_contents: Vec<&str> = msg.split(" ").collect();
return match msg_contents.as_slice() {
["SUBSCRBE", channel] => Ok(PubSubMessage::SUBSCRIBE { channel }),
["UNSUBSCRIBE", channel] => Ok(PubSubMessage::UNSUBSCRIBE { channel }),
["PUBLISH", channel, msg] => Ok(PubSubMessage::PUBLISH { channel, msg }),
_ => Err("Could not parse ws message.".to_string())
}
}
The current compiler error that I'm getting is just that the enum definition expects lifetime parameters.
Upvotes: 0
Views: 115
Reputation: 23414
As others have said in the comments, the easiest way to do it is to use String
everywhere. That being said, if you wan to avoid extra copies and allocations, you can push the responsibility for owning the string higher up the call chain. If you want to do that, you will need to change your function signature so that it borrows msg
instead of taking ownership, and add the required lifetime parameters. Something like this:
pub enum PubSubMessage<'a> {
// For now I won't worry about subbing/unsubbing to an array of channels
SUBSCRIBE { channel: &'a str },
UNSUBSCRIBE { channel: &'a str },
PUBLISH { channel: &'a str, msg: &'a str},
PSUBSCRIBE { pattern: &'a str },
PUNSUBSCRIBE { pattern: &'a str},
}
pub fn parse_message<'a> (msg: &'a str) -> Result<PubSubMessage<'a>, String> {
let msg_contents: Vec<_> = msg.split(" ").collect();
return match msg_contents.as_slice() {
["SUBSCRBE", channel] => Ok(PubSubMessage::SUBSCRIBE { channel }),
["UNSUBSCRIBE", channel] => Ok(PubSubMessage::UNSUBSCRIBE { channel }),
["PUBLISH", channel, msg] => Ok(PubSubMessage::PUBLISH { channel, msg }),
_ => Err("Could not parse ws message.".to_string())
}
}
Upvotes: 2