affine_importer 0.1.0

AFFiNE import planning and batching core.
Documentation
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VfsEntry {
  pub path: String,
  pub bytes: Vec<u8>,
}

#[cfg(test)]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Vfs {
  entries: Vec<VfsEntry>,
}

#[cfg(test)]
impl Vfs {
  pub fn insert(&mut self, path: impl Into<String>, bytes: Vec<u8>) -> crate::ImportResult<()> {
    let path = normalize_import_path(&path.into());
    if path.is_empty() {
      return Err(crate::ImportError::InvalidSource("empty path".to_string()));
    }
    if path.split('/').any(|part| part == "..") {
      return Err(crate::ImportError::InvalidSource(format!(
        "path escapes import root: {path}"
      )));
    }
    if is_system_path(&path) {
      return Ok(());
    }
    self.entries.push(VfsEntry { path, bytes });
    Ok(())
  }
}

pub fn normalize_import_path(path: &str) -> String {
  let mut parts = Vec::new();
  let path = path.replace('\\', "/");
  for part in path.split('/') {
    if part.is_empty() || part == "." {
      continue;
    }
    if part == ".." {
      if parts.last().is_some_and(|part| *part != "..") {
        parts.pop();
      } else {
        parts.push(part);
      }
      continue;
    }
    parts.push(part);
  }
  parts.join("/")
}

#[cfg(test)]
fn is_system_path(path: &str) -> bool {
  path.split('/').any(|part| part == "__MACOSX" || part == ".DS_Store")
}