smithay_clipboard/
mime.rs
1use std::borrow::Cow;
2use std::{error, fmt};
3
4pub static ALLOWED_TEXT_MIME_TYPES: [&str; 3] =
6 ["text/plain;charset=utf-8", "UTF8_STRING", "text/plain"];
7
8#[derive(Debug, Clone, Copy)]
9pub struct Error;
10
11impl fmt::Display for Error {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 write!(f, "Unsupported mime type")
14 }
15}
16
17impl error::Error for Error {}
18
19#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
20pub enum Text {
21 #[default]
22 TextPlainUtf8 = 0,
26 Utf8String = 1,
31 TextPlain = 2,
35}
36
37#[derive(Clone, Eq, PartialEq, Debug)]
39pub enum MimeType {
40 Text(Text),
42 Other(Cow<'static, str>),
44}
45
46impl Default for MimeType {
47 fn default() -> Self {
48 MimeType::Text(Text::default())
49 }
50}
51
52impl From<Cow<'static, str>> for MimeType {
53 fn from(value: Cow<'static, str>) -> Self {
54 if let Some(pos) = ALLOWED_TEXT_MIME_TYPES.into_iter().position(|allowed| allowed == value)
55 {
56 MimeType::Text(match pos {
57 0 => Text::TextPlainUtf8,
58 1 => Text::Utf8String,
59 2 => Text::TextPlain,
60 _ => unreachable!(),
61 })
62 } else {
63 MimeType::Other(value)
64 }
65 }
66}
67
68impl AsRef<str> for MimeType {
69 fn as_ref(&self) -> &str {
70 match self {
71 MimeType::Other(s) => s.as_ref(),
72 MimeType::Text(text) => ALLOWED_TEXT_MIME_TYPES[*text as usize],
73 }
74 }
75}
76
77pub trait AllowedMimeTypes: TryFrom<(Vec<u8>, MimeType)> {
79 fn allowed() -> Cow<'static, [MimeType]>;
84}
85
86pub trait AsMimeTypes {
88 fn available(&self) -> Cow<'static, [MimeType]>;
90
91 fn as_bytes(&self, mime_type: &MimeType) -> Option<Cow<'static, [u8]>>;
93}
94
95impl MimeType {
96 pub(crate) fn find_allowed(
101 offered_mime_types: &[String],
102 allowed_mime_types: &[Self],
103 ) -> Option<Self> {
104 allowed_mime_types
105 .iter()
106 .find(|allowed| {
107 offered_mime_types.iter().any(|offered| offered.as_str() == allowed.as_ref())
108 })
109 .cloned()
110 }
111}
112
113impl std::fmt::Display for MimeType {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 match self {
116 MimeType::Other(m) => write!(f, "{}", m),
117 MimeType::Text(text) => write!(f, "{}", ALLOWED_TEXT_MIME_TYPES[*text as usize]),
118 }
119 }
120}
121
122pub fn normalize_to_lf(text: String) -> String {
128 text.replace("\r\n", "\n").replace('\r', "\n")
129}
130
131#[cfg(test)]
132mod tests {
133 use std::borrow::Cow;
134
135 use crate::mime::{MimeType, ALLOWED_TEXT_MIME_TYPES};
136
137 #[test]
138 fn test_from_str() {
139 assert_eq!(
140 MimeType::from(Cow::Borrowed(ALLOWED_TEXT_MIME_TYPES[0])),
141 MimeType::Text(crate::mime::Text::TextPlainUtf8)
142 );
143 assert_eq!(
144 MimeType::from(Cow::Borrowed(ALLOWED_TEXT_MIME_TYPES[1])),
145 MimeType::Text(crate::mime::Text::Utf8String)
146 );
147 assert_eq!(
148 MimeType::from(Cow::Borrowed(ALLOWED_TEXT_MIME_TYPES[2])),
149 MimeType::Text(crate::mime::Text::TextPlain)
150 );
151 }
152}