I can get the following code to pass
#[derive(thiserror::Error, Debug)]
#[error("`{0}` is invalid status. It must be one of ToDo, InProgress, or Done")]
pub struct TicketStatusError(String);
impl TryFrom<&str> for Status {
type Error = TicketStatusError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
"todo" => Ok(Status::ToDo),
"inprogress" => Ok(Status::InProgress),
"done" => Ok(Status::Done),
_ => Err(TicketStatusError(value.into())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::convert::TryFrom;
#[test]
fn test_try_from_invalid() {
let status = Status::try_from("Blah");
assert!(status.is_err());
assert_eq!(
status.unwrap_err().to_string(),
"`Blah` is invalid status. It must be one of ToDo, InProgress, or Done"
)
}
}
Here the interpolation is happening in the thiserror::Error
macro's Display implementation (I hope I am correct about that). In the 2nd line of the above listing. The error value is likely TicketStatusError(String::from("Blah"))
.
But I want the error value to be TicketStatusError(String::from("
Blah is invalid status. It must be one of ToDo, InProgress, or Done"))
. So I change the listing by making the following changes:
The Display implementation:
#[error("{0}")]
And the Err
return in the match
:
impl TryFrom<&str> for Status {
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
// ...
_ => Err(TicketStatusError(
"`{value}` is invalid status. It must be one of ToDo, InProgress, or Done".into(),
)),
}
}
}
I get the error
assertion `left == right` failed
left: "`{value}` is invalid status. It must be one of ToDo, InProgress, or Done"
right: "`Invalid` is invalid status. It must be one of ToDo, InProgress, or Done"
Which means the interpolation of value
into the error string did not happen. Please help me understand how to make this interpolation happen and what are the rules for interpolation here.