aws_smithy_runtime_api/client/interceptors/
error.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Errors related to Smithy interceptors
7
8use crate::box_error::BoxError;
9use std::fmt;
10
11macro_rules! interceptor_error_fn {
12    ($fn_name:ident => $error_kind:ident (with source)) => {
13        #[doc = concat!("Create a new error indicating a failure with a ", stringify!($fn_name), " interceptor.")]
14        pub fn $fn_name(
15            interceptor_name: impl Into<String>,
16            source: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
17        ) -> Self {
18            Self {
19                kind: ErrorKind::$error_kind,
20                interceptor_name: Some(interceptor_name.into()),
21                source: Some(source.into()),
22            }
23        }
24    };
25    ($fn_name:ident => $error_kind:ident (invalid $thing:ident access)) => {
26        #[doc = concat!("Create a new error indicating that an interceptor tried to access the ", stringify!($thing), " out of turn.")]
27        pub fn $fn_name() -> Self {
28            Self {
29                kind: ErrorKind::$error_kind,
30                interceptor_name: None,
31                source: None,
32            }
33        }
34    }
35}
36
37/// An error related to Smithy interceptors.
38#[derive(Debug)]
39pub struct InterceptorError {
40    kind: ErrorKind,
41    interceptor_name: Option<String>,
42    source: Option<BoxError>,
43}
44
45impl InterceptorError {
46    interceptor_error_fn!(read_before_execution => ReadBeforeExecution (with source));
47    interceptor_error_fn!(modify_before_serialization => ModifyBeforeSerialization (with source));
48    interceptor_error_fn!(read_before_serialization => ReadBeforeSerialization (with source));
49    interceptor_error_fn!(read_after_serialization => ReadAfterSerialization (with source));
50    interceptor_error_fn!(modify_before_retry_loop => ModifyBeforeRetryLoop (with source));
51    interceptor_error_fn!(read_before_attempt => ReadBeforeAttempt (with source));
52    interceptor_error_fn!(modify_before_signing => ModifyBeforeSigning (with source));
53    interceptor_error_fn!(read_before_signing => ReadBeforeSigning (with source));
54    interceptor_error_fn!(read_after_signing => ReadAfterSigning (with source));
55    interceptor_error_fn!(modify_before_transmit => ModifyBeforeTransmit (with source));
56    interceptor_error_fn!(read_before_transmit => ReadBeforeTransmit (with source));
57    interceptor_error_fn!(read_after_transmit => ReadAfterTransmit (with source));
58    interceptor_error_fn!(modify_before_deserialization => ModifyBeforeDeserialization (with source));
59    interceptor_error_fn!(read_before_deserialization => ReadBeforeDeserialization (with source));
60    interceptor_error_fn!(read_after_deserialization => ReadAfterDeserialization (with source));
61    interceptor_error_fn!(modify_before_attempt_completion => ModifyBeforeAttemptCompletion (with source));
62    interceptor_error_fn!(read_after_attempt => ReadAfterAttempt (with source));
63    interceptor_error_fn!(modify_before_completion => ModifyBeforeCompletion (with source));
64    interceptor_error_fn!(read_after_execution => ReadAfterExecution (with source));
65
66    interceptor_error_fn!(modify_before_attempt_completion_failed => ModifyBeforeAttemptCompletion (with source));
67    interceptor_error_fn!(read_after_attempt_failed => ReadAfterAttempt (with source));
68    interceptor_error_fn!(modify_before_completion_failed => ModifyBeforeCompletion (with source));
69    interceptor_error_fn!(read_after_execution_failed => ReadAfterExecution (with source));
70
71    interceptor_error_fn!(invalid_request_access => InvalidRequestAccess (invalid request access));
72    interceptor_error_fn!(invalid_response_access => InvalidResponseAccess (invalid response access));
73    interceptor_error_fn!(invalid_input_access => InvalidInputAccess (invalid input access));
74    interceptor_error_fn!(invalid_output_access => InvalidOutputAccess (invalid output access));
75}
76
77#[derive(Debug)]
78enum ErrorKind {
79    /// An error occurred within the read_before_execution interceptor
80    ReadBeforeExecution,
81    /// An error occurred within the modify_before_serialization interceptor
82    ModifyBeforeSerialization,
83    /// An error occurred within the read_before_serialization interceptor
84    ReadBeforeSerialization,
85    /// An error occurred within the read_after_serialization interceptor
86    ReadAfterSerialization,
87    /// An error occurred within the modify_before_retry_loop interceptor
88    ModifyBeforeRetryLoop,
89    /// An error occurred within the read_before_attempt interceptor
90    ReadBeforeAttempt,
91    /// An error occurred within the modify_before_signing interceptor
92    ModifyBeforeSigning,
93    /// An error occurred within the read_before_signing interceptor
94    ReadBeforeSigning,
95    /// An error occurred within the read_after_signing interceptor
96    ReadAfterSigning,
97    /// An error occurred within the modify_before_transmit interceptor
98    ModifyBeforeTransmit,
99    /// An error occurred within the read_before_transmit interceptor
100    ReadBeforeTransmit,
101    /// An error occurred within the read_after_transmit interceptor
102    ReadAfterTransmit,
103    /// An error occurred within the modify_before_deserialization interceptor
104    ModifyBeforeDeserialization,
105    /// An error occurred within the read_before_deserialization interceptor
106    ReadBeforeDeserialization,
107    /// An error occurred within the read_after_deserialization interceptor
108    ReadAfterDeserialization,
109    /// An error occurred within the modify_before_attempt_completion interceptor
110    ModifyBeforeAttemptCompletion,
111    /// An error occurred within the read_after_attempt interceptor
112    ReadAfterAttempt,
113    /// An error occurred within the modify_before_completion interceptor
114    ModifyBeforeCompletion,
115    /// An error occurred within the read_after_execution interceptor
116    ReadAfterExecution,
117    /// An interceptor tried to access the request out of turn
118    InvalidRequestAccess,
119    /// An interceptor tried to access the response out of turn
120    InvalidResponseAccess,
121    /// An interceptor tried to access the input out of turn
122    InvalidInputAccess,
123    /// An interceptor tried to access the output out of turn
124    InvalidOutputAccess,
125}
126
127macro_rules! display_interceptor_err {
128    ($self:ident, $f:ident, $(($error_kind:ident => $fn_name:ident ($($option:tt)+)),)+) => {
129        {
130        use ErrorKind::*;
131        match &$self.kind {
132            $($error_kind => display_interceptor_err!($self, $f, $fn_name, ($($option)+)),)+
133        }
134    }
135    };
136    ($self:ident, $f:ident, $fn_name:ident, (interceptor error)) => {{
137        $f.write_str($self.interceptor_name.as_deref().unwrap_or_default())?;
138        $f.write_str(concat!(" ", stringify!($fn_name), " interceptor encountered an error"))
139    }};
140    ($self:ident, $f:ident, $fn_name:ident, (invalid access $name:ident $message:literal)) => {
141        $f.write_str(concat!("tried to access the ", stringify!($name), " ", $message))
142    };
143}
144
145impl fmt::Display for InterceptorError {
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        display_interceptor_err!(self, f,
148            (ReadBeforeExecution => read_before_execution (interceptor error)),
149            (ModifyBeforeSerialization => modify_before_serialization (interceptor error)),
150            (ReadBeforeSerialization => read_before_serialization (interceptor error)),
151            (ReadAfterSerialization => read_after_serialization (interceptor error)),
152            (ModifyBeforeRetryLoop => modify_before_retry_loop (interceptor error)),
153            (ReadBeforeAttempt => read_Before_attempt (interceptor error)),
154            (ModifyBeforeSigning => modify_before_signing (interceptor error)),
155            (ReadBeforeSigning => read_before_signing (interceptor error)),
156            (ReadAfterSigning => read_after_signing (interceptor error)),
157            (ModifyBeforeTransmit => modify_before_transmit (interceptor error)),
158            (ReadBeforeTransmit => read_before_transmit (interceptor error)),
159            (ReadAfterTransmit => read_after_transmit (interceptor error)),
160            (ModifyBeforeDeserialization => modify_before_deserialization (interceptor error)),
161            (ReadBeforeDeserialization => read_before_deserialization (interceptor error)),
162            (ReadAfterDeserialization => read_after_deserialization (interceptor error)),
163            (ModifyBeforeAttemptCompletion => modify_before_attempt_completion (interceptor error)),
164            (ReadAfterAttempt => read_after_attempt (interceptor error)),
165            (ModifyBeforeCompletion => modify_before_completion (interceptor error)),
166            (ReadAfterExecution => read_after_execution (interceptor error)),
167            (InvalidRequestAccess => invalid_request_access (invalid access request "before request serialization")),
168            (InvalidResponseAccess => invalid_response_access (invalid access response "before transmitting a request")),
169            (InvalidInputAccess => invalid_input_access (invalid access input "after request serialization")),
170            (InvalidOutputAccess => invalid_output_access (invalid access output "before response deserialization")),
171        )
172    }
173}
174
175impl std::error::Error for InterceptorError {
176    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
177        self.source.as_ref().map(|err| err.as_ref() as _)
178    }
179}
180
181/// A convenience error that allows for adding additional `context` to `source`
182#[derive(Debug)]
183pub struct ContextAttachedError {
184    context: String,
185    source: Option<BoxError>,
186}
187
188impl ContextAttachedError {
189    /// Creates a new `ContextAttachedError` with the given `context` and `source`.
190    pub fn new(context: impl Into<String>, source: impl Into<BoxError>) -> Self {
191        Self {
192            context: context.into(),
193            source: Some(source.into()),
194        }
195    }
196}
197
198impl fmt::Display for ContextAttachedError {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        write!(f, "{}", self.context)
201    }
202}
203
204impl std::error::Error for ContextAttachedError {
205    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
206        self.source.as_ref().map(|err| err.as_ref() as _)
207    }
208}