davis 0.1.1

An CLI client for MPD.
use std::error::Error as StdErr;
use std::fmt;

#[derive(Debug)]
pub enum Error {
    Mpd(mpdrs::error::Error),
    Io {
        context: &'static str,
        error: std::io::Error,
    },
    ArgParse(lexopt::Error),
    ParseSeek(&'static str),
    Config(String),
}

impl StdErr for Error {}

impl From<mpdrs::error::Error> for Error {
    fn from(e: mpdrs::error::Error) -> Self {
        Error::Mpd(e)
    }
}

impl From<lexopt::Error> for Error {
    fn from(e: lexopt::Error) -> Self {
        Error::ArgParse(e)
    }
}

pub trait WithContext<T> {
    fn context(self, ctx: &'static str) -> Result<T, Error>;
}

impl<T> WithContext<T> for Result<T, std::io::Error> {
    fn context(self, context: &'static str) -> Result<T, Error> {
        self.map_err(|error| Error::Io { context, error })
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Mpd(e) => {
                write!(f, "An error occured when communicating with MPD:\n{}", e)
            }
            Error::Io { error, context } => {
                write!(f, "I/O error when {}:\n{}", context, error)
            }
            Error::ArgParse(e) => {
                write!(f, "Failed to parse command line arguments:\n{}", e)
            }
            Error::ParseSeek(e) => {
                write!(f, "Couldn't parse seek command:\n{}", e)
            }
            Error::Config(e) => {
                write!(f, "Failed to parse config file:\n{}", e)
            }
        }
    }
}