aws_smithy_types/error/
operation.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Errors for operations
7
8use crate::date_time::DateTimeFormatError;
9use std::error::Error;
10use std::fmt::{Display, Formatter};
11
12#[derive(Debug)]
13enum SerializationErrorKind {
14    CannotSerializeUnknownVariant { union: &'static str },
15    DateTimeFormatError { cause: DateTimeFormatError },
16}
17
18/// An error that occurs when serialization of an operation fails.
19#[derive(Debug)]
20pub struct SerializationError {
21    kind: SerializationErrorKind,
22}
23
24impl SerializationError {
25    /// An error that occurs when serialization of an operation fails for an unknown reason.
26    pub fn unknown_variant(union: &'static str) -> Self {
27        Self {
28            kind: SerializationErrorKind::CannotSerializeUnknownVariant { union },
29        }
30    }
31}
32
33impl Display for SerializationError {
34    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35        match self.kind {
36            SerializationErrorKind::CannotSerializeUnknownVariant { union } => write!(
37                f,
38                "Cannot serialize `{union}::Unknown`. Unknown union variants cannot be serialized. \
39                This can occur when round-tripping a response from the server that was not \
40                recognized by the SDK. Consider upgrading to the latest version of the SDK.",
41            ),
42            SerializationErrorKind::DateTimeFormatError { .. } => {
43                write!(f, "failed to serialize timestamp")
44            }
45        }
46    }
47}
48
49impl Error for SerializationError {
50    fn source(&self) -> Option<&(dyn Error + 'static)> {
51        match &self.kind {
52            SerializationErrorKind::CannotSerializeUnknownVariant { .. } => None,
53            SerializationErrorKind::DateTimeFormatError { cause } => Some(cause as _),
54        }
55    }
56}
57
58impl From<DateTimeFormatError> for SerializationError {
59    fn from(err: DateTimeFormatError) -> SerializationError {
60        Self {
61            kind: SerializationErrorKind::DateTimeFormatError { cause: err },
62        }
63    }
64}
65
66#[derive(Debug)]
67enum BuildErrorKind {
68    /// A field contained an invalid value
69    InvalidField {
70        field: &'static str,
71        details: String,
72    },
73    /// A field was missing
74    MissingField {
75        field: &'static str,
76        details: &'static str,
77    },
78    /// The serializer could not serialize the input
79    SerializationError(SerializationError),
80
81    /// An error occurred request construction
82    Other(Box<dyn Error + Send + Sync + 'static>),
83}
84
85/// An error occurred attempting to build an `Operation` from an input
86///
87/// These are almost always due to user error caused by limitations of specific fields due to
88/// protocol serialization (e.g. fields that can only be a subset ASCII because they are serialized
89/// as the name of an HTTP header)
90#[derive(Debug)]
91pub struct BuildError {
92    kind: BuildErrorKind,
93}
94
95impl BuildError {
96    /// Construct a build error for a missing field
97    pub fn missing_field(field: &'static str, details: &'static str) -> Self {
98        Self {
99            kind: BuildErrorKind::MissingField { field, details },
100        }
101    }
102
103    /// Construct a build error for an invalid field
104    pub fn invalid_field(field: &'static str, details: impl Into<String>) -> Self {
105        Self {
106            kind: BuildErrorKind::InvalidField {
107                field,
108                details: details.into(),
109            },
110        }
111    }
112
113    /// Construct a build error from another underlying error
114    pub fn other(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
115        Self {
116            kind: BuildErrorKind::Other(source.into()),
117        }
118    }
119}
120
121impl From<SerializationError> for BuildError {
122    fn from(err: SerializationError) -> Self {
123        Self {
124            kind: BuildErrorKind::SerializationError(err),
125        }
126    }
127}
128
129impl From<DateTimeFormatError> for BuildError {
130    fn from(err: DateTimeFormatError) -> Self {
131        Self::from(SerializationError::from(err))
132    }
133}
134
135impl Display for BuildError {
136    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
137        match &self.kind {
138            BuildErrorKind::InvalidField { field, details } => {
139                write!(f, "invalid field in input: {field} (details: {details})")
140            }
141            BuildErrorKind::MissingField { field, details } => {
142                write!(f, "{field} was missing: {details}")
143            }
144            BuildErrorKind::SerializationError(_) => {
145                write!(f, "failed to serialize input")
146            }
147            BuildErrorKind::Other(_) => {
148                write!(f, "error during request construction")
149            }
150        }
151    }
152}
153
154impl Error for BuildError {
155    fn source(&self) -> Option<&(dyn Error + 'static)> {
156        match &self.kind {
157            BuildErrorKind::SerializationError(source) => Some(source as _),
158            BuildErrorKind::Other(source) => Some(source.as_ref()),
159            BuildErrorKind::InvalidField { .. } | BuildErrorKind::MissingField { .. } => None,
160        }
161    }
162}