Skip to main content

handoff/
error.rs

1//! Public error type for the `handoff` crate.
2//!
3//! All fallible operations in the library return [`Result<T>`]. The error enum
4//! is `Send` so it can flow across the consumer's runtime-bridging channels.
5
6use std::sync::mpsc::{RecvError, RecvTimeoutError, SendError};
7
8#[derive(Debug, thiserror::Error)]
9pub enum Error {
10    #[error("io: {0}")]
11    Io(#[from] std::io::Error),
12
13    #[error("codec: {0}")]
14    Codec(#[from] postcard::Error),
15
16    #[error("nix: {0}")]
17    Nix(#[from] nix::Error),
18
19    #[error("protocol violation: {0}")]
20    Protocol(String),
21
22    #[error("frame too large: {0} bytes exceeds cap")]
23    FrameTooLarge(u32),
24
25    #[error("frame malformed: declared length {0} is below the protocol minimum")]
26    FrameMalformed(u32),
27
28    #[error("peer announced pid {announced} does not match expected pid {expected}")]
29    PidMismatch { expected: u32, announced: u32 },
30
31    #[error(
32        "protocol version mismatch: our range {our_min}..={our_max}, peer range \
33         {their_min}..={their_max}"
34    )]
35    VersionMismatch {
36        our_min: u16,
37        our_max: u16,
38        their_min: u16,
39        their_max: u16,
40    },
41
42    #[error("unexpected message for current state: {0}")]
43    UnexpectedMessage(&'static str),
44
45    #[error("timed out waiting for {0}")]
46    Timeout(&'static str),
47
48    #[error("data-dir lock held by pid {holder_pid}")]
49    LockHeld { holder_pid: i32 },
50
51    #[error("refused to break lock held by live process {holder_pid}")]
52    StaleLockBreakRefused { holder_pid: i32 },
53
54    #[error("handoff already in progress")]
55    HandoffInProgress,
56
57    #[error("handoff aborted by peer: {0}")]
58    Aborted(String),
59
60    #[error("required env var {0} not set")]
61    MissingEnv(&'static str),
62
63    #[error("env var {var} has bad value: {value}")]
64    BadEnv { var: &'static str, value: String },
65
66    #[error("internal channel disconnected")]
67    Channel,
68}
69
70pub type Result<T> = std::result::Result<T, Error>;
71
72// Channel conversions — the bridge pattern relies on `?` working across mpsc.
73impl<T> From<SendError<T>> for Error {
74    fn from(_: SendError<T>) -> Self {
75        Error::Channel
76    }
77}
78
79impl From<RecvError> for Error {
80    fn from(_: RecvError) -> Self {
81        Error::Channel
82    }
83}
84
85impl From<RecvTimeoutError> for Error {
86    fn from(e: RecvTimeoutError) -> Self {
87        match e {
88            RecvTimeoutError::Timeout => Error::Timeout("channel recv"),
89            RecvTimeoutError::Disconnected => Error::Channel,
90        }
91    }
92}