Skip to main content

pg_srv/
error.rs

1//! Protocol error types for PostgreSQL wire protocol
2
3use crate::protocol;
4use std::{backtrace::Backtrace, fmt::Formatter};
5
6/// Protocol error abstract of handled/unhandled errors, it should not handle any kind of business logic errors
7/// TODO: Migrate back to thiserror crate, when Rust will stabilize feature(error_generic_member_access)
8#[derive(Debug)]
9pub enum ProtocolError {
10    IO {
11        source: std::io::Error,
12        backtrace: Backtrace,
13    },
14    ErrorResponse {
15        source: protocol::ErrorResponse,
16        backtrace: Backtrace,
17    },
18}
19
20impl std::fmt::Display for ProtocolError {
21    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22        match self {
23            ProtocolError::IO { source, .. } => f.write_fmt(format_args!("IO error: {}", source)),
24            ProtocolError::ErrorResponse { source, .. } => {
25                f.write_fmt(format_args!("Error: {}", source.message))
26            }
27        }
28    }
29}
30
31impl From<std::io::Error> for ProtocolError {
32    fn from(source: std::io::Error) -> Self {
33        ProtocolError::IO {
34            source,
35            backtrace: Backtrace::capture(),
36        }
37    }
38}
39
40impl From<protocol::ErrorResponse> for ProtocolError {
41    fn from(source: protocol::ErrorResponse) -> Self {
42        ProtocolError::ErrorResponse {
43            source,
44            backtrace: Backtrace::capture(),
45        }
46    }
47}
48
49impl ProtocolError {
50    /// Return Backtrace from any variant of Enum
51    pub fn backtrace(&self) -> Option<&Backtrace> {
52        match &self {
53            ProtocolError::IO { backtrace, .. } => Some(backtrace),
54            ProtocolError::ErrorResponse { backtrace, .. } => Some(backtrace),
55        }
56    }
57
58    /// Converts Error to protocol::ErrorResponse which is usefully for writing response to the client
59    pub fn to_error_response(self) -> protocol::ErrorResponse {
60        match self {
61            ProtocolError::IO { source, .. } => protocol::ErrorResponse::error(
62                protocol::ErrorCode::InternalError,
63                source.to_string(),
64            ),
65            ProtocolError::ErrorResponse { source, .. } => source,
66        }
67    }
68}