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