pub mod audio; pub mod document; pub mod image; pub mod markdown; pub mod video; use std::{collections::HashMap, path::Path}; use crate::{error::Result, media_type::MediaType, model::BookMetadata}; #[derive(Debug, Clone, Default)] pub struct ExtractedMetadata { pub title: Option, pub artist: Option, pub album: Option, pub genre: Option, pub year: Option, pub duration_secs: Option, pub description: Option, pub extra: HashMap, pub book_metadata: Option, // Photo-specific metadata pub date_taken: Option>, pub latitude: Option, pub longitude: Option, pub camera_make: Option, pub camera_model: Option, pub rating: Option, } pub trait MetadataExtractor: Send + Sync { /// Extract metadata from a file at the given path. /// /// # Errors /// /// Returns an error if the file cannot be read or parsed. fn extract(&self, path: &Path) -> Result; fn supported_types(&self) -> Vec; } /// Extract metadata from a file using the appropriate extractor for the given /// media type. /// /// # Errors /// /// Returns an error if no extractor supports the media type, or if extraction /// fails. pub fn extract_metadata( path: &Path, media_type: &MediaType, ) -> Result { let extractors: Vec> = vec![ Box::new(audio::AudioExtractor), Box::new(document::DocumentExtractor), Box::new(video::VideoExtractor), Box::new(markdown::MarkdownExtractor), Box::new(image::ImageExtractor), ]; for extractor in &extractors { if extractor.supported_types().contains(media_type) { return extractor.extract(path); } } Ok(ExtractedMetadata::default()) }