streamhouse/
error.rs

1use std::error::Error as StdError;
2
3use crate::types::ColumnType;
4
5/// Represents all possible errors.
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8#[allow(missing_docs)]
9pub enum Error {
10    #[error("invalid params: {0}")]
11    InvalidParams(#[source] Box<dyn StdError + Send + Sync>),
12    #[error("network error: {0:?}")]
13    Network(#[from] hyper::Error),
14    #[error("invalid utf-8: {0}")]
15    InvalidUnicode(#[from] std::string::FromUtf8Error),
16    #[error("no rows returned by a query that expected to return at least one row")]
17    RowNotFound,
18    #[error("sequences must have a known size ahead of time")]
19    SequenceMustHaveLength,
20    #[error("`deserialize_any` is not supported")]
21    NotEnoughData,
22    #[error("tag for enum is not valid")]
23    InvalidTagEncoding(usize),
24    #[error("bad response: {0}")]
25    BadResponse(String),
26    #[error("Unsupported column type: {0}")]
27    UnsupportedColumn(String),
28    #[error("Column types mismatch: {schema:?} vs {row:?}")]
29    WrongColumnTypes {
30        schema: Vec<ColumnType>,
31        row: Vec<ColumnType>,
32    },
33    #[error("Column names mismatch: {schema:?} vs {row:?}")]
34    WrongColumnNames {
35        schema: Vec<&'static str>,
36        row: Box<[String]>,
37    },
38    #[error("Each column must have a name: {row:?}")]
39    MissingColumnName { row: Vec<&'static str> },
40
41    // Internally handled errors, not part of public API.
42    // XXX: move to another error?
43    #[error("internal error: too small buffer, need another {0} bytes")]
44    #[doc(hidden)]
45    TooSmallBuffer(usize),
46}
47
48impl Error {
49    pub async fn from_bad_response(response: hyper::Response<hyper::Body>) -> Self {
50        let status = response.status();
51        let raw_bytes = match hyper::body::to_bytes(response.into_body()).await {
52            Ok(bytes) => bytes,
53            Err(err) => return err.into(),
54        };
55        let reason = String::from_utf8(raw_bytes.into())
56            .map(|reason| reason.trim().into())
57            .unwrap_or_else(|_| {
58                // If we have a unreadable response, return standardised reason for the status code.
59                format!(
60                    "{} {}",
61                    status.as_str(),
62                    status.canonical_reason().unwrap_or("<unknown>"),
63                )
64            });
65
66        Error::BadResponse(reason)
67    }
68}