···8181pub mod walk;
82828383pub use disk::{DiskBuilder, DiskDriver, DiskError, DiskStore, DriveError};
8484+#[cfg(feature = "jacquard")]
8585+pub use mem::JacquardLoadError;
8486pub use mem::{DriverBuilder, LoadError, MemCar, PartialCar};
8587pub use mst::Commit;
8688pub use slice::{SliceError, SliceProof, SliceWalker};
+75
src/mem.rs
···422422 Ok((commit, None, make_disk_driver(store, walker, self.process)))
423423 }
424424}
425425+426426+// ---------------------------------------------------------------------------
427427+// jacquard feature: construct a MemCar from a pre-parsed ParsedCar
428428+// ---------------------------------------------------------------------------
429429+430430+/// Errors from [`DriverBuilder::load_jacquard_parsed_car`]
431431+#[cfg(feature = "jacquard")]
432432+#[derive(Debug, thiserror::Error)]
433433+pub enum JacquardLoadError {
434434+ #[error("failed to decode cbor: {0}")]
435435+ BadBlock(#[from] serde_ipld_dagcbor::DecodeError<std::convert::Infallible>),
436436+ #[error("missing commit")]
437437+ MissingCommit,
438438+ #[error("failed to walk mst: {0}")]
439439+ WalkError(#[from] WalkError),
440440+}
441441+442442+#[cfg(feature = "jacquard")]
443443+impl DriverBuilder {
444444+ /// Construct a [`MemCar`] from a pre-parsed [`jacquard_repo::car::reader::ParsedCar`].
445445+ ///
446446+ /// Synchronous alternative to [`load_car`] for callers that already hold a
447447+ /// `ParsedCar` from the jacquard ecosystem. The block processor from
448448+ /// [`with_block_processor`] is applied; the memory limit is ignored since all
449449+ /// blocks are already in memory.
450450+ pub fn load_jacquard_parsed_car(
451451+ &self,
452452+ parsed: jacquard_repo::car::reader::ParsedCar,
453453+ ) -> Result<MemCar, JacquardLoadError> {
454454+ use crate::mst::ObjectLink;
455455+456456+ let process = self.block_processor;
457457+ let root = parsed.root;
458458+459459+ // Decode the commit block at the root CID.
460460+ let commit_bytes = parsed
461461+ .blocks
462462+ .get(&root)
463463+ .ok_or(JacquardLoadError::MissingCommit)?
464464+ .as_ref();
465465+ let commit: Commit = serde_ipld_dagcbor::from_slice(commit_bytes)?;
466466+467467+ // Build the block map from all non-commit blocks.
468468+ let mut blocks = HashMap::new();
469469+ for (cid, data) in parsed.blocks {
470470+ if cid == root {
471471+ continue;
472472+ }
473473+ let maybe_processed = MaybeProcessedBlock::maybe(process, data.to_vec());
474474+ blocks.insert(ObjectLink::from(cid), maybe_processed);
475475+ }
476476+477477+ // Look up and decode the root MST node.
478478+ let root_cid: Cid = commit.data.clone().into();
479479+ let (root_node, root_bytes) = match blocks
480480+ .get(&commit.data)
481481+ .ok_or(JacquardLoadError::MissingCommit)?
482482+ {
483483+ MaybeProcessedBlock::Processed(_) => {
484484+ return Err(WalkError::BadCommitFingerprint.into());
485485+ }
486486+ MaybeProcessedBlock::Raw(bytes) => {
487487+ (serde_ipld_dagcbor::from_slice(bytes)?, bytes.clone())
488488+ }
489489+ };
490490+491491+ Ok(MemCar {
492492+ commit,
493493+ prev_key: None,
494494+ blocks,
495495+ walker: Walker::new(root_node, root_cid, root_bytes),
496496+ process,
497497+ })
498498+ }
499499+}