use std::collections::BTreeSet;
use bitflags::bitflags;
use super::Path;
#[derive(Debug, Default, Clone)]
pub struct ChangeList {
entries: Vec<(Path, ChangeEntry)>,
}
#[derive(Debug, Default, Clone)]
pub struct ChangeEntry {
pub flags: ChangeFlags,
pub info_changed: BTreeSet<&'static str>,
}
bitflags! {
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct ChangeFlags: u16 {
const ADD_INERT_PRIM = 1 << 0;
const ADD_NON_INERT_PRIM = 1 << 1;
const REMOVE_INERT_PRIM = 1 << 2;
const REMOVE_NON_INERT_PRIM = 1 << 3;
const ADD_PROPERTY = 1 << 4;
const REMOVE_PROPERTY = 1 << 5;
const CHANGE_RELATIONSHIP_TARGETS = 1 << 6;
const CHANGE_ATTRIBUTE_CONNECTION = 1 << 7;
const NON_INERT_PRIM = Self::ADD_NON_INERT_PRIM.bits() | Self::REMOVE_NON_INERT_PRIM.bits();
const INERT_PRIM = Self::ADD_INERT_PRIM.bits() | Self::REMOVE_INERT_PRIM.bits();
}
}
impl ChangeList {
pub fn new() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn entries(&self) -> &[(Path, ChangeEntry)] {
&self.entries
}
pub fn iter(&self) -> std::slice::Iter<'_, (Path, ChangeEntry)> {
self.entries.iter()
}
pub fn entry_mut(&mut self, path: &Path) -> &mut ChangeEntry {
if let Some(pos) = self.entries.iter().position(|(p, _)| p == path) {
return &mut self.entries[pos].1;
}
self.entries.push((path.clone(), ChangeEntry::default()));
&mut self.entries.last_mut().expect("just pushed").1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn entry_mut_dedups_same_path() {
let mut cl = ChangeList::new();
let p = Path::abs_root();
cl.entry_mut(&p).flags |= ChangeFlags::ADD_NON_INERT_PRIM;
cl.entry_mut(&p).info_changed.insert("specifier");
assert_eq!(cl.entries().len(), 1);
assert!(cl.entries()[0].1.flags.contains(ChangeFlags::ADD_NON_INERT_PRIM));
assert!(cl.entries()[0].1.info_changed.contains("specifier"));
}
#[test]
fn empty_until_first_entry() {
let mut cl = ChangeList::new();
assert!(cl.is_empty());
cl.entry_mut(&Path::abs_root());
assert!(!cl.is_empty());
}
}