zulip-api 0.0.8

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

use crate::{impl_default, impl_display, Error, Result};

/// Represents the propagation mode on a Zulip server.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum PropagateMode {
    /// Indicates changing one message.
    ChangeOne,
    /// Indicates changing the target message, and all following messages in a topic.
    ChangeLater,
    /// Indicates changing all messages in a topic.
    ChangeAll,
}

impl PropagateMode {
    /// Represents the [PropagateMode] change one string value.
    pub const CHANGE_ONE: &str = "change_one";
    /// Represents the [PropagateMode] change later string value.
    pub const CHANGE_LATER: &str = "change_later";
    /// Represents the [PropagateMode] change all string value.
    pub const CHANGE_ALL: &str = "change_all";

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

    /// Gets the [PropagateMode] string representation.
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::ChangeOne => Self::CHANGE_ONE,
            Self::ChangeLater => Self::CHANGE_LATER,
            Self::ChangeAll => Self::CHANGE_ALL,
        }
    }
}

impl_default!(PropagateMode);
impl_display!(PropagateMode);

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

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

    fn try_from(val: &str) -> Result<Self> {
        match val.to_lowercase().as_str() {
            Self::CHANGE_ONE => Ok(Self::ChangeOne),
            Self::CHANGE_LATER => Ok(Self::ChangeLater),
            Self::CHANGE_ALL => Ok(Self::ChangeAll),
            _ => Err(Error::invalid_field(
                "propagate_mode",
                val,
                "change_one | change_later | change_all",
            )),
        }
    }
}

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

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

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

    #[test]
    fn test_propagate_mode() {
        [
            (PropagateMode::ChangeOne, PropagateMode::CHANGE_ONE),
            (PropagateMode::ChangeLater, PropagateMode::CHANGE_LATER),
            (PropagateMode::ChangeAll, PropagateMode::CHANGE_ALL),
        ]
        .into_iter()
        .for_each(|(mode, mode_str)| {
            assert_eq!(mode.as_str(), mode_str);
            let mode_json = format!(r#""{mode_str}""#);

            assert_eq!(<&str>::from(mode), mode_str);
            assert_eq!(PropagateMode::try_from(mode_str).unwrap(), mode);

            assert_eq!(serde_json::to_string(&mode).unwrap(), mode_json);
            assert_eq!(
                serde_json::from_str::<PropagateMode>(&mode_json).unwrap(),
                mode
            );
        });
    }
}