Skip to main content

cloud_sdk/operation/prepared/
error.rs

1//! Redacted prepared-request construction and execution failures.
2
3use core::fmt;
4
5use crate::operation::{ExecutionPermitError, ResponsePolicyError};
6use crate::transport::{EndpointIdentityError, ResponseWriterError};
7
8/// Incoherent policy supplied while constructing a prepared request.
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum PreparedRequestPolicyError {
11    /// Protected or retainable request IDs were not admitted by raw transport.
12    MissingRequestIdHeader,
13    /// Read-only metadata was paired with a method that can change state.
14    ReadOnlyMethodMismatch,
15}
16
17impl fmt::Display for PreparedRequestPolicyError {
18    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
19        formatter.write_str(match self {
20            Self::MissingRequestIdHeader => {
21                "prepared request ID policy requires raw x-request-id admission"
22            }
23            Self::ReadOnlyMethodMismatch => "read-only operation metadata requires GET or HEAD",
24        })
25    }
26}
27
28impl core::error::Error for PreparedRequestPolicyError {}
29
30/// Prepared execution failure with transport details redacted from diagnostics.
31#[derive(Clone, Copy, Eq, PartialEq)]
32pub enum PreparedExecutionError<E> {
33    /// A state-changing request was executed without plan-confirm authority.
34    AuthorizationRequired,
35    /// Plan-confirm authority became invalid before transport dispatch.
36    AuthorizationInvalid(ExecutionPermitError),
37    /// The bound transport returned invalid endpoint identity.
38    EndpointIdentity(EndpointIdentityError),
39    /// The bound endpoint differs from the prepared provider service.
40    EndpointMismatch,
41    /// The concrete transport failed.
42    Transport(E),
43    /// The SDK-owned response transaction failed.
44    ResponseWriter(ResponseWriterError),
45    /// The response failed provider-neutral policy.
46    ResponsePolicy(ResponsePolicyError),
47}
48
49impl<E> fmt::Debug for PreparedExecutionError<E> {
50    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
51        match self {
52            Self::AuthorizationRequired => formatter.write_str("AuthorizationRequired"),
53            Self::AuthorizationInvalid(error) => formatter
54                .debug_tuple("AuthorizationInvalid")
55                .field(error)
56                .finish(),
57            Self::EndpointIdentity(error) => formatter
58                .debug_tuple("EndpointIdentity")
59                .field(error)
60                .finish(),
61            Self::EndpointMismatch => formatter.write_str("EndpointMismatch"),
62            Self::Transport(_) => formatter.write_str("Transport([redacted])"),
63            Self::ResponseWriter(error) => formatter
64                .debug_tuple("ResponseWriter")
65                .field(error)
66                .finish(),
67            Self::ResponsePolicy(error) => formatter
68                .debug_tuple("ResponsePolicy")
69                .field(error)
70                .finish(),
71        }
72    }
73}
74
75impl<E> fmt::Display for PreparedExecutionError<E> {
76    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
77        formatter.write_str(match self {
78            Self::AuthorizationRequired => "state-changing request requires execution authority",
79            Self::AuthorizationInvalid(_) => "execution authority is no longer valid",
80            Self::EndpointIdentity(_) => "transport endpoint identity is invalid",
81            Self::EndpointMismatch => "transport endpoint differs from prepared service",
82            Self::Transport(_) => "prepared request transport failed",
83            Self::ResponseWriter(_) => "prepared response transaction failed",
84            Self::ResponsePolicy(_) => "prepared response policy failed",
85        })
86    }
87}
88
89impl<E> core::error::Error for PreparedExecutionError<E> {}
90
91impl<E: crate::transport::DeliveryClassified> crate::transport::DeliveryClassified
92    for PreparedExecutionError<E>
93{
94    fn delivery_phase(&self) -> crate::transport::DeliveryPhase {
95        use crate::transport::DeliveryPhase;
96        match self {
97            Self::AuthorizationRequired
98            | Self::AuthorizationInvalid(_)
99            | Self::EndpointIdentity(_)
100            | Self::EndpointMismatch => DeliveryPhase::NotSent,
101            Self::Transport(error) => error.delivery_phase(),
102            Self::ResponseWriter(_) => DeliveryPhase::PossiblySent,
103            Self::ResponsePolicy(_) => DeliveryPhase::ResponseStarted,
104        }
105    }
106}
107
108pub(super) enum EndpointCheckError {
109    Invalid(EndpointIdentityError),
110    Mismatch,
111}
112
113pub(super) fn map_endpoint_error<E>(error: EndpointCheckError) -> PreparedExecutionError<E> {
114    match error {
115        EndpointCheckError::Invalid(error) => PreparedExecutionError::EndpointIdentity(error),
116        EndpointCheckError::Mismatch => PreparedExecutionError::EndpointMismatch,
117    }
118}