use std::{fs::{self}, path::PathBuf, str::FromStr};
use getset::{Getters, MutGetters, Setters};
use crate::dossier;
use super::{resource_reference::ResourceReference, source::Source, ResourceError};
#[derive(Debug, Getters, MutGetters, Setters, Clone)]
pub struct ImageResource {
#[getset(get = "pub", get_mut = "pub", set = "pub")]
src: Source,
#[getset(get = "pub", set = "pub")]
mime_type: Option<String>,
#[getset(get = "pub", set = "pub")]
id: Option<ResourceReference>,
#[getset(get = "pub", set = "pub")]
caption: Option<String>,
#[getset(get = "pub", set = "pub")]
style: Option<String>,
}
impl ImageResource {
pub fn new(src: Source, mime_type: Option<String>, id: Option<ResourceReference>, caption: Option<String>, style: Option<String>) -> Self {
Self {
src,
mime_type,
id,
caption,
style
}
}
pub fn inferring_id_if_not_set(mut self, document_name: &impl ToString) -> Result<Self, ResourceError> {
if self.id.is_none() {
if let Some(ref caption) = self.caption {
self.id = Some(ResourceReference::of_internal_from_without_sharp(caption, Some(document_name))?)
} else {
match &self.src {
Source::Remote { url } => self.id = Some(ResourceReference::of_url(url.as_str())?),
Source::Local { path } => self.id = Some(ResourceReference::of_asset(path.to_string_lossy().to_string().as_str())?),
Source::Base64String { base64: _ } | Source::Bytes { bytes: _ } => todo!(), }
}
}
Ok(self)
}
pub fn inferring_mime_type(mut self) -> Result<Self, ResourceError> {
match &self.src {
Source::Remote { url } => {
log::debug!("impossible to infer mime type of url: {}", url);
},
Source::Local { path } => {
let mime_type = infer::get_from_path(path)?;
if let Some(t) = mime_type {
let mut mime_type = t.mime_type().to_string();
if mime_type.contains("text/xml") {
mime_type = String::from("image/svg+xml");
}
self.set_mime_type(Some(mime_type));
return Ok(self);
} else {
return Err(ResourceError::InvalidResourceVerbose(format!("image {:?} mime type not found", self.src)));
}
},
Source::Base64String { base64: _ } | Source::Bytes { bytes: _ } => todo!(),
}
Ok(self)
}
pub fn inferring_mime_type_or_nothing(self) -> Self {
let backup = self.clone();
match self.inferring_mime_type() {
Ok(ok) => ok,
Err(err) => {
log::warn!("wrong inferring MIME type of image ({:?}): {}", backup.src(), err.to_string());
backup
},
}
}
pub fn elaborating_relative_path_as_dossier_assets(mut self, base_location: &PathBuf) -> Self {
match &self.src {
Source::Local { path } => {
let mut base_location: PathBuf = base_location.clone();
if !base_location.is_dir() {
base_location = PathBuf::from(base_location.parent().unwrap());
}
if path.is_relative() {
let mut path = base_location.join(path);
if !path.exists() {
let image_file_name = path.file_name().unwrap();
path = base_location.join(dossier::ASSETS_DIR).join(dossier::IMAGES_DIR).join(image_file_name);
if !path.exists() {
log::warn!("image src path {:?} not found also with images dossier assets path, try canonicalize path", path);
if let Ok(src) = fs::canonicalize(path.clone()) {
log::info!("canonicalizing ok: {:?} -> {:?}", path, src);
path = src;
} else {
log::warn!("canonicalizing fails for {:?}", path);
}
}
}
self.set_src(Source::Local { path });
}
},
_ => (),
}
self
}
}
impl FromStr for ImageResource {
type Err = ResourceError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(Source::from_str(s)?, None, None, None, None).inferring_mime_type_or_nothing())
}
}
#[cfg(test)]
mod test {
}