1mod payload {
13 use serde::{Deserialize, Deserializer, Serializer};
14
15 pub fn serialize<S: Serializer>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
16 serializer.serialize_bytes(bytes)
17 }
18
19 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<&'de [u8], D::Error> {
20 <&[u8]>::deserialize(deserializer)
21 }
22}
23
24use serde::{Deserialize, Serialize};
32use super::{WireAnswer, WireChild, WireChildAction, WireChildCall, WireChildControl, WireCommand};
34
35const VERSION: u8 = 6;
38pub(super) const LIMIT: usize = 16 * 1024 * 1024;
39
40#[derive(Serialize, Deserialize)]
47struct Value<'a> {
48 key: &'a str,
49
50 #[serde(borrow, with = "payload")]
51 payload: &'a [u8],
52}
53
54#[derive(Debug, thiserror::Error)]
57pub enum WireCodecError {
58 #[error("operation envelope exceeds the 16 MiB limit")]
59 Oversized,
60
61 #[error("unsupported operation envelope version")]
62 Version,
63
64 #[error("unexpected operation envelope kind")]
65 Kind,
66
67 #[error("trailing operation envelope bytes")]
68 Trailing,
69
70 #[error("invalid operation envelope")]
71 Encoding(#[from] postcard::Error),
72}
73
74#[derive(Serialize, Deserialize)]
77enum Envelope<'a> {
78 Prepare {
79 invocation: u64,
80 operation: &'a str,
81
82 #[serde(borrow, with = "payload")]
83 payload: &'a [u8],
84 },
85 Initialize {
86 invocation: u64,
87 context: [u8; 32],
88 },
89 Attempt {
90 invocation: u64,
91 context: [u8; 32],
92
93 #[serde(borrow)]
94 values: Vec<Value<'a>>,
95 },
96 Finalize {
97 invocation: u64,
98 },
99 Ready {
100 #[serde(borrow, with = "payload")]
101 payload: &'a [u8],
102 },
103 Failed {
104 failure: crate::Failure,
105 },
106 Child {
107 context: [u8; 32],
108 generation_context: Option<[u8; 32]>,
109
110 #[serde(borrow)]
111 values: Vec<Value<'a>>,
112
113 operation: &'a str,
114
115 #[serde(borrow, with = "payload")]
116 payload: &'a [u8],
117
118 submit: bool,
119 },
120 PrepareGrpc {
121 invocation: u64,
122 operation: &'a str,
123
124 #[serde(borrow, with = "payload")]
125 payload: &'a [u8],
126 },
127 StreamAttempt {
128 invocation: u64,
129 epoch: u64,
130 context: [u8; 32],
131
132 #[serde(borrow)]
133 values: Vec<Value<'a>>,
134 },
135 StreamSend {
136 invocation: u64,
137 epoch: u64,
138
139 #[serde(borrow, with = "payload")]
140 payload: &'a [u8],
141 },
142 StreamFinish {
143 invocation: u64,
144 epoch: u64,
145 },
146 StreamReceive {
147 invocation: u64,
148 epoch: u64,
149 },
150 StreamItem {
151 epoch: u64,
152 transferred: bool,
153
154 #[serde(borrow, with = "payload")]
155 payload: &'a [u8],
156 },
157 StreamEnd {
158 epoch: u64,
159 transferred: bool,
160 },
161 ChildControl {
162 context: [u8; 32],
163 instance: u64,
164 action: WireChildAction,
165 },
166}
167
168impl WireCommand {
173 pub fn encode(&self) -> Result<Vec<u8>, WireCodecError> {
174 encode(self.envelope())
175 }
176
177 pub fn decode(bytes: &[u8]) -> Result<Self, WireCodecError> {
178 Ok(match decode(bytes)? {
179 Envelope::Prepare { invocation, operation, payload } => {
180 Self::Prepare { invocation, operation: operation.to_owned(), payload: payload.to_vec() }
181 }
182 Envelope::PrepareGrpc { invocation, operation, payload } => {
183 Self::PrepareGrpc { invocation, operation: operation.to_owned(), payload: payload.to_vec() }
184 }
185 Envelope::Initialize { invocation, context } => Self::Initialize { invocation, context },
186 Envelope::Attempt { invocation, context, values } => Self::Attempt { invocation, context, values: owned(values)? },
187 Envelope::Finalize { invocation } => Self::Finalize { invocation },
188 Envelope::StreamAttempt { invocation, epoch, context, values } => {
189 Self::StreamAttempt { invocation, epoch, context, values: owned(values)? }
190 }
191 Envelope::StreamSend { invocation, epoch, payload } => Self::StreamSend { invocation, epoch, payload: payload.to_vec() },
192 Envelope::StreamFinish { invocation, epoch } => Self::StreamFinish { invocation, epoch },
193 Envelope::StreamReceive { invocation, epoch } => Self::StreamReceive { invocation, epoch },
194 _ => return Err(WireCodecError::Kind),
195 })
196 }
197
198 fn envelope(&self) -> Envelope<'_> {
199 match self {
200 Self::Prepare { invocation, operation, payload } => Envelope::Prepare { invocation: *invocation, operation, payload },
201 Self::PrepareGrpc { invocation, operation, payload } => Envelope::PrepareGrpc { invocation: *invocation, operation, payload },
202 Self::Initialize { invocation, context } => Envelope::Initialize { invocation: *invocation, context: *context },
203 Self::Attempt { invocation, context, values } => {
204 Envelope::Attempt { invocation: *invocation, context: *context, values: borrowed(values) }
205 }
206 Self::StreamAttempt { invocation, epoch, context, values } => {
207 Envelope::StreamAttempt { invocation: *invocation, epoch: *epoch, context: *context, values: borrowed(values) }
208 }
209 Self::StreamSend { invocation, epoch, payload } => Envelope::StreamSend { invocation: *invocation, epoch: *epoch, payload },
210 Self::StreamFinish { invocation, epoch } => Envelope::StreamFinish { invocation: *invocation, epoch: *epoch },
211 Self::StreamReceive { invocation, epoch } => Envelope::StreamReceive { invocation: *invocation, epoch: *epoch },
212 Self::Finalize { invocation } => Envelope::Finalize { invocation: *invocation },
213 }
214 }
215}
216
217impl WireAnswer {
218 pub fn encode(&self) -> Result<Vec<u8>, WireCodecError> {
219 let envelope = match self {
220 Self::Ready { payload } => Envelope::Ready { payload },
221 Self::Stream { epoch, transferred, payload: Some(payload) } => {
222 Envelope::StreamItem { epoch: *epoch, transferred: *transferred, payload }
223 }
224 Self::Stream { epoch, transferred, payload: None } => Envelope::StreamEnd { epoch: *epoch, transferred: *transferred },
225 Self::Failed { failure } => Envelope::Failed { failure: failure.clone() },
226 };
227 encode(envelope)
228 }
229
230 pub fn decode(bytes: &[u8]) -> Result<Self, WireCodecError> {
231 Ok(match decode(bytes)? {
232 Envelope::StreamItem { epoch, transferred, payload } => Self::Stream { epoch, transferred, payload: Some(payload.to_vec()) },
233 Envelope::StreamEnd { epoch, transferred } => Self::Stream { epoch, transferred, payload: None },
234 Envelope::Ready { payload } => Self::Ready { payload: payload.to_vec() },
235 Envelope::Failed { failure } => Self::Failed { failure },
236 _ => return Err(WireCodecError::Kind),
237 })
238 }
239}
240
241impl WireChildCall {
242 pub fn encode(&self) -> Result<Vec<u8>, WireCodecError> {
243 check_values(&self.values)?;
244 encode(Envelope::Child {
245 context: self.context,
246 generation_context: self.generation_context,
247 values: borrowed(&self.values),
248 operation: &self.operation,
249 payload: &self.payload,
250 submit: self.submit,
251 })
252 }
253
254 pub fn decode(bytes: &[u8]) -> Result<Self, WireCodecError> {
255 match WireChild::decode(bytes)? {
256 WireChild::Call(call) => Ok(call),
257 WireChild::Control(_) => Err(WireCodecError::Kind),
258 }
259 }
260}
261
262impl WireChildControl {
263 pub fn encode(&self) -> Result<Vec<u8>, WireCodecError> {
264 encode(Envelope::ChildControl { context: self.context, instance: self.instance, action: self.action })
265 }
266}
267
268impl WireChild {
269 pub fn decode(bytes: &[u8]) -> Result<Self, WireCodecError> {
270 let child = match decode(bytes)? {
271 Envelope::Child { context, generation_context, values, operation, payload, submit } => Self::Call(WireChildCall {
272 context,
273 generation_context,
274 values: owned(values)?,
275 operation: operation.to_owned(),
276 payload: payload.to_vec(),
277 submit,
278 }),
279 Envelope::ChildControl { context, instance, action } => Self::Control(WireChildControl { context, instance, action }),
280 _ => return Err(WireCodecError::Kind),
281 };
282 Ok(child)
283 }
284
285 pub fn context(&self) -> &[u8; 32] {
286 match self {
287 Self::Call(call) => &call.context,
288 Self::Control(control) => &control.context,
289 }
290 }
291}
292
293fn check_values(values: &[super::super::CallValue]) -> Result<(), WireCodecError> {
298 let bytes = values.iter().map(|value| value.key.len().saturating_add(value.payload.len())).fold(0usize, usize::saturating_add);
299 if values.len() > super::super::PORTABLE_VALUES || bytes > super::super::PORTABLE_BYTES {
300 return Err(WireCodecError::Oversized);
301 }
302 for (index, value) in values.iter().enumerate() {
303 if values[..index].iter().any(|previous| previous.key == value.key) {
304 return Err(WireCodecError::Kind);
305 }
306 }
307 Ok(())
308}
309
310fn borrowed(values: &[super::super::CallValue]) -> Vec<Value<'_>> {
311 values.iter().map(|value| Value { key: &value.key, payload: &value.payload }).collect()
312}
313
314fn owned(values: Vec<Value<'_>>) -> Result<Vec<super::super::CallValue>, WireCodecError> {
315 let bytes = values.iter().map(|value| value.key.len() + value.payload.len()).sum::<usize>();
316 if values.len() > super::super::PORTABLE_VALUES || bytes > super::super::PORTABLE_BYTES {
317 return Err(WireCodecError::Oversized);
318 }
319 Ok(values.into_iter().map(|value| super::super::CallValue { key: value.key.to_owned(), payload: value.payload.to_vec() }).collect())
320}
321
322fn encode(envelope: Envelope<'_>) -> Result<Vec<u8>, WireCodecError> {
323 let message = (VERSION, envelope);
324 let size = postcard::experimental::serialized_size(&message)?;
325 if size > LIMIT {
326 return Err(WireCodecError::Oversized);
327 }
328 Ok(postcard::to_allocvec(&message)?)
329}
330
331fn decode(bytes: &[u8]) -> Result<Envelope<'_>, WireCodecError> {
332 if bytes.len() > LIMIT {
333 return Err(WireCodecError::Oversized);
334 }
335 let (version, rest) = postcard::take_from_bytes::<u8>(bytes)?;
336 if version != VERSION {
337 return Err(WireCodecError::Version);
338 }
339 let (envelope, rest) = postcard::take_from_bytes::<Envelope<'_>>(rest)?;
340 if !rest.is_empty() {
341 return Err(WireCodecError::Trailing);
342 }
343 Ok(envelope)
344}
345
346