contextvm_sdk/transport/oversized_transfer/errors.rs
1//! Error taxonomy for CEP-22 oversized transfers.
2//!
3//! Mirrors the TypeScript SDK's error classes
4//! (`sdk/src/transport/oversized-transfer/errors.ts`) so failure classification
5//! is identical across implementations. Surfaced through the crate-level
6//! [`crate::Error`] via a `#[from]` conversion.
7
8/// Errors raised while building, framing, or reassembling an oversized transfer.
9#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
10pub enum OversizedTransferError {
11 /// The remote peer aborted the transfer (terminal).
12 #[error("Transfer aborted (token: {token}){}", .reason.as_deref().map(|r| format!(": {r}")).unwrap_or_default())]
13 Abort {
14 /// The `progressToken` of the aborted transfer.
15 token: String,
16 /// Optional advisory reason supplied in the `abort` frame.
17 reason: Option<String>,
18 },
19
20 /// A frame violated a declared or configured policy limit
21 /// (`totalBytes`, `totalChunks`, concurrency, out-of-order bounds, chunk size).
22 #[error("Oversized transfer policy violation: {0}")]
23 Policy(String),
24
25 /// The byte length or SHA-256 digest of the reassembled payload did not match
26 /// the values declared in the `start` frame.
27 #[error("Oversized transfer integrity error: {0}")]
28 Digest(String),
29
30 /// Chunks could not be reassembled (missing frames, unresolved gaps, or the
31 /// reassembled payload is not a valid JSON-RPC message).
32 #[error("Oversized transfer reassembly error: {0}")]
33 Reassembly(String),
34
35 /// Frames violated CEP-22 sequencing rules (bad progress ordering,
36 /// duplicate `start`, conflicting duplicate chunk, missing token).
37 #[error("Oversized transfer sequence error: {0}")]
38 Sequence(String),
39}
40
41impl OversizedTransferError {
42 /// Construct an [`OversizedTransferError::Abort`].
43 pub fn abort(token: impl Into<String>, reason: Option<String>) -> Self {
44 Self::Abort {
45 token: token.into(),
46 reason,
47 }
48 }
49
50 /// Returns `true` if this is a terminal [`abort`](OversizedTransferError::Abort).
51 pub fn is_abort(&self) -> bool {
52 matches!(self, Self::Abort { .. })
53 }
54}