use alloc::vec::Vec;
use vize_l0::String;
use super::{DeclarationId, Facet, Fingerprint, SfcSummary, SummaryError};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Usage {
consumer: String,
used: Vec<(DeclarationId, Fingerprint)>,
}
impl Usage {
pub fn record(
consumer: &str,
summary: &SfcSummary,
used: &[(Facet, &str)],
) -> Result<Self, SummaryError> {
if consumer.is_empty() {
return Err(SummaryError::EmptyConsumer);
}
let mut recorded = Vec::with_capacity(used.len());
for &(facet, name) in used {
if recorded
.iter()
.any(|(id, _): &(DeclarationId, Fingerprint)| {
id.facet() == facet && id.name() == name
})
{
return Err(SummaryError::DuplicateUse {
facet,
name: String::from(name),
});
}
let Some(fp) = summary.fingerprint(facet, name) else {
return Err(SummaryError::Unknown {
facet,
name: String::from(name),
});
};
recorded.push((DeclarationId::new(facet, name), fp));
}
Ok(Self {
consumer: String::from(consumer),
used: recorded,
})
}
#[must_use]
pub fn consumer(&self) -> &str {
&self.consumer
}
#[must_use]
pub fn is_fresh(&self, next: &SfcSummary) -> bool {
self.used
.iter()
.all(|(id, fp)| next.fingerprint(id.facet(), id.name()) == Some(*fp))
}
}
impl SfcSummary {
#[must_use]
pub fn invalidated<'a>(&self, usages: &'a [Usage]) -> Vec<&'a str> {
usages
.iter()
.filter(|usage| !usage.is_fresh(self))
.map(Usage::consumer)
.collect()
}
}