Reputation: 5324
I was following along here.
It contains a simplified example which seemed relevant, but my implementation doesn't lend itself well. The error here is: returns a reference to data owned by the current function
. The example suggests using a specific attribute of a struct, which is a String
. This is fine because the compiler can know how long that struct will last. But what if we need to build the string at runtime? How do I make this work?
#[derive(Clone, Debug)]
pub enum ReadFailure {
MissingFile(String),
BadData(String),
// ...
}
impl fmt::Display for ReadFailure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ReadFailure::MissingFile(path) => write!(f, "WARNING - File not read (file does not exist): {}", path),
ReadFailure::BadData(path) => write!(f, "WARNING - File cannot be read (file has bad data): {}", path),
// ...
}
}
}
/// Implements an error for failure to read with a message
#[derive(Clone, Debug)]
pub struct ReadError {
/// Failure condition
error: ReadFailure,
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.error)
}
}
impl Error for ReadError {
fn description(&self) -> &str {
let s = format!("{}", self.error);
&s
}
}
Upvotes: 0
Views: 2722
Reputation: 15115
But what if we need to build the string at runtime? How do I make this work?
Just build it at run-time when you create the ReadError
, here's an example:
use std::fmt;
use std::error::Error;
#[derive(Clone, Debug)]
pub enum ReadFailure {
MissingFile(String),
BadData(String),
}
impl fmt::Display for ReadFailure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ReadFailure::MissingFile(path) => write!(f, "WARNING - File not read (file does not exist): {}", path),
ReadFailure::BadData(path) => write!(f, "WARNING - File cannot be read (file has bad data): {}", path),
}
}
}
#[derive(Clone, Debug)]
pub struct ReadError {
error: ReadFailure,
description: String, // NEW
}
// NEW
impl ReadError {
fn new(error: ReadFailure) -> Self {
ReadError {
description: error.to_string(),
error,
}
}
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.error)
}
}
impl Error for ReadError {
fn description(&self) -> &str {
&self.description
}
}
fn main() {
// example
let error = ReadError::new(ReadFailure::MissingFile("./whatever.txt".to_string()));
println!("{}", error.description());
}
It's clear from description
's function signature that it's only suppose to be a read-only method that returns a reference to some field within the error.
Anyway, as @justinas pointed out in the comments that method is deprecated and the docs recommend implementing the Display
trait instead which you're already doing.
Upvotes: 1