lazily-evaluated extractors

This commit is contained in:
2026-02-22 09:23:57 -08:00
parent d16d16be26
commit 751ff787e2
19 changed files with 525 additions and 391 deletions

View File

@@ -0,0 +1,68 @@
mod flac;
use std::{collections::HashMap, rc::Rc};
pub use flac::*;
mod fs;
pub use fs::*;
mod map;
pub use map::*;
use pile_config::Label;
/// An attachment that extracts metadata from an [Item].
///
/// Metadata is exposed as an immutable map of {label: value},
/// much like a json object.
pub trait Extractor<I: crate::Item> {
/// Get the field at `name` from `item`.
/// - returns `None` if `name` is not a valid field
/// - returns `Some(Null)` if `name` is not available
fn field<'a>(
&'a self,
name: &pile_config::Label,
) -> Result<Option<&'a crate::PileValue<'a, I>>, std::io::Error>;
/// Return all fields in this extractor.
/// `Self::field` must return [Some] for all these keys
/// and [None] for all others.
fn fields(&self) -> Result<Vec<Label>, std::io::Error>;
}
pub struct MetaExtractor<'a, I: crate::Item> {
inner: MapExtractor<'a, I>,
}
impl<'a> MetaExtractor<'a, crate::FileItem> {
#[expect(clippy::unwrap_used)]
pub fn new(item: &'a crate::FileItem) -> Self {
let inner = MapExtractor {
inner: HashMap::from([
(
Label::new("flac").unwrap(),
crate::PileValue::Extractor(Rc::new(FlacExtractor::new(item))),
),
(
Label::new("fs").unwrap(),
crate::PileValue::Extractor(Rc::new(FsExtractor::new(item))),
),
]),
};
Self { inner }
}
}
impl Extractor<crate::FileItem> for MetaExtractor<'_, crate::FileItem> {
fn field<'a>(
&'a self,
name: &pile_config::Label,
) -> Result<Option<&'a crate::PileValue<'a, crate::FileItem>>, std::io::Error> {
self.inner.field(name)
}
#[expect(clippy::unwrap_used)]
fn fields(&self) -> Result<Vec<Label>, std::io::Error> {
return Ok(vec![Label::new("flac").unwrap(), Label::new("fs").unwrap()]);
}
}