use std::sync::Arc;
#[cfg(feature = "resolution-test-support")]
use crate::observe::{self, Observation};
use crate::resolution::rust::identity::TargetId;
pub(super) struct Ancestry {
latest: Arc<Link>,
}
struct Link {
previous: Option<Arc<Link>>,
target: TargetId,
package_name: Arc<str>,
}
impl Ancestry {
pub(super) fn root(target: TargetId, package_name: &Arc<str>) -> Self {
Self {
latest: Arc::new(Link {
previous: None,
target,
package_name: Arc::clone(package_name),
}),
}
}
pub(super) fn extend(&self, target: TargetId, package_name: &Arc<str>) -> Self {
#[cfg(feature = "resolution-test-support")]
observe::record(Observation::DependencyChainExtension {
history_entries_copied: 0,
});
Self {
latest: Arc::new(Link {
previous: Some(Arc::clone(&self.latest)),
target,
package_name: Arc::clone(package_name),
}),
}
}
pub(super) fn repeats_latest(&self) -> bool {
let target = self.latest.target;
links(self.latest.previous.as_deref()).any(|entry| entry.target == target)
}
pub(super) fn package_names(&self) -> Vec<&str> {
let mut names: Vec<&str> = links(Some(&self.latest))
.map(|entry| entry.package_name.as_ref())
.collect();
names.reverse();
names
}
}
fn links(start: Option<&Link>) -> impl Iterator<Item = &Link> {
std::iter::successors(start, |entry| entry.previous.as_deref())
}