use std::ops::Deref;
use std::sync::Arc;
use crate::{MimeConfig, MimeDetectionPolicy, MimeDetector};
use super::mime_detector_backend::MimeDetectorBackend;
use super::{FileCommandMimeDetector, RepositoryMimeDetector};
#[derive(Clone)]
pub struct ArcMimeDetector {
inner: Arc<dyn MimeDetector>,
}
impl ArcMimeDetector {
pub fn new(detector: Arc<dyn MimeDetector>) -> Self {
Self { inner: detector }
}
pub fn from_name(name: &str) -> Option<Self> {
super::mime_detector_backend::MimeDetectorBackend::from_name(name).map(Self::from_backend)
}
pub fn from_mime_config(config: &MimeConfig) -> Self {
let backend = MimeDetectorBackend::select(
config.mime_detector_default(),
FileCommandMimeDetector::is_available(),
);
Self::from_backend_with_config(backend, config)
}
pub fn into_inner(self) -> Arc<dyn MimeDetector> {
self.inner
}
fn from_backend(backend: MimeDetectorBackend) -> Self {
Self::from_backend_with_config(backend, &MimeConfig::default())
}
fn from_backend_with_config(backend: MimeDetectorBackend, config: &MimeConfig) -> Self {
match backend {
MimeDetectorBackend::Repository => Self::new(Arc::new(
RepositoryMimeDetector::from_mime_config(config.clone()),
)),
MimeDetectorBackend::FileCommand => Self::new(Arc::new(
FileCommandMimeDetector::from_mime_config(config.clone()),
)),
}
}
}
impl Default for ArcMimeDetector {
fn default() -> Self {
Self::from_mime_config(&MimeConfig::default())
}
}
impl Deref for ArcMimeDetector {
type Target = dyn MimeDetector;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<dyn MimeDetector> for ArcMimeDetector {
fn as_ref(&self) -> &(dyn MimeDetector + 'static) {
self.inner.as_ref()
}
}
impl From<Arc<dyn MimeDetector>> for ArcMimeDetector {
fn from(detector: Arc<dyn MimeDetector>) -> Self {
Self::new(detector)
}
}
impl From<ArcMimeDetector> for Arc<dyn MimeDetector> {
fn from(detector: ArcMimeDetector) -> Self {
detector.into_inner()
}
}
impl MimeDetector for ArcMimeDetector {
fn detect_by_filename(&self, filename: &str) -> Option<String> {
self.inner.detect_by_filename(filename)
}
fn detect_by_content(&self, content: &[u8]) -> Option<String> {
self.inner.detect_by_content(content)
}
fn detect(
&self,
content: &[u8],
filename: Option<&str>,
policy: MimeDetectionPolicy,
) -> Option<String> {
self.inner.detect(content, filename, policy)
}
}