Skip to main content
← dvs documentation Rust API reference

dvs/
error.rs

1//! Stable, machine-readable codes for failures, shared by every command.
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum ErrorCode {
8    AuthRequired,
9    AuthExpired,
10    AccessDenied,
11    ServerUnavailable,
12    ServerTooOld,
13    ProjectNotFound,
14    /// An unreadable `.dvs` record, including git conflict markers
15    BadMetadata,
16    CredentialsUnreadable,
17    NotInProject,
18    InvalidArguments,
19    InvalidConfiguration,
20    NoFilesSelected,
21    IoError,
22    /// The fallback when nothing more specific is known
23    OperationFailed,
24    /// A row that failed without a more specific code
25    FileFailed,
26    RevokeFailed,
27    /// A row a cancel stopped before it started: a row state, not a failure
28    Cancelled,
29}
30
31impl ErrorCode {
32    pub fn as_str(&self) -> &'static str {
33        match self {
34            ErrorCode::AuthRequired => "auth_required",
35            ErrorCode::AuthExpired => "auth_expired",
36            ErrorCode::AccessDenied => "access_denied",
37            ErrorCode::ServerUnavailable => "server_unavailable",
38            ErrorCode::ServerTooOld => "server_too_old",
39            ErrorCode::ProjectNotFound => "project_not_found",
40            ErrorCode::BadMetadata => "bad_metadata",
41            ErrorCode::CredentialsUnreadable => "credentials_unreadable",
42            ErrorCode::NotInProject => "not_in_project",
43            ErrorCode::InvalidArguments => "invalid_arguments",
44            ErrorCode::InvalidConfiguration => "invalid_configuration",
45            ErrorCode::NoFilesSelected => "no_files_selected",
46            ErrorCode::IoError => "io_error",
47            ErrorCode::OperationFailed => "operation_failed",
48            ErrorCode::FileFailed => "file_failed",
49            ErrorCode::RevokeFailed => "revoke_failed",
50            ErrorCode::Cancelled => "cancelled",
51        }
52    }
53}
54
55/// A failure with its code: backend, records and credentials.
56#[derive(Debug, Clone, Serialize)]
57pub struct Error {
58    pub code: ErrorCode,
59    pub message: String,
60}
61
62impl Error {
63    pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
64        Self {
65            code,
66            message: message.into(),
67        }
68    }
69}
70
71impl std::fmt::Display for Error {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        f.write_str(&self.message)
74    }
75}
76
77impl std::error::Error for Error {}
78
79pub fn backend_error_code(error: &anyhow::Error) -> Option<ErrorCode> {
80    error.downcast_ref::<Error>().map(|e| e.code)
81}