Skip to main content

bob_chat/
file.rs

1//! File attachment and upload types.
2
3use serde::{Deserialize, Serialize};
4
5/// The kind of an attachment.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum AttachmentKind {
9    /// An image attachment.
10    Image,
11    /// A generic file attachment.
12    File,
13    /// A video attachment.
14    Video,
15    /// An audio attachment.
16    Audio,
17}
18
19/// A file attachment received from a chat adapter.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct Attachment {
22    /// Optional human-readable name.
23    pub name: Option<String>,
24    /// MIME type such as `image/png`.
25    pub mime_type: Option<String>,
26    /// Size in bytes, if known.
27    pub size: Option<u64>,
28    /// URL where the attachment can be fetched.
29    pub url: Option<String>,
30    /// Raw bytes of the attachment, if already downloaded.
31    #[serde(skip)]
32    pub data: Option<bytes::Bytes>,
33    /// The kind of attachment.
34    pub kind: AttachmentKind,
35}
36
37/// A file upload to be sent along with a message.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct FileUpload {
40    /// The filename to present to the recipient.
41    pub filename: String,
42    /// MIME type of the file.
43    pub mime_type: Option<String>,
44    /// Raw file bytes.
45    #[serde(skip)]
46    pub data: bytes::Bytes,
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn attachment_kind_roundtrip() {
55        let json = serde_json::to_string(&AttachmentKind::Image).expect("serialize");
56        let back: AttachmentKind = serde_json::from_str(&json).expect("deserialize");
57        assert_eq!(back, AttachmentKind::Image);
58    }
59
60    #[test]
61    fn attachment_debug() {
62        let att = Attachment {
63            name: Some("photo.png".into()),
64            mime_type: Some("image/png".into()),
65            size: Some(1024),
66            url: None,
67            data: None,
68            kind: AttachmentKind::Image,
69        };
70        let dbg = format!("{att:?}");
71        assert!(dbg.contains("photo.png"));
72    }
73
74    #[test]
75    fn file_upload_debug() {
76        let fu = FileUpload {
77            filename: "report.pdf".into(),
78            mime_type: Some("application/pdf".into()),
79            data: bytes::Bytes::from_static(b"fake"),
80        };
81        let dbg = format!("{fu:?}");
82        assert!(dbg.contains("report.pdf"));
83    }
84}