1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use std::borrow::Cow;

use crate::mime::{self, normalize_to_lf, AllowedMimeTypes, AsMimeTypes, Error, MimeType};

pub struct Text(pub String);

impl TryFrom<(Vec<u8>, MimeType)> for Text {
    type Error = Error;

    fn try_from((content, mime_type): (Vec<u8>, MimeType)) -> Result<Self, Self::Error> {
        let utf8 = String::from_utf8_lossy(&content);
        let content = match utf8 {
            Cow::Borrowed(_) => String::from_utf8(content).unwrap(),
            Cow::Owned(content) => content,
        };

        // Post-process the content according to mime type.
        let content = match mime_type {
            MimeType::Text(mime::Text::TextPlainUtf8 | mime::Text::TextPlain) => {
                normalize_to_lf(content)
            },
            MimeType::Text(mime::Text::Utf8String) => content,
            MimeType::Other(_) => return Err(Error),
        };
        Ok(Text(content))
    }
}

impl AllowedMimeTypes for Text {
    fn allowed() -> Cow<'static, [MimeType]> {
        Cow::Borrowed(&[
            MimeType::Text(mime::Text::TextPlainUtf8),
            MimeType::Text(mime::Text::Utf8String),
            MimeType::Text(mime::Text::TextPlain),
        ])
    }
}

impl AsMimeTypes for Text {
    fn available(&self) -> Cow<'static, [MimeType]> {
        Self::allowed()
    }

    fn as_bytes(&self, mime_type: &MimeType) -> Option<Cow<'static, [u8]>> {
        match mime_type {
            MimeType::Text(
                mime::Text::TextPlainUtf8 | mime::Text::Utf8String | mime::Text::TextPlain,
            ) => Some(Cow::Owned(self.0.as_bytes().to_owned())),
            MimeType::Other(_) => None,
        }
    }
}