use core::{error::Error, fmt};
use crate::Format;
pub trait Suggest {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
impl<T: Suggest + ?Sized> Suggest for &T {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Suggest::fmt(*self, f)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Suggestion;
impl<E: Error + Suggest + ?Sized> Format<E> for Suggestion {
fn fmt(error: &E, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Suggest::fmt(error, f)
}
}
#[cfg(test)]
mod tests {
use thiserror::Error;
use super::*;
use crate::FormatError;
#[derive(Error, Debug)]
pub enum SugError {
#[error("env file missing")]
NoEnv,
#[error("something else")]
Other,
}
impl Suggest for SugError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoEnv => f.write_str("Did you mean rename the .env.example file to .env?"),
Self::Other => Ok(()),
}
}
}
#[derive(Error, Debug)]
#[error("plain")]
struct NoHint;
impl Suggest for NoHint {}
#[test]
fn renders_variant_hint() {
let error = SugError::NoEnv;
assert_eq!(
error.suggestion().to_string(),
"Did you mean rename the .env.example file to .env?"
);
}
#[test]
fn renders_empty_for_variant_without_hint() {
let error = SugError::Other;
assert_eq!(error.suggestion().to_string(), "");
}
#[test]
fn default_impl_writes_nothing() {
let error = NoHint;
assert_eq!(error.suggestion().to_string(), "");
}
#[test]
fn debug_forwards_to_inner() {
let error = SugError::NoEnv;
assert_eq!(format!("{:?}", error.suggestion()), "NoEnv");
}
#[test]
fn one_line_still_works_on_suggestion_types() {
let error = SugError::NoEnv;
assert_eq!(error.one_line().to_string(), "env file missing");
}
}