affine_doc_loader 0.1.9

AFFiNE document parsing and rendering utilities.
Documentation
use y_octo::Any;

use super::{
  ArrayRead, MapRead, ParseError, ValueRead, WorkspaceRootProjection, any_as_string, any_truthy, get_string, load_doc,
};

pub fn project_workspace_root(doc_bin: Vec<u8>, include_trash: bool) -> Result<WorkspaceRootProjection, ParseError> {
  let doc = load_doc(&doc_bin, None)?;
  let complete = !doc.has_pending_updates();
  let doc_ids = doc
    .get_map("meta")
    .map(|meta| collect_doc_ids(meta, include_trash))
    .unwrap_or_default();
  Ok(WorkspaceRootProjection { doc_ids, complete })
}

pub fn get_doc_ids_from_binary(doc_bin: Vec<u8>, include_trash: bool) -> Result<Vec<String>, ParseError> {
  project_workspace_root(doc_bin, include_trash).map(|projection| projection.doc_ids)
}

fn collect_doc_ids<M: MapRead>(meta: M, include_trash: bool) -> Vec<String> {
  let mut doc_ids = Vec::new();
  let pages_value = meta.get_value("pages");
  if let Some(pages) = pages_value.as_ref().and_then(ValueRead::as_array_view) {
    for page_val in pages.items() {
      if let Some(page) = page_val.as_map_view()
        && let Some(id) = get_string(&page, "id")
      {
        let trash = page
          .get_value("trash")
          .and_then(|value| value.as_any_read().map(|value| any_truthy(&value)))
          .unwrap_or(false);
        if include_trash || !trash {
          doc_ids.push(id);
        }
      }
    }
    return doc_ids;
  }
  if let Some(Any::Array(entries)) = pages_value.and_then(|value| value.as_any_owned()) {
    for entry in entries {
      let Any::Object(map) = entry else {
        continue;
      };
      if let Some(id) = map.get("id").and_then(any_as_string).map(str::to_string) {
        let trash = map.get("trash").map(any_truthy).unwrap_or(false);
        if include_trash || !trash {
          doc_ids.push(id);
        }
      }
    }
  }
  doc_ids
}