#[derive(Debug)]
pub struct Error {
pub description: String,
context: Vec<String>,
}
impl Error {
pub fn new(description: String) -> Error {
Error {
description,
context: Vec::new(),
}
}
pub fn message(&self) -> String {
if self.context.is_empty() {
self.description.clone()
} else {
let ctx = self.context.iter().fold(String::new(), |mut a, b| {
if !a.is_empty() {
a.push_str("/");
}
a + b
});
format!("{}: {}", ctx, self.description)
}
}
pub fn push_context(&self, context: &str) -> Error {
let mut new_context = self.context.clone();
new_context.insert(0, context.to_string());
Error {
description: self.description.clone(),
context: new_context,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_error_message_should_include_context_in_the_correct_order() {
let msg = "This is a slam poem that I wrote and I am speaking the slam poem to you right now with my mouth.";
let expected = "outer/inner: ".to_string() + msg;
let error = Error::new(msg.to_string())
.push_context("inner")
.push_context("outer");
assert_eq!(error.message(), expected);
}
}