1use std::str::FromStr;
2use std::{convert::Infallible, fmt};
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
12#[serde(transparent)]
13pub struct FileSize {
14 bytes: usize,
15}
16
17impl FileSize {
18 pub fn to_bytes(&self) -> usize {
19 self.bytes
20 }
21}
22
23#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
36#[serde(try_from = "String", into = "String")]
37pub struct AttachmentId([u8; 128], usize); impl FromStr for AttachmentId {
40 type Err = Infallible;
41
42 fn from_str(s: &str) -> Result<Self, Self::Err> {
43 Ok(Self::from(s))
44 }
45}
46
47impl<'a> From<&'a str> for AttachmentId {
48 fn from(s: &'a str) -> Self {
49 let len = s.len();
50 assert!(len <= 128);
51 let mut buf = [0; 128];
52 buf[..len].copy_from_slice(s.as_bytes());
53
54 Self(buf, len)
55 }
56}
57
58impl From<String> for AttachmentId {
59 fn from(s: String) -> Self {
60 Self::from(s.as_str())
61 }
62}
63
64impl AsRef<str> for AttachmentId {
65 fn as_ref(&self) -> &str {
66 unsafe { std::str::from_utf8_unchecked(&self.0[..self.1]) }
67 }
68}
69
70impl From<AttachmentId> for String {
71 fn from(id: AttachmentId) -> Self {
72 id.as_ref().to_string()
73 }
74}
75
76impl fmt::Display for AttachmentId {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 self.as_ref().fmt(f)
79 }
80}
81
82#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
86#[serde(tag = "type")]
87#[serde(deny_unknown_fields)]
88pub enum AttachmentMetadata {
89 File,
90 Text,
91 Audio,
92 Image { width: usize, height: usize },
93 Video { width: usize, height: usize },
94}
95
96#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
100#[serde(rename_all = "lowercase")]
101pub enum AttachmentTag {
102 Attachments,
103 Avatars,
104 Backgrounds,
105 Icons,
106 Banners,
107}
108
109impl AttachmentTag {
110 pub fn to_str(self) -> &'static str {
111 match self {
112 Self::Attachments => "attachments",
113 Self::Avatars => "avatars",
114 Self::Backgrounds => "backgrounds",
115 Self::Icons => "icons",
116 Self::Banners => "banners",
117 }
118 }
119}
120
121impl fmt::Display for AttachmentTag {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 self.to_str().fmt(f)
124 }
125}
126
127#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
132#[serde(deny_unknown_fields)]
133pub struct Attachment {
134 #[serde(rename = "_id")]
135 pub id: AttachmentId,
136 pub tag: AttachmentTag,
137 pub size: FileSize,
138 pub filename: String,
139 pub metadata: AttachmentMetadata,
140 pub content_type: String,
141}
142
143#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
147#[serde(deny_unknown_fields)]
148pub struct SizeOptions {
149 #[serde(default, skip_serializing_if = "Option::is_none")]
151 pub width: Option<u32>,
152 #[serde(default, skip_serializing_if = "Option::is_none")]
154 pub height: Option<u32>,
155 #[serde(default, skip_serializing_if = "Option::is_none")]
157 pub size: Option<u32>,
158 #[serde(default, skip_serializing_if = "Option::is_none")]
160 pub max_size: Option<u32>,
161}