zulip-api 0.0.8

Client library for interacting with the Zulip API
Documentation
//! Library error types.

use std::borrow::Cow;

use serde::{Deserialize, Serialize};

mod kind;

pub use kind::ErrorKind;

/// Represents error variants for the library.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum Error {
    InvalidField {
        field: String,
        have: String,
        expected: String,
    },
    Io {
        kind: ErrorKind,
        message: String,
    },
}

impl Error {
    /// Creates a new invalid field [Error].
    pub fn invalid_field<'f, 'h, 'e, F, H, E>(field: F, have: H, expected: E) -> Self
    where
        F: Into<Cow<'f, str>>,
        H: Into<Cow<'h, str>>,
        E: Into<Cow<'e, str>>,
    {
        Self::InvalidField {
            field: F::into(field).into(),
            have: H::into(have).into(),
            expected: E::into(expected).into(),
        }
    }

    /// Creates a new I/O [Error] from a [`std::io::Error`].
    pub fn std_io(err: std::io::Error) -> Self {
        Self::Io {
            kind: ErrorKind::from_io(err.kind()),
            message: format!("{err}"),
        }
    }

    /// Creates a new I/O [Error].
    pub fn io<'m, M: Into<Cow<'m, str>>>(kind: ErrorKind, message: M) -> Self {
        Self::Io {
            kind,
            message: M::into(message).into(),
        }
    }

    /// Creates a new I/O other [Error].
    pub fn io_other<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
        Self::Io {
            kind: ErrorKind::Other,
            message: M::into(message).into(),
        }
    }

    /// Creates a new I/O filename [Error].
    pub fn io_filename<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
        Self::Io {
            kind: ErrorKind::InvalidFilename,
            message: M::into(message).into(),
        }
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::InvalidField {
                field,
                have,
                expected,
            } => write!(f, "invalid {field}, have: {have}, expected: {expected}"),
            Self::Io { kind, message } => write!(f, "I/O error, kind: {kind}, message: {message}"),
        }
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Self {
        Self::std_io(err)
    }
}

impl From<Error> for std::io::Error {
    fn from(err: Error) -> Self {
        match err {
            Error::Io { kind, message } => Self::new(kind.as_io(), message),
            err => Self::other(err),
        }
    }
}

impl From<uuid::Error> for Error {
    fn from(err: uuid::Error) -> Self {
        Self::std_io(std::io::Error::other(err))
    }
}

impl From<reqwest::Error> for Error {
    fn from(err: reqwest::Error) -> Self {
        Self::std_io(std::io::Error::other(err))
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Self {
        Self::std_io(std::io::Error::other(err))
    }
}

impl From<std::str::Utf8Error> for Error {
    fn from(err: std::str::Utf8Error) -> Self {
        Self::std_io(std::io::Error::other(err))
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Self {
        Self::io(ErrorKind::Other, format!("{err}"))
    }
}

impl From<reqwest::header::ToStrError> for Error {
    fn from(err: reqwest::header::ToStrError) -> Self {
        Self::io(ErrorKind::Other, format!("{err}"))
    }
}

#[cfg(target_family = "wasm")]
impl From<Error> for wasm_bindgen::JsValue {
    fn from(err: Error) -> Self {
        serde_wasm_bindgen::to_value(&err).unwrap_or_default()
    }
}

impl serde::de::Error for Error {
    fn custom<T: std::fmt::Display>(msg: T) -> Self {
        Self::io(ErrorKind::Other, format!("{msg}"))
    }
}

impl std::error::Error for Error {}