prikk_error/lib.rs
1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3
4//! Shared error taxonomy for Prikk crates.
5
6use core::fmt;
7
8/// Shared result type.
9pub type Result<T> = core::result::Result<T, PrikkError>;
10
11/// Error type used by the initial implementation crates.
12///
13/// `#[non_exhaustive]` (RFC 132 increment 1): `prikk-error` is published, and until this attribute
14/// landed, adding any new variant was a breaking change for every downstream match. Verified free to
15/// add before landing it: no exhaustive `match` on a `PrikkError` value exists anywhere in this
16/// workspace.
17#[non_exhaustive]
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum PrikkError {
20 /// Canonical encoding failed because input data violates the frozen schema contract.
21 CanonicalEncoding(String),
22 /// An object identifier had an invalid form.
23 InvalidObjectId(String),
24 /// A signature had an invalid form or did not match its envelope context.
25 InvalidSignature(String),
26 /// A path-like name failed Prikk path/ref validation.
27 InvalidName(String),
28 /// A persistent object had an unexpected type.
29 ObjectTypeMismatch {
30 /// The object type required by the caller.
31 expected: String,
32 /// The object type actually found in the stored envelope.
33 actual: String,
34 },
35 /// The persistent format version is unsupported.
36 UnsupportedFormatVersion(u32),
37 /// A persisted object or record has malformed bytes.
38 MalformedData(String),
39 /// A persisted object was found at a path that does not match its computed ID.
40 Integrity(String),
41 /// A lock could not be acquired because another writer may be active.
42 LockConflict(String),
43 /// A caller precondition for the requested operation is not satisfied. Distinct from
44 /// [`Self::LockConflict`], which means another writer may hold a lock: nothing here is
45 /// transient and waiting does not help — the caller must change what they asked for.
46 Precondition(String),
47 /// The requested object type cannot be persisted in the requested store.
48 UnsupportedObjectType(String),
49 /// An I/O failure. `kind` is `Some` only when this value was built from a real
50 /// `std::io::Error` via [`From`] -- every explicit construction site elsewhere in the workspace
51 /// (a caller-precondition violation, a platform-capability refusal, or a validation failure
52 /// wearing this variant rather than one that describes it) sets `kind: None`, which is the
53 /// truth, not a placeholder to "tidy" into something non-optional. RFC 132 increment 2 is
54 /// expected to move those sites onto variants that describe them and narrow this field.
55 Io {
56 /// The underlying `std::io::ErrorKind`, when this was built from a real `std::io::Error`.
57 kind: Option<std::io::ErrorKind>,
58 /// Human-readable context. Alone carries the full `Display` message -- see that impl.
59 context: String,
60 },
61}
62
63impl fmt::Display for PrikkError {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 Self::CanonicalEncoding(msg) => write!(f, "canonical encoding error: {msg}"),
67 Self::InvalidObjectId(msg) => write!(f, "invalid object id: {msg}"),
68 Self::InvalidSignature(msg) => write!(f, "invalid signature: {msg}"),
69 Self::InvalidName(msg) => write!(f, "invalid name: {msg}"),
70 Self::ObjectTypeMismatch { expected, actual } => {
71 write!(f, "object type mismatch: expected {expected}, got {actual}")
72 }
73 Self::UnsupportedFormatVersion(version) => {
74 write!(f, "unsupported format version: {version}")
75 }
76 Self::MalformedData(msg) => write!(f, "malformed persisted data: {msg}"),
77 Self::Integrity(msg) => write!(f, "integrity error: {msg}"),
78 Self::LockConflict(msg) => write!(f, "lock conflict: {msg}"),
79 Self::Precondition(msg) => write!(f, "precondition not met: {msg}"),
80 Self::UnsupportedObjectType(msg) => write!(f, "unsupported object type: {msg}"),
81 Self::Io { context, .. } => write!(f, "i/o error: {context}"),
82 }
83 }
84}
85
86impl std::error::Error for PrikkError {}
87
88impl From<std::io::Error> for PrikkError {
89 fn from(value: std::io::Error) -> Self {
90 Self::Io {
91 kind: Some(value.kind()),
92 context: value.to_string(),
93 }
94 }
95}