use codas::types::Text;
mod media_type;
pub use media_type::{MediaCategory, MediaType};
use crate::proc::ProcessingError;
#[derive(Clone, Debug)]
pub struct Asset {
path: Text,
content: Option<AssetContent>,
content_media_type: MediaType,
}
impl Asset {
pub fn new(path: Text, content: Vec<u8>) -> Self {
let contents = if content.is_empty() {
None
} else {
Some(match String::from_utf8(content) {
Ok(text) => AssetContent::Textual(text.into()),
Err(e) => AssetContent::Binary(e.into_bytes()),
})
};
let media_type = MediaType::from_extension(path.split('.').next_back().unwrap_or_default());
Self {
path,
content_media_type: media_type,
content: contents,
}
}
pub fn path(&self) -> &Text {
&self.path
}
pub fn media_type(&self) -> &MediaType {
&self.content_media_type
}
pub fn set_media_type(&mut self, media_type: MediaType) {
self.content_media_type = media_type;
}
pub fn replace_with_bytes(&mut self, bytes: Vec<u8>, media_type: MediaType) {
self.content = Some(AssetContent::Binary(bytes));
self.content_media_type = media_type;
}
pub fn replace_with_text(&mut self, text: Text, media_type: MediaType) {
self.content = Some(AssetContent::Textual(text));
self.content_media_type = media_type;
}
pub fn as_bytes(&self) -> &[u8] {
match self.content.as_ref() {
Some(AssetContent::Binary(bytes)) => bytes,
Some(AssetContent::Textual(text)) => text.as_bytes(),
None => &[],
}
}
pub fn as_text(&self) -> Result<&Text, ProcessingError> {
match self.content.as_ref() {
Some(AssetContent::Textual(text)) => Ok(text),
_ => Err(ProcessingError::NonTextual),
}
}
pub fn as_mut_bytes(&mut self) -> Result<&mut Vec<u8>, ProcessingError> {
match &mut self.content {
Some(AssetContent::Binary(bytes)) => Ok(bytes),
_ => Err(ProcessingError::NonBinary),
}
}
}
#[derive(Clone, Debug)]
enum AssetContent {
Binary(Vec<u8>),
Textual(Text),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn creates_assets() {
let markdown_asset = Asset::new("story.md".into(), "Hello, world!".as_bytes().to_vec());
assert_eq!("story.md", markdown_asset.path());
assert_eq!(&MediaType::Markdown, markdown_asset.media_type());
assert_eq!(b"Hello, world!", markdown_asset.as_bytes());
assert_eq!("Hello, world!", markdown_asset.as_text().unwrap());
let binary_asset = Asset::new("data.dat".into(), (-1337i16).to_le_bytes().to_vec());
assert_eq!("data.dat", binary_asset.path());
assert_eq!(
&MediaType::Unknown {
extension: ["dat".into()]
},
binary_asset.media_type()
);
assert_eq!(&(-1337i16).to_le_bytes().to_vec(), binary_asset.as_bytes(),);
assert_eq!(Err(ProcessingError::NonTextual), binary_asset.as_text());
}
}