use std::path::{Path, PathBuf}; use mime::Mime; use crate::files::mime_extension_lookup; use crate::String; #[cfg(feature = "json")] use serde::{ser::SerializeStruct, Serializer}; use std::fmt::{Display, Formatter}; /// Information about a scanned file. #[derive(Ord, PartialOrd, Eq, PartialEq)] pub struct Findings { /// The location of the scanned file. pub file: PathBuf, /// Whether or not the file's extension is valid for its mimetype. pub valid: bool, /// The file's mimetype. pub mime: Mime, } #[cfg(feature = "json")] impl serde::Serialize for Findings { fn serialize(&self, serializer: S) -> Result where S: Serializer, { // the second parameter is the number of fields in the struct -- in this case, 3 let mut state = serializer.serialize_struct("Findings", 3)?; state.serialize_field("file", &self.file)?; state.serialize_field("valid", &self.valid)?; state.serialize_field("mime", &self.mime.essence_str())?; state.end() } } impl Findings { pub fn recommended_extension(&self) -> Option { mime_extension_lookup(self.mime.essence_str().into()).map(|extensions| extensions[0].clone().into()) } } #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] #[cfg_attr(feature = "json", derive(serde::Serialize))] #[cfg_attr(feature = "json", serde(tag = "type", content = "path"))] pub enum ScanError<'a> { /// Something went wrong while trying to read the given file. File(&'a Path), /// Failed to determine the mimetype of the given file. Mime(&'a Path), } impl<'a> Display for ScanError<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, "Couldn't {} file: {}", match self { Self::File(_) => "read", Self::Mime(_) => "determine mime type of", }, match self { Self::File(f) | Self::Mime(f) => f.to_string_lossy(), } ) } }