//! Failures from inverting a commit's operations. use crate::cid::Cid; use crate::key::{Key, KeyError}; /// Which operation was being inverted when something did not line up. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OpKind { Create, Update, Delete, } impl std::fmt::Display for OpKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { OpKind::Create => "create", OpKind::Update => "update", OpKind::Delete => "delete", }; f.write_str(s) } } /// Why a node could not be read as an MST node. #[derive(Debug, thiserror::Error)] pub enum NodeFault { #[error("entry claims a {claimed}-byte shared prefix, previous key is {available} bytes")] PrefixOverrun { claimed: usize, available: usize }, #[error("key is {len} bytes, longer than any legal record path")] KeyTooLong { len: usize }, #[error("node has no entries")] Empty, #[error("node has subtree pointers but no leaves, so it has no layer")] NoLeaves, #[error("subtree at layer {child} hangs off a node at layer {parent}")] SubtreeNotBelow { parent: u8, child: u8 }, #[error("node at the leaf layer has a subtree pointer")] SubtreeAtLeafLayer, } /// Errors from [`crate::invert_ops`] and [`crate::Tree`]. /// /// The three interesting cases to tell apart operationally are /// [`ProofIncomplete`](Self::ProofIncomplete) (the producer sent us too few /// blocks — their bug), [`OpMismatch`](Self::OpMismatch) (the commit's claims /// do not match its own tree — a fork, or a broken producer), and the /// structural faults (garbage, or a format we do not speak). #[derive(Debug, thiserror::Error)] pub enum InvertError { /// The commit's blocks do not cover this operation. #[error("proof does not cover {key}: missing block {missing}")] ProofIncomplete { missing: Cid, key: Key }, /// A block referenced by the tree is absent, with no key to blame it on. #[error("proof is missing block {missing}")] MissingBlock { missing: Cid }, /// The tree does not hold what the operation says it should. #[error("{kind} op on {key} does not match the tree: expected {expected:?}, found {found:?}")] OpMismatch { key: Key, kind: OpKind, expected: Option, found: Option, }, /// A node decoded, but is not a well-formed MST node. `cid` is absent for /// a node we built mid-inversion and have not encoded yet. #[error("malformed node {cid:?}: {detail}")] MalformedNode { cid: Option, detail: NodeFault }, /// A node did not decode as DAG-CBOR in the MST node schema. #[error("could not decode node {cid}: {detail}")] Decode { cid: Cid, detail: String }, /// Re-encoding a node failed. Should not happen for a tree we decoded. #[error("could not encode node: {detail}")] Encode { detail: String }, /// An operation names a key that is not a legal MST key. #[error("invalid key: {0}")] InvalidKey(#[from] KeyError), }