use std::str::FromStr;
use std::{convert::Infallible, fmt};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(transparent)]
pub struct FileSize {
bytes: usize,
}
impl FileSize {
pub fn to_bytes(&self) -> usize {
self.bytes
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(try_from = "String", into = "String")]
pub struct AttachmentId([u8; 128], usize);
impl FromStr for AttachmentId {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from(s))
}
}
impl<'a> From<&'a str> for AttachmentId {
fn from(s: &'a str) -> Self {
let len = s.len();
assert!(len <= 128);
let mut buf = [0; 128];
buf[..len].copy_from_slice(s.as_bytes());
Self(buf, len)
}
}
impl From<String> for AttachmentId {
fn from(s: String) -> Self {
Self::from(s.as_str())
}
}
impl AsRef<str> for AttachmentId {
fn as_ref(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(&self.0[..self.1]) }
}
}
impl From<AttachmentId> for String {
fn from(id: AttachmentId) -> Self {
id.as_ref().to_string()
}
}
impl fmt::Display for AttachmentId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_ref().fmt(f)
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(tag = "type")]
#[serde(deny_unknown_fields)]
pub enum AttachmentMetadata {
File,
Text,
Audio,
Image { width: usize, height: usize },
Video { width: usize, height: usize },
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(rename_all = "lowercase")]
pub enum AttachmentTag {
Attachments,
Avatars,
Backgrounds,
Icons,
Banners,
}
impl AttachmentTag {
pub fn to_str(self) -> &'static str {
match self {
Self::Attachments => "attachments",
Self::Avatars => "avatars",
Self::Backgrounds => "backgrounds",
Self::Icons => "icons",
Self::Banners => "banners",
}
}
}
impl fmt::Display for AttachmentTag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.to_str().fmt(f)
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Attachment {
#[serde(rename = "_id")]
pub id: AttachmentId,
pub tag: AttachmentTag,
pub size: FileSize,
pub filename: String,
pub metadata: AttachmentMetadata,
pub content_type: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct SizeOptions {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub width: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub height: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_size: Option<u32>,
}