robespierre_models/
autumn.rs

1use std::str::FromStr;
2use std::{convert::Infallible, fmt};
3
4use serde::{Deserialize, Serialize};
5
6/*
7Newtypes
8*/
9
10/// Information about a file size
11#[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/*
24Types
25*/
26
27// https://github.com/revoltchat/api/blob/097f40e37108cd3a1816b1c2cc69a137ae317069/types/Autumn.ts#L1-L6
28
29/// Id type for attachments
30///
31/// Attachment ids are returned by `Autumn`.
32// and can be from 1 up to 128 characters
33// right now uploading a file gives a 42
34// char id
35#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
36#[serde(try_from = "String", into = "String")]
37pub struct AttachmentId([u8; 128], usize); // buffer + string slice length
38
39impl 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// https://github.com/revoltchat/api/blob/097f40e37108cd3a1816b1c2cc69a137ae317069/types/Autumn.ts#L8-L14
83
84/// Attachment metadata
85#[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// https://github.com/revoltchat/api/blob/097f40e37108cd3a1816b1c2cc69a137ae317069/types/Autumn.ts#L16-L19
97
98/// Attachment tag
99#[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// https://github.com/revoltchat/api/blob/097f40e37108cd3a1816b1c2cc69a137ae317069/types/Autumn.ts#L21-L45
128
129/// Attachment to a message, but can be any other media
130/// like avatars, server icons, channel icons, banners
131#[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// https://github.com/revoltchat/api/blob/097f40e37108cd3a1816b1c2cc69a137ae317069/types/Autumn.ts#L47-L70
144
145/// File serving parameters
146#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
147#[serde(deny_unknown_fields)]
148pub struct SizeOptions {
149    /// Width of resized image
150    #[serde(default, skip_serializing_if = "Option::is_none")]
151    pub width: Option<u32>,
152    /// Height of resized image
153    #[serde(default, skip_serializing_if = "Option::is_none")]
154    pub height: Option<u32>,
155    /// Width and height of resized image
156    #[serde(default, skip_serializing_if = "Option::is_none")]
157    pub size: Option<u32>,
158    /// Maximum resized image side length
159    #[serde(default, skip_serializing_if = "Option::is_none")]
160    pub max_size: Option<u32>,
161}