Skip to main content

bonds_core/
error.rs

1use thiserror::Error;
2
3/// Coarse error categories used by the CLI to pick a color.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum ErrorKind {
6    /// User provided invalid or unusable data (e.g. path, timestamp, identifier).
7    Input,
8    /// No bond matched the provided identifier or path.
9    NotFound,
10    /// A bond already exists for the provided identifier or target path.
11    Conflict,
12    /// An unexpected error occurred at runtime (e.g. IO, database, serialization).
13    Runtime,
14    /// Configuration file parse or write error.
15    Config,
16}
17
18/// Errors surfaced by the API
19#[derive(Error, Debug)]
20pub enum BondError {
21    /// Filesystem or OS I/O failure.
22    #[error("IO error: {0}")]
23    Io(#[from] std::io::Error),
24
25    /// SQLite query/connection failure.
26    #[error("SQLite error: {0}")]
27    Sqlite(#[from] rusqlite::Error),
28
29    /// JSON serialization/deserialization failure.
30    #[error("Serialization error: {0}")]
31    Serde(#[from] serde_json::Error),
32
33    /// A conflicting bond record already exists.
34    #[error("Bond already exists")]
35    AlreadyExists,
36
37    /// The requested target path already exists and cannot be replaced.
38    #[error("Target already exists: {0}")]
39    TargetExists(String),
40
41    /// No bond matched the provided identifier.
42    #[error("Bond not found: {0}")]
43    NotFound(String),
44
45    /// A provided path is invalid or unusable.
46    #[error("Invalid path: {0}")]
47    InvalidPath(String),
48
49    /// Configuration file parse or write error.
50    #[error("config error: {0}")]
51    Config(String),
52
53    /// The identifier prefix matched more than one bond.
54    #[error("ambiguous identifier '{0}': use more characters")]
55    AmbiguousId(String),
56
57    /// Failed to parse or interpret a timestamp.
58    #[error("invalid timestamp: {0}")]
59    InvalidTimestamp(String),
60}
61
62impl BondError {
63    /// Return a broad category so the CLI can render the error consistently.
64    pub fn kind(&self) -> ErrorKind {
65        match self {
66            Self::InvalidPath(_) | Self::InvalidTimestamp(_) | Self::AmbiguousId(_) => {
67                ErrorKind::Input
68            }
69            Self::NotFound(_) => ErrorKind::NotFound,
70            Self::AlreadyExists | Self::TargetExists(_) => ErrorKind::Conflict,
71            Self::Io(_) | Self::Sqlite(_) | Self::Serde(_) => ErrorKind::Runtime,
72            Self::Config(_) => ErrorKind::Config,
73        }
74    }
75}