zulip-api 0.0.8

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

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

/// Represents the content type of a Zulip message.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum ContentType {
    #[serde(rename = "text/html")]
    Html,
    #[serde(rename = "text/x-markdown")]
    Markdown,
}

impl ContentType {
    /// Represents the string value of the HTML [ContentType].
    pub const HTML: &str = "text/html";
    /// Represents the string value of the Markdown [ContentType].
    pub const MARKDOWN: &str = "text/x-markdown";

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

    /// Gets the [ContentType] string representation.
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::Html => Self::HTML,
            Self::Markdown => Self::MARKDOWN,
        }
    }

    /// Attempts to convert a string into a [ContentType].
    pub fn try_from_str(val: &str) -> Result<Self> {
        match val.to_lowercase().as_str() {
            Self::HTML => Ok(Self::Html),
            Self::MARKDOWN => Ok(Self::Markdown),
            s => Err(Error::invalid_field(
                "content_type",
                s,
                format!("{} | {}", Self::HTML, Self::MARKDOWN),
            )),
        }
    }
}

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

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

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

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

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

impl TryFrom<&String> for ContentType {
    type Error = Error;

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

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

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

impl std::fmt::Display for ContentType {
    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_content_type() {
        [
            (ContentType::Html, ContentType::HTML),
            (ContentType::Markdown, ContentType::MARKDOWN),
        ]
        .into_iter()
        .for_each(|(ct_ty, ct_ty_str)| {
            let ct_ty_json = format!(r#""{ct_ty_str}""#);

            assert_eq!(ct_ty.as_str(), ct_ty_str);
            assert_eq!(ContentType::try_from(ct_ty_str), Ok(ct_ty));
            assert_eq!(ContentType::try_from(ct_ty_str.to_string()), Ok(ct_ty));

            assert_eq!(serde_json::to_string(&ct_ty).unwrap(), ct_ty_json);
            assert_eq!(
                serde_json::from_str::<ContentType>(&ct_ty_json).unwrap(),
                ct_ty
            );
        });
    }
}