use std::cmp::Ordering;
use crate::*;
#[derive(Debug, PartialEq, Eq)]
pub enum MatchedEntries<AE, BE>
where
AE: EntryTrait,
BE: EntryTrait,
{
Left(AE),
Right(BE),
Both(AE, BE),
}
impl<AE, BE> MatchedEntries<AE, BE>
where
AE: EntryTrait,
BE: EntryTrait,
{
pub(crate) fn to_entry_change(&self) -> EntryChange {
match self {
MatchedEntries::Both(ae, be) => EntryChange::diff_metadata(ae, be),
MatchedEntries::Left(ae) => EntryChange::deleted(ae),
MatchedEntries::Right(be) => EntryChange::added(be),
}
}
}
pub struct MergeTrees<AE, BE, AIT, BIT>
where
AE: EntryTrait,
BE: EntryTrait,
AIT: Iterator<Item = AE>,
BIT: Iterator<Item = BE>,
{
ait: AIT,
bit: BIT,
na: Option<AE>,
nb: Option<BE>,
}
impl<AE, BE, AIT, BIT> MergeTrees<AE, BE, AIT, BIT>
where
AE: EntryTrait,
BE: EntryTrait,
AIT: Iterator<Item = AE>,
BIT: Iterator<Item = BE>,
{
pub fn new(ait: AIT, bit: BIT) -> MergeTrees<AE, BE, AIT, BIT> {
MergeTrees {
ait,
bit,
na: None,
nb: None,
}
}
}
impl<AE, BE, AIT, BIT> Iterator for MergeTrees<AE, BE, AIT, BIT>
where
AE: EntryTrait,
BE: EntryTrait,
AIT: Iterator<Item = AE>,
BIT: Iterator<Item = BE>,
{
type Item = MatchedEntries<AE, BE>;
fn next(&mut self) -> Option<Self::Item> {
if self.na.is_none() {
self.na = self.ait.next();
}
if self.nb.is_none() {
self.nb = self.bit.next();
}
match (&self.na, &self.nb) {
(None, None) => None,
(Some(_a), None) => Some(MatchedEntries::Left(self.na.take().unwrap())),
(None, Some(_b)) => Some(MatchedEntries::Right(self.nb.take().unwrap())),
(Some(a), Some(b)) => match a.apath().cmp(b.apath()) {
Ordering::Equal => Some(MatchedEntries::Both(
self.na.take().unwrap(),
self.nb.take().unwrap(),
)),
Ordering::Less => Some(MatchedEntries::Left(self.na.take().unwrap())),
Ordering::Greater => Some(MatchedEntries::Right(self.nb.take().unwrap())),
},
}
}
}
#[cfg(test)]
mod tests {
use crate::monitor::test::TestMonitor;
use crate::test_fixtures::*;
use crate::*;
use super::MatchedEntries;
#[test]
fn merge_entry_trees() {
let ta = TreeFixture::new();
let tb = TreeFixture::new();
let monitor = TestMonitor::arc();
let di = MergeTrees::new(
ta.live_tree()
.iter_entries(Apath::root(), Exclude::nothing(), monitor.clone())
.unwrap(),
tb.live_tree()
.iter_entries(Apath::root(), Exclude::nothing(), monitor.clone())
.unwrap(),
)
.collect::<Vec<_>>();
assert_eq!(di.len(), 1);
match &di[0] {
MatchedEntries::Both(ae, be) => {
assert_eq!(ae.kind(), Kind::Dir);
assert_eq!(be.kind(), Kind::Dir);
assert_eq!(ae.apath(), "/");
assert_eq!(be.apath(), "/");
}
other => panic!("unexpected {other:#?}"),
}
}
}