Skip to main content

hyperdb_api/
error.rs

1// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Error types for the pure Rust Hyper API.
5
6use hyperdb_api_core::client::ErrorKind;
7use std::error::Error as StdError;
8use thiserror::Error as ThisError;
9
10/// The error type for Hyper API operations.
11///
12/// This enum is `#[non_exhaustive]`: new variants and new fields on existing
13/// struct variants may be added in minor releases. Match arms must include a
14/// wildcard `_ =>` pattern.
15#[derive(Debug, ThisError)]
16#[non_exhaustive]
17pub enum Error {
18    /// Error from the underlying Hyper client.
19    #[error("{0}")]
20    Client(#[from] hyperdb_api_core::client::Error),
21
22    /// I/O error.
23    #[error("I/O error: {0}")]
24    Io(#[from] std::io::Error),
25
26    /// Invalid name error (empty or too long).
27    #[error("Invalid name: {0}")]
28    InvalidName(String),
29
30    /// Invalid table definition.
31    #[error("Invalid table definition: {0}")]
32    InvalidTableDefinition(String),
33
34    /// Database object not found (table, schema, etc.).
35    #[error("Not found: {0}")]
36    NotFound(String),
37
38    /// Database object already exists.
39    #[error("Already exists: {0}")]
40    AlreadyExists(String),
41
42    /// Generic error with a custom message.
43    #[error("{message}")]
44    #[non_exhaustive]
45    Other {
46        /// The error message.
47        message: String,
48        /// The underlying cause of the error, if any.
49        #[source]
50        source: Option<Box<dyn StdError + Send + Sync>>,
51    },
52}
53
54impl Error {
55    /// Creates a new error with the given message.
56    ///
57    /// This is a convenience constructor for creating generic errors.
58    pub fn new(message: impl Into<String>) -> Self {
59        Error::Other {
60            message: message.into(),
61            source: None,
62        }
63    }
64
65    /// Creates a new error with a cause.
66    ///
67    /// This is a convenience constructor for creating generic errors with a source.
68    pub fn with_cause<E>(message: impl Into<String>, cause: E) -> Self
69    where
70        E: Into<Box<dyn StdError + Send + Sync>>,
71    {
72        Error::Other {
73            message: message.into(),
74            source: Some(cause.into()),
75        }
76    }
77
78    /// Returns the error kind, if this is a client error.
79    ///
80    /// This is available when the error originates from `hyperdb_api_core::client::Error`.
81    /// Use this for matching on error categories (e.g., `ErrorKind::Connection`).
82    #[must_use]
83    pub fn kind(&self) -> Option<ErrorKind> {
84        match self {
85            Error::Client(err) => Some(err.kind()),
86            _ => None,
87        }
88    }
89
90    /// Returns the error message.
91    #[must_use]
92    pub fn message(&self) -> String {
93        self.to_string()
94    }
95
96    /// Extracts the `PostgreSQL` SQLSTATE code from the error, if available.
97    ///
98    /// This is only available for database query errors from the Hyper client.
99    ///
100    /// # Example
101    ///
102    /// ```
103    /// use hyperdb_api::Error;
104    ///
105    /// // Assuming we have a client error with SQLSTATE
106    /// // let err: Error = ...;
107    /// // if let Some("42P04") = err.sqlstate() {
108    /// //     println!("Database already exists");
109    /// // }
110    /// ```
111    #[must_use]
112    pub fn sqlstate(&self) -> Option<&str> {
113        match self {
114            Error::Client(err) => err.sqlstate(),
115            _ => None,
116        }
117    }
118}
119
120impl From<std::convert::Infallible> for Error {
121    fn from(_: std::convert::Infallible) -> Self {
122        unreachable!()
123    }
124}
125
126/// Result type for Hyper API operations.
127pub type Result<T> = std::result::Result<T, Error>;