zulip-api 0.0.8

Client library for interacting with the Zulip API
Documentation
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;

use crate::error::Error;
use crate::result::Result;

/// Represents the `result` field returned in Zulip API responses.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, Zeroize)]
#[serde(rename_all = "lowercase")]
pub enum ApiResult {
    Success,
    Error,
}

impl ApiResult {
    /// Represents the string value of a success result.
    pub const SUCCESS: &str = "success";
    /// Represents the string value of an error result.
    pub const ERROR: &str = "error";

    /// Creates a new [ApiResult].
    pub const fn new() -> Self {
        Self::Success
    }

    /// Gets the string representation of the [ApiResult].
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::Success => Self::SUCCESS,
            Self::Error => Self::ERROR,
        }
    }

    /// Attempts to convert a string into an [ApiResult].
    pub fn try_from_str<S: Into<String>>(val: S) -> Result<Self> {
        match val.into().to_lowercase().as_str() {
            Self::SUCCESS => Ok(Self::Success),
            Self::ERROR => Ok(Self::Error),
            s => Err(Error::io_other(format!("invalid ApiResult: {s}"))),
        }
    }
}

impl Default for ApiResult {
    fn default() -> Self {
        Self::new()
    }
}

impl From<ApiResult> for &'static str {
    fn from(val: ApiResult) -> Self {
        val.as_str()
    }
}

impl From<ApiResult> for String {
    fn from(val: ApiResult) -> Self {
        val.as_str().to_string()
    }
}

impl TryFrom<&str> for ApiResult {
    type Error = Error;

    fn try_from(val: &str) -> Result<Self> {
        Self::try_from_str(val)
    }
}

impl TryFrom<String> for ApiResult {
    type Error = Error;

    fn try_from(val: String) -> Result<Self> {
        Self::try_from_str(val.as_str())
    }
}

impl std::fmt::Display for ApiResult {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_api_result() {
        [ApiResult::Success, ApiResult::Error]
            .into_iter()
            .zip([ApiResult::SUCCESS, ApiResult::ERROR])
            .for_each(|(res, res_str)| {
                let res_json = format!(r#""{res}""#);
                assert_eq!(res.as_str(), res_str);

                assert_eq!(<&str>::from(res), res_str);
                assert_eq!(String::from(res), res_str.to_string());

                assert_eq!(ApiResult::try_from_str(res_str), Ok(res));
                assert_eq!(ApiResult::try_from(res_str), Ok(res));
                assert_eq!(ApiResult::try_from(res_str.to_string()), Ok(res));

                assert_eq!(serde_json::to_string(&res).unwrap(), res_json);
                assert_eq!(serde_json::from_str::<ApiResult>(&res_json).unwrap(), res);
            });
    }
}