use std::sync::Arc;
use {parking_lot::RwLock, reovim_kernel::api::v1::Service};
use crate::{ContentClassifier, ContentCodec, ContentCodecFactory, ContentType};
#[derive(Default)]
pub struct ContentCodecFactoryStore {
factories: RwLock<Vec<Arc<dyn ContentCodecFactory>>>,
}
impl ContentCodecFactoryStore {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add_factory(&self, factory: Arc<dyn ContentCodecFactory>) {
self.factories.write().push(factory);
}
#[must_use]
pub fn find(&self, content_type: &ContentType) -> Option<Box<dyn ContentCodec>> {
self.factories
.read()
.iter()
.find_map(|f| f.create(content_type))
}
pub fn take_factories(&self) -> Vec<Arc<dyn ContentCodecFactory>> {
std::mem::take(&mut *self.factories.write())
}
#[must_use]
pub fn len(&self) -> usize {
self.factories.read().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.factories.read().is_empty()
}
}
impl Service for ContentCodecFactoryStore {}
impl std::fmt::Debug for ContentCodecFactoryStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContentCodecFactoryStore")
.field("count", &self.len())
.finish()
}
}
#[derive(Default)]
pub struct ContentClassifierStore {
classifiers: RwLock<Vec<Arc<dyn ContentClassifier>>>,
}
impl ContentClassifierStore {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add(&self, classifier: Arc<dyn ContentClassifier>) {
self.classifiers.write().push(classifier);
}
#[must_use]
pub fn classify(&self, raw: &[u8], path: &str) -> Option<ContentType> {
let mut sorted: Vec<_> = self.classifiers.read().iter().cloned().collect();
sorted.sort_by_key(|c| std::cmp::Reverse(c.priority()));
for classifier in &sorted {
if let Some(content_type) = classifier.classify(raw, path) {
return Some(content_type);
}
}
None
}
pub fn take_classifiers(&self) -> Vec<Arc<dyn ContentClassifier>> {
std::mem::take(&mut *self.classifiers.write())
}
#[must_use]
pub fn len(&self) -> usize {
self.classifiers.read().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.classifiers.read().is_empty()
}
}
impl Service for ContentClassifierStore {}
impl std::fmt::Debug for ContentClassifierStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContentClassifierStore")
.field("count", &self.len())
.finish()
}
}
#[cfg(test)]
#[path = "store_tests.rs"]
mod tests;