1 + | // Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
|
2 + | /// Wrapper for event stream messages that may be signed
|
3 + | #[derive(Debug)]
|
4 + | pub struct SignedEvent<T> {
|
5 + | /// The actual event message
|
6 + | pub message: T,
|
7 + | /// Signature information if the message was signed
|
8 + | pub signature: ::std::option::Option<crate::sigv4_event_stream::SignatureInfo>,
|
9 + | }
|
10 + |
|
11 + | /// Error wrapper for signed event stream errors
|
12 + | #[derive(Debug)]
|
13 + | pub enum SignedEventError<E> {
|
14 + | /// Error from the underlying event stream
|
15 + | Event(E),
|
16 + | /// Error extracting signed message
|
17 + | InvalidSignedEvent(crate::sigv4_event_stream::ExtractionError),
|
18 + | }
|
19 + |
|
20 + | impl<E> From<E> for SignedEventError<E> {
|
21 + | fn from(err: E) -> Self {
|
22 + | SignedEventError::Event(err)
|
23 + | }
|
24 + | }
|
25 + |
|
26 + | /// Information extracted from a signed event stream message
|
27 + | #[non_exhaustive]
|
28 + | #[derive(Debug, Clone)]
|
29 + | pub struct SignatureInfo {
|
30 + | /// The chunk signature bytes from the `:chunk-signature` header
|
31 + | pub chunk_signature: Vec<u8>,
|
32 + | /// The timestamp from the `:date` header
|
33 + | pub timestamp: ::std::time::SystemTime,
|
34 + | }
|
35 + |
|
36 + | /// Error type for signed message extraction operations
|
37 + | #[non_exhaustive]
|
38 + | #[derive(Debug)]
|
39 + | pub enum ExtractionError {
|
40 + | /// The payload could not be decoded as a valid message
|
41 + | #[non_exhaustive]
|
42 + | InvalidPayload {
|
43 + | error: ::aws_smithy_eventstream::error::Error,
|
44 + | },
|
45 + | /// The timestamp header is missing or has an invalid format
|
46 + | #[non_exhaustive]
|
47 + | InvalidTimestamp,
|
48 + | }
|
49 + |
|
50 + | /// Unmarshaller wrapper that handles SigV4 signed event stream messages
|
51 + | #[derive(Debug)]
|
52 + | pub struct SigV4Unmarshaller<T> {
|
53 + | inner: T,
|
54 + | }
|
55 + |
|
56 + | impl<T> SigV4Unmarshaller<T> {
|
57 + | pub fn new(inner: T) -> Self {
|
58 + | Self { inner }
|
59 + | }
|
60 + | }
|
61 + |
|
62 + | impl<T> ::aws_smithy_eventstream::frame::UnmarshallMessage for SigV4Unmarshaller<T>
|
63 + | where
|
64 + | T: ::aws_smithy_eventstream::frame::UnmarshallMessage,
|
65 + | {
|
66 + | type Output = crate::sigv4_event_stream::SignedEvent<T::Output>;
|
67 + | type Error = crate::sigv4_event_stream::SignedEventError<T::Error>;
|
68 + |
|
69 + | fn unmarshall(
|
70 + | &self,
|
71 + | message: &::aws_smithy_types::event_stream::Message,
|
72 + | ) -> ::std::result::Result<
|
73 + | ::aws_smithy_eventstream::frame::UnmarshalledMessage<Self::Output, Self::Error>,
|
74 + | ::aws_smithy_eventstream::error::Error,
|
75 + | > {
|
76 + | // First, try to extract the signed message
|
77 + | match crate::sigv4_event_stream::extract_signed_message(message) {
|
78 + | Ok(MaybeSignedMessage::Signed {
|
79 + | message: inner_message,
|
80 + | signature,
|
81 + | }) => {
|
82 + | // Process the inner message with the base unmarshaller
|
83 + | match self.inner.unmarshall(&inner_message) {
|
84 + | Ok(unmarshalled) => match unmarshalled {
|
85 + | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(event) => {
|
86 + | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(
|
87 + | crate::sigv4_event_stream::SignedEvent {
|
88 + | message: event,
|
89 + | signature: Some(signature),
|
90 + | },
|
91 + | ))
|
92 + | }
|
93 + | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(err) => {
|
94 + | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
95 + | crate::sigv4_event_stream::SignedEventError::Event(err),
|
96 + | ))
|
97 + | }
|
98 + | },
|
99 + | Err(err) => Err(err),
|
100 + | }
|
101 + | }
|
102 + | Ok(MaybeSignedMessage::Unsigned) => {
|
103 + | // Process unsigned message directly
|
104 + | match self.inner.unmarshall(message) {
|
105 + | Ok(unmarshalled) => match unmarshalled {
|
106 + | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(event) => {
|
107 + | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(
|
108 + | crate::sigv4_event_stream::SignedEvent {
|
109 + | message: event,
|
110 + | signature: None,
|
111 + | },
|
112 + | ))
|
113 + | }
|
114 + | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(err) => {
|
115 + | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
116 + | crate::sigv4_event_stream::SignedEventError::Event(err),
|
117 + | ))
|
118 + | }
|
119 + | },
|
120 + | Err(err) => Err(err),
|
121 + | }
|
122 + | }
|
123 + | Err(extraction_err) => Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
124 + | crate::sigv4_event_stream::SignedEventError::InvalidSignedEvent(extraction_err),
|
125 + | )),
|
126 + | }
|
127 + | }
|
128 + | }
|
129 + |
|
130 + | /// Result of extracting a potentially signed message
|
131 + | #[derive(Debug)]
|
132 + | pub enum MaybeSignedMessage {
|
133 + | /// Message was signed and has been extracted
|
134 + | Signed {
|
135 + | /// The inner message that was signed
|
136 + | message: ::aws_smithy_types::event_stream::Message,
|
137 + | /// Signature information from the outer message
|
138 + | signature: crate::sigv4_event_stream::SignatureInfo,
|
139 + | },
|
140 + | /// Message was not signed (no `:chunk-signature` header present)
|
141 + | Unsigned,
|
142 + | }
|
143 + |
|
144 + | /// Extracts the inner message from a potentially signed event stream message.
|
145 + | pub fn extract_signed_message(
|
146 + | message: &::aws_smithy_types::event_stream::Message,
|
147 + | ) -> ::std::result::Result<MaybeSignedMessage, crate::sigv4_event_stream::ExtractionError> {
|
148 + | // Check if message has chunk signature
|
149 + | let mut chunk_signature = None;
|
150 + | let mut timestamp = None;
|
151 + |
|
152 + | for header in message.headers() {
|
153 + | match header.name().as_str() {
|
154 + | ":chunk-signature" => {
|
155 + | if let ::aws_smithy_types::event_stream::HeaderValue::ByteArray(bytes) =
|
156 + | header.value()
|
157 + | {
|
158 + | chunk_signature = Some(bytes.as_ref().to_vec());
|
159 + | }
|
160 + | }
|
161 + | ":date" => {
|
162 + | if let ::aws_smithy_types::event_stream::HeaderValue::Timestamp(ts) = header.value()
|
163 + | {
|
164 + | timestamp = Some(::std::time::SystemTime::try_from(*ts).map_err(|_err| {
|
165 + | crate::sigv4_event_stream::ExtractionError::InvalidTimestamp
|
166 + | })?);
|
167 + | } else {
|
168 + | return Err(crate::sigv4_event_stream::ExtractionError::InvalidTimestamp);
|
169 + | }
|
170 + | }
|
171 + | _ => {}
|
172 + | }
|
173 + | }
|
174 + |
|
175 + | let Some(chunk_signature) = chunk_signature else {
|
176 + | return Ok(MaybeSignedMessage::Unsigned);
|
177 + | };
|
178 + |
|
179 + | let Some(timestamp) = timestamp else {
|
180 + | return Err(crate::sigv4_event_stream::ExtractionError::InvalidTimestamp);
|
181 + | };
|
182 + |
|
183 + | // Extract inner message
|
184 + | let cursor = ::std::io::Cursor::new(message.payload());
|
185 + | let inner_message = ::aws_smithy_eventstream::frame::read_message_from(cursor)
|
186 + | .map_err(|err| crate::sigv4_event_stream::ExtractionError::InvalidPayload { error: err })?;
|
187 + |
|
188 + | Ok(MaybeSignedMessage::Signed {
|
189 + | message: inner_message,
|
190 + | signature: crate::sigv4_event_stream::SignatureInfo {
|
191 + | chunk_signature,
|
192 + | timestamp,
|
193 + | },
|
194 + | })
|
195 + | }
|