Skip to main content

zulip_api/message/
draft.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{field_access, impl_default, impl_display};
4
5/// Represents a message draft.
6///
7/// Modified from `openapi-generator-cli` output:
8///
9/// ```shell,no_build,no_run
10/// $ openapi-generator-cli generate -g rust -i ./zerver/openapi/zulip.yaml -o zulip-openapi --skip-validate-spec
11/// ```
12///
13/// ```text
14/// /*
15/// * Zulip REST API
16/// *
17/// * Powerful open source group chat
18/// *
19/// * The version of the OpenAPI document: 1.0.0
20/// *
21/// * Generated by: https://openapi-generator.tech
22/// */
23/// ```
24///
25/// See [zerver/openapi/zulip.yaml](https://github.com/zulip/zulip/blob/main/zerver/openapi/zulip.yaml) for the original OpenAPI configuration.
26///
27/// Configuration slightly modified to work with the Rust generator of [`openapi-generator-cli`](https://openapi-generator.tech).
28#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
29pub struct Draft {
30    #[serde(skip_serializing_if = "Option::is_none")]
31    id: Option<i64>,
32    #[serde(rename = "type")]
33    draft_type: DraftType,
34    to: Vec<u64>,
35    topic: String,
36    content: String,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    timestamp: Option<u64>,
39}
40
41impl Draft {
42    /// Creates a new [Draft].
43    pub const fn new() -> Self {
44        Self {
45            id: None,
46            draft_type: DraftType::new(),
47            to: Vec::new(),
48            topic: String::new(),
49            content: String::new(),
50            timestamp: None,
51        }
52    }
53}
54
55field_access! {
56    Draft {
57        /// The unique ID of the draft.
58        ///
59        /// It will only used whenever the drafts are fetched.
60        /// This field should not be specified when the draft is being created or edited.
61        id: option { i64 },
62        /// A Unix timestamp (seconds only) representing when the draft was last edited.
63        ///
64        /// When creating a draft, this key need not be present and it will be filled in automatically by the server.
65        timestamp: option { u64 },
66    }
67}
68
69field_access! {
70    Draft {
71        /// The type of the draft.
72        ///
73        /// Either unaddressed (empty string), `\"stream\"`, or `\"private\"` (for one-on-one and group direct messages).
74        draft_type: DraftType,
75    }
76}
77
78field_access! {
79    Draft {
80        /// An array of the tentative target audience IDs.
81        ///
82        /// For channel messages, this should contain exactly 1 ID, the ID of the target channel.
83        /// For direct messages, this should be an array of target user IDs.
84        /// For unaddressed drafts, this is ignored, and clients should send an empty array.
85        to: cow { [u64] },
86        /// For channel message drafts, the tentative topic name.
87        ///
88        /// For direct or unaddressed messages, this will be ignored and should ideally be the empty string.
89        /// Should not contain null bytes.
90        topic: cow { str },
91        /// The body of the draft.
92        ///
93        /// Should not contain null bytes.
94        content: cow { str },
95    }
96}
97
98impl_default!(Draft);
99impl_display!(Draft);
100
101/// Represents the [Draft] type.
102#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
103#[serde(rename_all = "snake_case")]
104pub enum DraftType {
105    #[serde(rename = "")]
106    Unaddressed,
107    Stream,
108    Private,
109}
110
111impl DraftType {
112    /// Creates a new [DraftType].
113    pub const fn new() -> Self {
114        Self::Unaddressed
115    }
116}
117
118impl_default!(DraftType);
119impl_display!(DraftType);
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn test_draft() {
127        let id = 1;
128        let draft_type = DraftType::new();
129        let to = [2u64];
130        let topic = "test topic";
131        let content = "test content";
132        let timestamp = 3;
133
134        let draft = Draft::new()
135            .with_id(id)
136            .with_draft_type(draft_type)
137            .with_to(to.as_ref())
138            .with_topic(topic)
139            .with_content(content)
140            .with_timestamp(timestamp);
141        let draft_json = draft.to_string();
142
143        assert_eq!(serde_json::to_string(&draft).unwrap(), draft_json);
144        assert_eq!(serde_json::from_str::<Draft>(&draft_json).unwrap(), draft);
145
146        assert_eq!(draft.id(), Some(id));
147        assert_eq!(draft.draft_type(), draft_type);
148        assert_eq!(draft.to(), to.as_ref());
149        assert_eq!(draft.topic(), topic);
150        assert_eq!(draft.content(), content);
151        assert_eq!(draft.timestamp(), Some(timestamp));
152    }
153}