zulip-api 0.0.8

Client library for interacting with the Zulip API
Documentation
use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use crate::response::BaseResponse;
use crate::{field_access, impl_default, impl_display, impl_response};

/// Represents the response for the `Matches Narrow` Zulip API endpoint.
///
/// See [check-messages-match-narrow](https://zulip.com/api/check-messages-match-narrow) for details.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Response {
    #[serde(flatten)]
    base: BaseResponse,
    messages: Option<HashMap<String, MatchNarrow>>,
}

impl Response {
    /// Creates a new [Response].
    pub const fn new() -> Self {
        Self {
            base: BaseResponse::new(),
            messages: None,
        }
    }
}

field_access! {
    Response {
        /// A dictionary with a key for each queried message that matches the narrow,
        /// with message IDs as keys and search rendering data as values.
        messages: option_ref { HashMap<String, MatchNarrow> },
    }
}

impl_default!(Response);
impl_display!(Response);
impl_response!(Response, base);

/// Represents the match entry response for the `Matches Narrow` Zulip API endpoint.
///
/// See [check-messages-match-narrow](https://zulip.com/api/check-messages-match-narrow) for details.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct MatchNarrow {
    match_content: String,
    match_subject: String,
}

impl MatchNarrow {
    /// Creates a new [MatchNarrow].
    pub const fn new() -> Self {
        Self {
            match_content: String::new(),
            match_subject: String::new(),
        }
    }
}

field_access! {
    MatchNarrow {
        /// HTML content of a queried message that matches the narrow. If the
        /// narrow is a search narrow, `<span class="highlight">` elements
        /// will be included, wrapping the matches for the search keywords.
        match_content: cow { str },
        /// HTML-escaped topic of a queried message that matches the narrow. If the
        /// narrow is a search narrow, `<span class="highlight">` elements
        /// will be included wrapping the matches for the search keywords.
        match_subject: cow { str },
    }
}

impl_default!(MatchNarrow);
impl_display!(MatchNarrow);

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

    #[test]
    fn test_response() {
        let msg_id = String::from("31");
        let match_narrow = MatchNarrow::new()
            .with_match_content(r#"<p><a href="http://foo.com" target="_blank" title="http://foo.com">http://foo.com</a></p>"#)
            .with_match_subject("test_topic");
        let messages = HashMap::from([(msg_id, match_narrow)]);

        let response = Response::new().with_messages(messages.clone());
        let response_json = response.to_string();

        assert_eq!(serde_json::to_string(&response).unwrap(), response_json);
        assert_eq!(
            serde_json::from_str::<Response>(&response_json).unwrap(),
            response
        );

        assert_eq!(response.messages(), Some(&messages));
    }
}