1use crate::generated_protocol::v1 as generated_protocol;
2use serde::de::{self, SeqAccess, Visitor};
3use serde::ser::SerializeTuple;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
7use std::error::Error;
8use std::fmt;
9
10pub use crate::wire::{OwnershipRequirement, ProtocolCodecError, RequestDirection};
11
12pub const PROTOCOL_NAME: &str = crate::wire::PROTOCOL_NAME;
13pub const PROTOCOL_VERSION: u16 = crate::wire::PROTOCOL_VERSION;
14pub const DEFAULT_MAX_FRAME_BYTES: usize = crate::wire::DEFAULT_MAX_FRAME_BYTES;
15pub const DEFAULT_COMPLETED_RESPONSE_CAP: usize = 10_000;
16pub type RequestId = crate::wire::RequestId;
17pub type ExtEnvelope = crate::wire::ExtEnvelope;
18
19fn serialize_bare_newtype_tag<S, T>(serializer: S, tag: u64, payload: &T) -> Result<S::Ok, S::Error>
20where
21 S: Serializer,
22 T: Serialize,
23{
24 let mut tuple = serializer.serialize_tuple(2)?;
25 tuple.serialize_element(&serde_bare::Uint(tag))?;
26 tuple.serialize_element(payload)?;
27 tuple.end()
28}
29
30pub fn to_generated_protocol_frame(
32 frame: &ProtocolFrame,
33) -> Result<generated_protocol::ProtocolFrame, ProtocolCodecError> {
34 Ok(match frame {
35 ProtocolFrame::Request(frame) => {
36 generated_protocol::ProtocolFrame::RequestFrame(generated_protocol::RequestFrame {
37 schema: to_generated_protocol_schema(&frame.schema),
38 request_id: frame.request_id,
39 ownership: to_generated_ownership_scope(&frame.ownership),
40 payload: to_generated_request_payload(&frame.payload)?,
41 })
42 }
43 ProtocolFrame::Response(frame) => {
44 generated_protocol::ProtocolFrame::ResponseFrame(generated_protocol::ResponseFrame {
45 schema: to_generated_protocol_schema(&frame.schema),
46 request_id: frame.request_id,
47 ownership: to_generated_ownership_scope(&frame.ownership),
48 payload: to_generated_response_payload(&frame.payload)?,
49 })
50 }
51 ProtocolFrame::Event(frame) => {
52 generated_protocol::ProtocolFrame::EventFrame(generated_protocol::EventFrame {
53 schema: to_generated_protocol_schema(&frame.schema),
54 ownership: to_generated_ownership_scope(&frame.ownership),
55 payload: to_generated_event_payload(&frame.payload),
56 })
57 }
58 ProtocolFrame::SidecarRequest(frame) => {
59 generated_protocol::ProtocolFrame::SidecarRequestFrame(
60 generated_protocol::SidecarRequestFrame {
61 schema: to_generated_protocol_schema(&frame.schema),
62 request_id: frame.request_id,
63 ownership: to_generated_ownership_scope(&frame.ownership),
64 payload: to_generated_sidecar_request_payload(&frame.payload)?,
65 },
66 )
67 }
68 ProtocolFrame::SidecarResponse(frame) => {
69 generated_protocol::ProtocolFrame::SidecarResponseFrame(
70 generated_protocol::SidecarResponseFrame {
71 schema: to_generated_protocol_schema(&frame.schema),
72 request_id: frame.request_id,
73 ownership: to_generated_ownership_scope(&frame.ownership),
74 payload: to_generated_sidecar_response_payload(&frame.payload)?,
75 },
76 )
77 }
78 })
79}
80
81pub fn from_generated_protocol_frame(
83 frame: generated_protocol::ProtocolFrame,
84) -> Result<ProtocolFrame, ProtocolCodecError> {
85 Ok(match frame {
86 generated_protocol::ProtocolFrame::RequestFrame(frame) => {
87 ProtocolFrame::Request(RequestFrame {
88 schema: from_generated_protocol_schema(frame.schema),
89 request_id: frame.request_id,
90 ownership: from_generated_ownership_scope(frame.ownership),
91 payload: from_generated_request_payload(frame.payload)?,
92 })
93 }
94 generated_protocol::ProtocolFrame::ResponseFrame(frame) => {
95 ProtocolFrame::Response(ResponseFrame {
96 schema: from_generated_protocol_schema(frame.schema),
97 request_id: frame.request_id,
98 ownership: from_generated_ownership_scope(frame.ownership),
99 payload: from_generated_response_payload(frame.payload)?,
100 })
101 }
102 generated_protocol::ProtocolFrame::EventFrame(frame) => ProtocolFrame::Event(EventFrame {
103 schema: from_generated_protocol_schema(frame.schema),
104 ownership: from_generated_ownership_scope(frame.ownership),
105 payload: from_generated_event_payload(frame.payload),
106 }),
107 generated_protocol::ProtocolFrame::SidecarRequestFrame(frame) => {
108 ProtocolFrame::SidecarRequest(SidecarRequestFrame {
109 schema: from_generated_protocol_schema(frame.schema),
110 request_id: frame.request_id,
111 ownership: from_generated_ownership_scope(frame.ownership),
112 payload: from_generated_sidecar_request_payload(frame.payload)?,
113 })
114 }
115 generated_protocol::ProtocolFrame::SidecarResponseFrame(frame) => {
116 ProtocolFrame::SidecarResponse(SidecarResponseFrame {
117 schema: from_generated_protocol_schema(frame.schema),
118 request_id: frame.request_id,
119 ownership: from_generated_ownership_scope(frame.ownership),
120 payload: from_generated_sidecar_response_payload(frame.payload)?,
121 })
122 }
123 })
124}
125
126fn to_generated_protocol_schema(schema: &ProtocolSchema) -> generated_protocol::ProtocolSchema {
127 schema.clone()
128}
129
130fn from_generated_protocol_schema(schema: generated_protocol::ProtocolSchema) -> ProtocolSchema {
131 schema
132}
133
134pub(crate) fn to_generated_ownership_scope(
139 ownership: &OwnershipScope,
140) -> generated_protocol::OwnershipScope {
141 ownership.clone()
142}
143
144pub(crate) fn from_generated_ownership_scope(
145 ownership: generated_protocol::OwnershipScope,
146) -> OwnershipScope {
147 ownership
148}
149
150fn to_generated_dispose_reason(reason: &DisposeReason) -> generated_protocol::DisposeReason {
151 match reason {
152 DisposeReason::Requested => generated_protocol::DisposeReason::Requested,
153 DisposeReason::ConnectionClosed => generated_protocol::DisposeReason::ConnectionClosed,
154 DisposeReason::HostShutdown => generated_protocol::DisposeReason::HostShutdown,
155 }
156}
157
158fn from_generated_dispose_reason(reason: generated_protocol::DisposeReason) -> DisposeReason {
159 match reason {
160 generated_protocol::DisposeReason::Requested => DisposeReason::Requested,
161 generated_protocol::DisposeReason::ConnectionClosed => DisposeReason::ConnectionClosed,
162 generated_protocol::DisposeReason::HostShutdown => DisposeReason::HostShutdown,
163 }
164}
165
166fn to_generated_filesystem_operation(
167 operation: &FilesystemOperation,
168) -> generated_protocol::FilesystemOperation {
169 match operation {
170 FilesystemOperation::Read => generated_protocol::FilesystemOperation::Read,
171 FilesystemOperation::Write => generated_protocol::FilesystemOperation::Write,
172 FilesystemOperation::Stat => generated_protocol::FilesystemOperation::Stat,
173 FilesystemOperation::ReadDir => generated_protocol::FilesystemOperation::ReadDir,
174 FilesystemOperation::Mkdir => generated_protocol::FilesystemOperation::Mkdir,
175 FilesystemOperation::Remove => generated_protocol::FilesystemOperation::Remove,
176 FilesystemOperation::Rename => generated_protocol::FilesystemOperation::Rename,
177 }
178}
179
180fn from_generated_filesystem_operation(
181 operation: generated_protocol::FilesystemOperation,
182) -> FilesystemOperation {
183 match operation {
184 generated_protocol::FilesystemOperation::Read => FilesystemOperation::Read,
185 generated_protocol::FilesystemOperation::Write => FilesystemOperation::Write,
186 generated_protocol::FilesystemOperation::Stat => FilesystemOperation::Stat,
187 generated_protocol::FilesystemOperation::ReadDir => FilesystemOperation::ReadDir,
188 generated_protocol::FilesystemOperation::Mkdir => FilesystemOperation::Mkdir,
189 generated_protocol::FilesystemOperation::Remove => FilesystemOperation::Remove,
190 generated_protocol::FilesystemOperation::Rename => FilesystemOperation::Rename,
191 }
192}
193
194fn to_generated_guest_filesystem_operation(
195 operation: &GuestFilesystemOperation,
196) -> generated_protocol::GuestFilesystemOperation {
197 match operation {
198 GuestFilesystemOperation::ReadFile => {
199 generated_protocol::GuestFilesystemOperation::ReadFile
200 }
201 GuestFilesystemOperation::WriteFile => {
202 generated_protocol::GuestFilesystemOperation::WriteFile
203 }
204 GuestFilesystemOperation::CreateDir => {
205 generated_protocol::GuestFilesystemOperation::CreateDir
206 }
207 GuestFilesystemOperation::Mkdir => generated_protocol::GuestFilesystemOperation::Mkdir,
208 GuestFilesystemOperation::Exists => generated_protocol::GuestFilesystemOperation::Exists,
209 GuestFilesystemOperation::Stat => generated_protocol::GuestFilesystemOperation::Stat,
210 GuestFilesystemOperation::Lstat => generated_protocol::GuestFilesystemOperation::Lstat,
211 GuestFilesystemOperation::ReadDir => generated_protocol::GuestFilesystemOperation::ReadDir,
212 GuestFilesystemOperation::ReadDirRecursive => {
213 generated_protocol::GuestFilesystemOperation::ReadDirRecursive
214 }
215 GuestFilesystemOperation::RemoveFile => {
216 generated_protocol::GuestFilesystemOperation::RemoveFile
217 }
218 GuestFilesystemOperation::RemoveDir => {
219 generated_protocol::GuestFilesystemOperation::RemoveDir
220 }
221 GuestFilesystemOperation::Remove => generated_protocol::GuestFilesystemOperation::Remove,
222 GuestFilesystemOperation::Copy => generated_protocol::GuestFilesystemOperation::Copy,
223 GuestFilesystemOperation::Move => generated_protocol::GuestFilesystemOperation::Move,
224 GuestFilesystemOperation::Rename => generated_protocol::GuestFilesystemOperation::Rename,
225 GuestFilesystemOperation::Realpath => {
226 generated_protocol::GuestFilesystemOperation::Realpath
227 }
228 GuestFilesystemOperation::Symlink => generated_protocol::GuestFilesystemOperation::Symlink,
229 GuestFilesystemOperation::ReadLink => {
230 generated_protocol::GuestFilesystemOperation::ReadLink
231 }
232 GuestFilesystemOperation::Link => generated_protocol::GuestFilesystemOperation::Link,
233 GuestFilesystemOperation::Chmod => generated_protocol::GuestFilesystemOperation::Chmod,
234 GuestFilesystemOperation::Chown => generated_protocol::GuestFilesystemOperation::Chown,
235 GuestFilesystemOperation::Utimes => generated_protocol::GuestFilesystemOperation::Utimes,
236 GuestFilesystemOperation::Truncate => {
237 generated_protocol::GuestFilesystemOperation::Truncate
238 }
239 GuestFilesystemOperation::Pread => generated_protocol::GuestFilesystemOperation::Pread,
240 GuestFilesystemOperation::Pwrite => generated_protocol::GuestFilesystemOperation::Pwrite,
241 }
242}
243
244fn from_generated_guest_filesystem_operation(
245 operation: generated_protocol::GuestFilesystemOperation,
246) -> GuestFilesystemOperation {
247 match operation {
248 generated_protocol::GuestFilesystemOperation::ReadFile => {
249 GuestFilesystemOperation::ReadFile
250 }
251 generated_protocol::GuestFilesystemOperation::WriteFile => {
252 GuestFilesystemOperation::WriteFile
253 }
254 generated_protocol::GuestFilesystemOperation::CreateDir => {
255 GuestFilesystemOperation::CreateDir
256 }
257 generated_protocol::GuestFilesystemOperation::Mkdir => GuestFilesystemOperation::Mkdir,
258 generated_protocol::GuestFilesystemOperation::Exists => GuestFilesystemOperation::Exists,
259 generated_protocol::GuestFilesystemOperation::Stat => GuestFilesystemOperation::Stat,
260 generated_protocol::GuestFilesystemOperation::Lstat => GuestFilesystemOperation::Lstat,
261 generated_protocol::GuestFilesystemOperation::ReadDir => GuestFilesystemOperation::ReadDir,
262 generated_protocol::GuestFilesystemOperation::ReadDirRecursive => {
263 GuestFilesystemOperation::ReadDirRecursive
264 }
265 generated_protocol::GuestFilesystemOperation::RemoveFile => {
266 GuestFilesystemOperation::RemoveFile
267 }
268 generated_protocol::GuestFilesystemOperation::RemoveDir => {
269 GuestFilesystemOperation::RemoveDir
270 }
271 generated_protocol::GuestFilesystemOperation::Remove => GuestFilesystemOperation::Remove,
272 generated_protocol::GuestFilesystemOperation::Copy => GuestFilesystemOperation::Copy,
273 generated_protocol::GuestFilesystemOperation::Move => GuestFilesystemOperation::Move,
274 generated_protocol::GuestFilesystemOperation::Rename => GuestFilesystemOperation::Rename,
275 generated_protocol::GuestFilesystemOperation::Realpath => {
276 GuestFilesystemOperation::Realpath
277 }
278 generated_protocol::GuestFilesystemOperation::Symlink => GuestFilesystemOperation::Symlink,
279 generated_protocol::GuestFilesystemOperation::ReadLink => {
280 GuestFilesystemOperation::ReadLink
281 }
282 generated_protocol::GuestFilesystemOperation::Link => GuestFilesystemOperation::Link,
283 generated_protocol::GuestFilesystemOperation::Chmod => GuestFilesystemOperation::Chmod,
284 generated_protocol::GuestFilesystemOperation::Chown => GuestFilesystemOperation::Chown,
285 generated_protocol::GuestFilesystemOperation::Utimes => GuestFilesystemOperation::Utimes,
286 generated_protocol::GuestFilesystemOperation::Truncate => {
287 GuestFilesystemOperation::Truncate
288 }
289 generated_protocol::GuestFilesystemOperation::Pread => GuestFilesystemOperation::Pread,
290 generated_protocol::GuestFilesystemOperation::Pwrite => GuestFilesystemOperation::Pwrite,
291 }
292}
293
294fn to_generated_permission_mode(mode: &PermissionMode) -> generated_protocol::PermissionMode {
295 mode.clone()
296}
297
298fn from_generated_permission_mode(mode: generated_protocol::PermissionMode) -> PermissionMode {
299 mode
300}
301
302fn to_generated_root_filesystem_entry_encoding(
303 encoding: &RootFilesystemEntryEncoding,
304) -> generated_protocol::RootFilesystemEntryEncoding {
305 match encoding {
306 RootFilesystemEntryEncoding::Utf8 => generated_protocol::RootFilesystemEntryEncoding::Utf8,
307 RootFilesystemEntryEncoding::Base64 => {
308 generated_protocol::RootFilesystemEntryEncoding::Base64
309 }
310 }
311}
312
313fn from_generated_root_filesystem_entry_encoding(
314 encoding: generated_protocol::RootFilesystemEntryEncoding,
315) -> RootFilesystemEntryEncoding {
316 match encoding {
317 generated_protocol::RootFilesystemEntryEncoding::Utf8 => RootFilesystemEntryEncoding::Utf8,
318 generated_protocol::RootFilesystemEntryEncoding::Base64 => {
319 RootFilesystemEntryEncoding::Base64
320 }
321 }
322}
323
324fn to_generated_stream_channel(channel: &StreamChannel) -> generated_protocol::StreamChannel {
325 match channel {
326 StreamChannel::Stdout => generated_protocol::StreamChannel::Stdout,
327 StreamChannel::Stderr => generated_protocol::StreamChannel::Stderr,
328 }
329}
330
331fn from_generated_stream_channel(channel: generated_protocol::StreamChannel) -> StreamChannel {
332 match channel {
333 generated_protocol::StreamChannel::Stdout => StreamChannel::Stdout,
334 generated_protocol::StreamChannel::Stderr => StreamChannel::Stderr,
335 }
336}
337
338fn to_generated_vm_lifecycle_state(
339 state: &VmLifecycleState,
340) -> generated_protocol::VmLifecycleState {
341 match state {
342 VmLifecycleState::Creating => generated_protocol::VmLifecycleState::Creating,
343 VmLifecycleState::Ready => generated_protocol::VmLifecycleState::Ready,
344 VmLifecycleState::Disposing => generated_protocol::VmLifecycleState::Disposing,
345 VmLifecycleState::Disposed => generated_protocol::VmLifecycleState::Disposed,
346 VmLifecycleState::Failed => generated_protocol::VmLifecycleState::Failed,
347 }
348}
349
350fn from_generated_vm_lifecycle_state(
351 state: generated_protocol::VmLifecycleState,
352) -> VmLifecycleState {
353 match state {
354 generated_protocol::VmLifecycleState::Creating => VmLifecycleState::Creating,
355 generated_protocol::VmLifecycleState::Ready => VmLifecycleState::Ready,
356 generated_protocol::VmLifecycleState::Disposing => VmLifecycleState::Disposing,
357 generated_protocol::VmLifecycleState::Disposed => VmLifecycleState::Disposed,
358 generated_protocol::VmLifecycleState::Failed => VmLifecycleState::Failed,
359 }
360}
361
362fn to_generated_guest_filesystem_stat(
363 stat: &GuestFilesystemStat,
364) -> generated_protocol::GuestFilesystemStat {
365 stat.clone()
366}
367
368fn from_generated_guest_filesystem_stat(
369 stat: generated_protocol::GuestFilesystemStat,
370) -> GuestFilesystemStat {
371 stat
372}
373
374fn to_generated_process_snapshot_entry(
375 entry: &ProcessSnapshotEntry,
376) -> generated_protocol::ProcessSnapshotEntry {
377 entry.clone()
378}
379
380fn from_generated_process_snapshot_entry(
381 entry: generated_protocol::ProcessSnapshotEntry,
382) -> ProcessSnapshotEntry {
383 entry
384}
385
386fn to_generated_ext_envelope(envelope: &ExtEnvelope) -> generated_protocol::ExtEnvelope {
387 envelope.clone()
388}
389
390fn from_generated_ext_envelope(envelope: generated_protocol::ExtEnvelope) -> ExtEnvelope {
391 envelope
392}
393
394fn to_generated_request_payload(
395 payload: &RequestPayload,
396) -> Result<generated_protocol::RequestPayload, ProtocolCodecError> {
397 Ok(match payload {
398 RequestPayload::Authenticate(inner) => {
399 generated_protocol::RequestPayload::AuthenticateRequest(inner.clone())
400 }
401 RequestPayload::OpenSession(inner) => {
402 generated_protocol::RequestPayload::OpenSessionRequest(inner.clone())
403 }
404 RequestPayload::CreateVm(inner) => {
405 generated_protocol::RequestPayload::CreateVmRequest(inner.clone())
406 }
407 RequestPayload::DisposeVm(inner) => generated_protocol::RequestPayload::DisposeVmRequest(
408 generated_protocol::DisposeVmRequest {
409 reason: to_generated_dispose_reason(&inner.reason),
410 },
411 ),
412 RequestPayload::BootstrapRootFilesystem(inner) => {
413 generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner.clone())
414 }
415 RequestPayload::ConfigureVm(inner) => {
416 generated_protocol::RequestPayload::ConfigureVmRequest(inner.clone())
417 }
418 RequestPayload::RegisterHostCallbacks(inner) => {
419 generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner.clone())
420 }
421 RequestPayload::CreateLayer(_) => generated_protocol::RequestPayload::CreateLayerRequest,
422 RequestPayload::SealLayer(inner) => {
423 generated_protocol::RequestPayload::SealLayerRequest(inner.clone())
424 }
425 RequestPayload::ImportSnapshot(inner) => {
426 generated_protocol::RequestPayload::ImportSnapshotRequest(inner.clone())
427 }
428 RequestPayload::ExportSnapshot(inner) => {
429 generated_protocol::RequestPayload::ExportSnapshotRequest(inner.clone())
430 }
431 RequestPayload::CreateOverlay(inner) => {
432 generated_protocol::RequestPayload::CreateOverlayRequest(inner.clone())
433 }
434 RequestPayload::GuestFilesystemCall(inner) => {
435 generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner.clone())
436 }
437 RequestPayload::SnapshotRootFilesystem(_) => {
438 generated_protocol::RequestPayload::SnapshotRootFilesystemRequest
439 }
440 RequestPayload::Execute(inner) => {
441 generated_protocol::RequestPayload::ExecuteRequest(inner.clone())
442 }
443 RequestPayload::WriteStdin(inner) => {
444 generated_protocol::RequestPayload::WriteStdinRequest(inner.clone())
445 }
446 RequestPayload::CloseStdin(inner) => {
447 generated_protocol::RequestPayload::CloseStdinRequest(inner.clone())
448 }
449 RequestPayload::KillProcess(inner) => {
450 generated_protocol::RequestPayload::KillProcessRequest(inner.clone())
451 }
452 RequestPayload::GetProcessSnapshot(_) => {
453 generated_protocol::RequestPayload::GetProcessSnapshotRequest
454 }
455 RequestPayload::GetResourceSnapshot(_) => {
456 generated_protocol::RequestPayload::GetResourceSnapshotRequest
457 }
458 RequestPayload::FindListener(inner) => {
459 generated_protocol::RequestPayload::FindListenerRequest(inner.clone())
460 }
461 RequestPayload::FindBoundUdp(inner) => {
462 generated_protocol::RequestPayload::FindBoundUdpRequest(inner.clone())
463 }
464 RequestPayload::VmFetch(inner) => {
465 generated_protocol::RequestPayload::VmFetchRequest(inner.clone())
466 }
467 RequestPayload::GetSignalState(inner) => {
468 generated_protocol::RequestPayload::GetSignalStateRequest(inner.clone())
469 }
470 RequestPayload::GetZombieTimerCount(_) => {
471 generated_protocol::RequestPayload::GetZombieTimerCountRequest
472 }
473 RequestPayload::HostFilesystemCall(inner) => {
474 generated_protocol::RequestPayload::HostFilesystemCallRequest(
475 generated_protocol::HostFilesystemCallRequest {
476 operation: to_generated_filesystem_operation(&inner.operation),
477 path: inner.path.clone(),
478 payload_size_bytes: inner.payload_size_bytes,
479 },
480 )
481 }
482 RequestPayload::PersistenceLoad(inner) => {
483 generated_protocol::RequestPayload::PersistenceLoadRequest(inner.clone())
484 }
485 RequestPayload::PersistenceFlush(inner) => {
486 generated_protocol::RequestPayload::PersistenceFlushRequest(inner.clone())
487 }
488 RequestPayload::Ext(inner) => {
489 generated_protocol::RequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
490 }
491 RequestPayload::GuestKernelCall(inner) => {
492 generated_protocol::RequestPayload::GuestKernelCallRequest(inner.clone())
493 }
494 RequestPayload::ResizePty(inner) => {
495 generated_protocol::RequestPayload::ResizePtyRequest(inner.clone())
496 }
497 RequestPayload::LinkPackage(inner) => {
498 generated_protocol::RequestPayload::LinkPackageRequest(inner.clone())
499 }
500 RequestPayload::ProvidedCommands(_) => {
501 generated_protocol::RequestPayload::ProvidedCommandsRequest
502 }
503 })
504}
505
506fn from_generated_request_payload(
507 payload: generated_protocol::RequestPayload,
508) -> Result<RequestPayload, ProtocolCodecError> {
509 Ok(match payload {
510 generated_protocol::RequestPayload::AuthenticateRequest(inner) => {
511 RequestPayload::Authenticate(inner)
512 }
513 generated_protocol::RequestPayload::OpenSessionRequest(inner) => {
514 RequestPayload::OpenSession(inner)
515 }
516 generated_protocol::RequestPayload::CreateVmRequest(inner) => {
517 RequestPayload::CreateVm(inner)
518 }
519 generated_protocol::RequestPayload::DisposeVmRequest(inner) => {
520 RequestPayload::DisposeVm(DisposeVmRequest {
521 reason: from_generated_dispose_reason(inner.reason),
522 })
523 }
524 generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner) => {
525 RequestPayload::BootstrapRootFilesystem(inner)
526 }
527 generated_protocol::RequestPayload::ConfigureVmRequest(inner) => {
528 RequestPayload::ConfigureVm(inner)
529 }
530 generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner) => {
531 RequestPayload::RegisterHostCallbacks(inner)
532 }
533 generated_protocol::RequestPayload::CreateLayerRequest => {
534 RequestPayload::CreateLayer(CreateLayerRequest {})
535 }
536 generated_protocol::RequestPayload::SealLayerRequest(inner) => {
537 RequestPayload::SealLayer(inner)
538 }
539 generated_protocol::RequestPayload::ImportSnapshotRequest(inner) => {
540 RequestPayload::ImportSnapshot(inner)
541 }
542 generated_protocol::RequestPayload::ExportSnapshotRequest(inner) => {
543 RequestPayload::ExportSnapshot(inner)
544 }
545 generated_protocol::RequestPayload::CreateOverlayRequest(inner) => {
546 RequestPayload::CreateOverlay(inner)
547 }
548 generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner) => {
549 RequestPayload::GuestFilesystemCall(inner)
550 }
551 generated_protocol::RequestPayload::SnapshotRootFilesystemRequest => {
552 RequestPayload::SnapshotRootFilesystem(SnapshotRootFilesystemRequest {})
553 }
554 generated_protocol::RequestPayload::ExecuteRequest(inner) => RequestPayload::Execute(inner),
555 generated_protocol::RequestPayload::WriteStdinRequest(inner) => {
556 RequestPayload::WriteStdin(inner)
557 }
558 generated_protocol::RequestPayload::CloseStdinRequest(inner) => {
559 RequestPayload::CloseStdin(inner)
560 }
561 generated_protocol::RequestPayload::KillProcessRequest(inner) => {
562 RequestPayload::KillProcess(inner)
563 }
564 generated_protocol::RequestPayload::GetProcessSnapshotRequest => {
565 RequestPayload::GetProcessSnapshot(GetProcessSnapshotRequest {})
566 }
567 generated_protocol::RequestPayload::GetResourceSnapshotRequest => {
568 RequestPayload::GetResourceSnapshot(GetResourceSnapshotRequest {})
569 }
570 generated_protocol::RequestPayload::FindListenerRequest(inner) => {
571 RequestPayload::FindListener(inner)
572 }
573 generated_protocol::RequestPayload::FindBoundUdpRequest(inner) => {
574 RequestPayload::FindBoundUdp(inner)
575 }
576 generated_protocol::RequestPayload::VmFetchRequest(inner) => RequestPayload::VmFetch(inner),
577 generated_protocol::RequestPayload::GetSignalStateRequest(inner) => {
578 RequestPayload::GetSignalState(inner)
579 }
580 generated_protocol::RequestPayload::GetZombieTimerCountRequest => {
581 RequestPayload::GetZombieTimerCount(GetZombieTimerCountRequest {})
582 }
583 generated_protocol::RequestPayload::HostFilesystemCallRequest(inner) => {
584 RequestPayload::HostFilesystemCall(HostFilesystemCallRequest {
585 operation: from_generated_filesystem_operation(inner.operation),
586 path: inner.path,
587 payload_size_bytes: inner.payload_size_bytes,
588 })
589 }
590 generated_protocol::RequestPayload::PersistenceLoadRequest(inner) => {
591 RequestPayload::PersistenceLoad(inner)
592 }
593 generated_protocol::RequestPayload::PersistenceFlushRequest(inner) => {
594 RequestPayload::PersistenceFlush(inner)
595 }
596 generated_protocol::RequestPayload::ExtEnvelope(inner) => {
597 RequestPayload::Ext(from_generated_ext_envelope(inner))
598 }
599 generated_protocol::RequestPayload::GuestKernelCallRequest(inner) => {
600 RequestPayload::GuestKernelCall(inner)
601 }
602 generated_protocol::RequestPayload::ResizePtyRequest(inner) => {
603 RequestPayload::ResizePty(inner)
604 }
605 generated_protocol::RequestPayload::LinkPackageRequest(inner) => {
606 RequestPayload::LinkPackage(inner)
607 }
608 generated_protocol::RequestPayload::ProvidedCommandsRequest => {
609 RequestPayload::ProvidedCommands(ProvidedCommandsRequest {})
610 }
611 })
612}
613
614fn to_generated_response_payload(
615 payload: &ResponsePayload,
616) -> Result<generated_protocol::ResponsePayload, ProtocolCodecError> {
617 Ok(match payload {
618 ResponsePayload::Authenticated(inner) => {
619 generated_protocol::ResponsePayload::AuthenticatedResponse(inner.clone())
620 }
621 ResponsePayload::SessionOpened(inner) => {
622 generated_protocol::ResponsePayload::SessionOpenedResponse(inner.clone())
623 }
624 ResponsePayload::VmCreated(inner) => {
625 generated_protocol::ResponsePayload::VmCreatedResponse(inner.clone())
626 }
627 ResponsePayload::VmDisposed(inner) => {
628 generated_protocol::ResponsePayload::VmDisposedResponse(inner.clone())
629 }
630 ResponsePayload::RootFilesystemBootstrapped(inner) => {
631 generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner.clone())
632 }
633 ResponsePayload::VmConfigured(inner) => {
634 generated_protocol::ResponsePayload::VmConfiguredResponse(inner.clone())
635 }
636 ResponsePayload::HostCallbacksRegistered(inner) => {
637 generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner.clone())
638 }
639 ResponsePayload::LayerCreated(inner) => {
640 generated_protocol::ResponsePayload::LayerCreatedResponse(inner.clone())
641 }
642 ResponsePayload::LayerSealed(inner) => {
643 generated_protocol::ResponsePayload::LayerSealedResponse(inner.clone())
644 }
645 ResponsePayload::SnapshotImported(inner) => {
646 generated_protocol::ResponsePayload::SnapshotImportedResponse(inner.clone())
647 }
648 ResponsePayload::SnapshotExported(inner) => {
649 generated_protocol::ResponsePayload::SnapshotExportedResponse(
650 generated_protocol::SnapshotExportedResponse {
651 layer_id: inner.layer_id.clone(),
652 entries: inner.entries.clone(),
653 },
654 )
655 }
656 ResponsePayload::OverlayCreated(inner) => {
657 generated_protocol::ResponsePayload::OverlayCreatedResponse(inner.clone())
658 }
659 ResponsePayload::GuestFilesystemResult(inner) => {
660 generated_protocol::ResponsePayload::GuestFilesystemResultResponse(
661 generated_protocol::GuestFilesystemResultResponse {
662 operation: to_generated_guest_filesystem_operation(&inner.operation),
663 path: inner.path.clone(),
664 content: inner.content.clone(),
665 encoding: inner
666 .encoding
667 .as_ref()
668 .map(to_generated_root_filesystem_entry_encoding),
669 entries: inner.entries.clone(),
670 stat: inner.stat.as_ref().map(to_generated_guest_filesystem_stat),
671 exists: inner.exists,
672 target: inner.target.clone(),
673 },
674 )
675 }
676 ResponsePayload::RootFilesystemSnapshot(inner) => {
677 generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(
678 generated_protocol::RootFilesystemSnapshotResponse {
679 entries: inner.entries.clone(),
680 },
681 )
682 }
683 ResponsePayload::ProcessStarted(inner) => {
684 generated_protocol::ResponsePayload::ProcessStartedResponse(inner.clone())
685 }
686 ResponsePayload::StdinWritten(inner) => {
687 generated_protocol::ResponsePayload::StdinWrittenResponse(inner.clone())
688 }
689 ResponsePayload::StdinClosed(inner) => {
690 generated_protocol::ResponsePayload::StdinClosedResponse(inner.clone())
691 }
692 ResponsePayload::ProcessKilled(inner) => {
693 generated_protocol::ResponsePayload::ProcessKilledResponse(inner.clone())
694 }
695 ResponsePayload::ProcessSnapshot(inner) => {
696 generated_protocol::ResponsePayload::ProcessSnapshotResponse(
697 generated_protocol::ProcessSnapshotResponse {
698 processes: inner
699 .processes
700 .iter()
701 .map(to_generated_process_snapshot_entry)
702 .collect(),
703 },
704 )
705 }
706 ResponsePayload::ResourceSnapshot(inner) => {
707 generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner.clone())
708 }
709 ResponsePayload::ListenerSnapshot(inner) => {
710 generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner.clone())
711 }
712 ResponsePayload::BoundUdpSnapshot(inner) => {
713 generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner.clone())
714 }
715 ResponsePayload::VmFetchResult(inner) => {
716 generated_protocol::ResponsePayload::VmFetchResponse(inner.clone())
717 }
718 ResponsePayload::SignalState(inner) => {
719 generated_protocol::ResponsePayload::SignalStateResponse(inner.clone())
720 }
721 ResponsePayload::ZombieTimerCount(inner) => {
722 generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner.clone())
723 }
724 ResponsePayload::FilesystemResult(inner) => {
725 generated_protocol::ResponsePayload::FilesystemResultResponse(
726 generated_protocol::FilesystemResultResponse {
727 operation: to_generated_filesystem_operation(&inner.operation),
728 status: inner.status.clone(),
729 payload_size_bytes: inner.payload_size_bytes,
730 },
731 )
732 }
733 ResponsePayload::PermissionDecision(inner) => {
734 generated_protocol::ResponsePayload::PermissionDecisionResponse(
735 generated_protocol::PermissionDecisionResponse {
736 capability: inner.capability.clone(),
737 decision: to_generated_permission_mode(&inner.decision),
738 },
739 )
740 }
741 ResponsePayload::PersistenceState(inner) => {
742 generated_protocol::ResponsePayload::PersistenceStateResponse(inner.clone())
743 }
744 ResponsePayload::PersistenceFlushed(inner) => {
745 generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner.clone())
746 }
747 ResponsePayload::Rejected(inner) => {
748 generated_protocol::ResponsePayload::RejectedResponse(inner.clone())
749 }
750 ResponsePayload::ExtResult(inner) => {
751 generated_protocol::ResponsePayload::ExtEnvelope(to_generated_ext_envelope(inner))
752 }
753 ResponsePayload::GuestKernelResult(inner) => {
754 generated_protocol::ResponsePayload::GuestKernelResultResponse(inner.clone())
755 }
756 ResponsePayload::PtyResized(inner) => {
757 generated_protocol::ResponsePayload::PtyResizedResponse(inner.clone())
758 }
759 ResponsePayload::PackageLinked(inner) => {
760 generated_protocol::ResponsePayload::PackageLinkedResponse(inner.clone())
761 }
762 ResponsePayload::ProvidedCommands(inner) => {
763 generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner.clone())
764 }
765 })
766}
767
768fn from_generated_response_payload(
769 payload: generated_protocol::ResponsePayload,
770) -> Result<ResponsePayload, ProtocolCodecError> {
771 Ok(match payload {
772 generated_protocol::ResponsePayload::AuthenticatedResponse(inner) => {
773 ResponsePayload::Authenticated(inner)
774 }
775 generated_protocol::ResponsePayload::SessionOpenedResponse(inner) => {
776 ResponsePayload::SessionOpened(inner)
777 }
778 generated_protocol::ResponsePayload::VmCreatedResponse(inner) => {
779 ResponsePayload::VmCreated(inner)
780 }
781 generated_protocol::ResponsePayload::VmDisposedResponse(inner) => {
782 ResponsePayload::VmDisposed(inner)
783 }
784 generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner) => {
785 ResponsePayload::RootFilesystemBootstrapped(inner)
786 }
787 generated_protocol::ResponsePayload::VmConfiguredResponse(inner) => {
788 ResponsePayload::VmConfigured(inner)
789 }
790 generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner) => {
791 ResponsePayload::HostCallbacksRegistered(inner)
792 }
793 generated_protocol::ResponsePayload::LayerCreatedResponse(inner) => {
794 ResponsePayload::LayerCreated(inner)
795 }
796 generated_protocol::ResponsePayload::LayerSealedResponse(inner) => {
797 ResponsePayload::LayerSealed(inner)
798 }
799 generated_protocol::ResponsePayload::SnapshotImportedResponse(inner) => {
800 ResponsePayload::SnapshotImported(inner)
801 }
802 generated_protocol::ResponsePayload::SnapshotExportedResponse(inner) => {
803 ResponsePayload::SnapshotExported(SnapshotExportedResponse {
804 layer_id: inner.layer_id,
805 entries: inner.entries,
806 })
807 }
808 generated_protocol::ResponsePayload::OverlayCreatedResponse(inner) => {
809 ResponsePayload::OverlayCreated(inner)
810 }
811 generated_protocol::ResponsePayload::GuestFilesystemResultResponse(inner) => {
812 ResponsePayload::GuestFilesystemResult(GuestFilesystemResultResponse {
813 operation: from_generated_guest_filesystem_operation(inner.operation),
814 path: inner.path,
815 content: inner.content,
816 encoding: inner
817 .encoding
818 .map(from_generated_root_filesystem_entry_encoding),
819 entries: inner.entries,
820 stat: inner.stat.map(from_generated_guest_filesystem_stat),
821 exists: inner.exists,
822 target: inner.target,
823 })
824 }
825 generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(inner) => {
826 ResponsePayload::RootFilesystemSnapshot(RootFilesystemSnapshotResponse {
827 entries: inner.entries,
828 })
829 }
830 generated_protocol::ResponsePayload::ProcessStartedResponse(inner) => {
831 ResponsePayload::ProcessStarted(inner)
832 }
833 generated_protocol::ResponsePayload::StdinWrittenResponse(inner) => {
834 ResponsePayload::StdinWritten(inner)
835 }
836 generated_protocol::ResponsePayload::StdinClosedResponse(inner) => {
837 ResponsePayload::StdinClosed(inner)
838 }
839 generated_protocol::ResponsePayload::ProcessKilledResponse(inner) => {
840 ResponsePayload::ProcessKilled(inner)
841 }
842 generated_protocol::ResponsePayload::ProcessSnapshotResponse(inner) => {
843 ResponsePayload::ProcessSnapshot(ProcessSnapshotResponse {
844 processes: inner
845 .processes
846 .into_iter()
847 .map(from_generated_process_snapshot_entry)
848 .collect(),
849 })
850 }
851 generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner) => {
852 ResponsePayload::ResourceSnapshot(inner)
853 }
854 generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner) => {
855 ResponsePayload::ListenerSnapshot(inner)
856 }
857 generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner) => {
858 ResponsePayload::BoundUdpSnapshot(inner)
859 }
860 generated_protocol::ResponsePayload::VmFetchResponse(inner) => {
861 ResponsePayload::VmFetchResult(inner)
862 }
863 generated_protocol::ResponsePayload::SignalStateResponse(inner) => {
864 ResponsePayload::SignalState(inner)
865 }
866 generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner) => {
867 ResponsePayload::ZombieTimerCount(inner)
868 }
869 generated_protocol::ResponsePayload::FilesystemResultResponse(inner) => {
870 ResponsePayload::FilesystemResult(FilesystemResultResponse {
871 operation: from_generated_filesystem_operation(inner.operation),
872 status: inner.status,
873 payload_size_bytes: inner.payload_size_bytes,
874 })
875 }
876 generated_protocol::ResponsePayload::PermissionDecisionResponse(inner) => {
877 ResponsePayload::PermissionDecision(PermissionDecisionResponse {
878 capability: inner.capability,
879 decision: from_generated_permission_mode(inner.decision),
880 })
881 }
882 generated_protocol::ResponsePayload::PersistenceStateResponse(inner) => {
883 ResponsePayload::PersistenceState(inner)
884 }
885 generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner) => {
886 ResponsePayload::PersistenceFlushed(inner)
887 }
888 generated_protocol::ResponsePayload::RejectedResponse(inner) => {
889 ResponsePayload::Rejected(inner)
890 }
891 generated_protocol::ResponsePayload::ExtEnvelope(inner) => {
892 ResponsePayload::ExtResult(from_generated_ext_envelope(inner))
893 }
894 generated_protocol::ResponsePayload::GuestKernelResultResponse(inner) => {
895 ResponsePayload::GuestKernelResult(inner)
896 }
897 generated_protocol::ResponsePayload::PtyResizedResponse(inner) => {
898 ResponsePayload::PtyResized(inner)
899 }
900 generated_protocol::ResponsePayload::PackageLinkedResponse(inner) => {
901 ResponsePayload::PackageLinked(inner)
902 }
903 generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner) => {
904 ResponsePayload::ProvidedCommands(inner)
905 }
906 })
907}
908
909fn to_generated_event_payload(payload: &EventPayload) -> generated_protocol::EventPayload {
910 match payload {
911 EventPayload::VmLifecycle(inner) => generated_protocol::EventPayload::VmLifecycleEvent(
912 generated_protocol::VmLifecycleEvent {
913 state: to_generated_vm_lifecycle_state(&inner.state),
914 },
915 ),
916 EventPayload::ProcessOutput(inner) => generated_protocol::EventPayload::ProcessOutputEvent(
917 generated_protocol::ProcessOutputEvent {
918 process_id: inner.process_id.clone(),
919 channel: to_generated_stream_channel(&inner.channel),
920 chunk: inner.chunk.clone(),
921 },
922 ),
923 EventPayload::ProcessExited(inner) => {
924 generated_protocol::EventPayload::ProcessExitedEvent(inner.clone())
925 }
926 EventPayload::Structured(inner) => {
927 generated_protocol::EventPayload::StructuredEvent(inner.clone())
928 }
929 EventPayload::Ext(inner) => {
930 generated_protocol::EventPayload::ExtEnvelope(to_generated_ext_envelope(inner))
931 }
932 }
933}
934
935fn from_generated_event_payload(payload: generated_protocol::EventPayload) -> EventPayload {
936 match payload {
937 generated_protocol::EventPayload::VmLifecycleEvent(inner) => {
938 EventPayload::VmLifecycle(VmLifecycleEvent {
939 state: from_generated_vm_lifecycle_state(inner.state),
940 })
941 }
942 generated_protocol::EventPayload::ProcessOutputEvent(inner) => {
943 EventPayload::ProcessOutput(ProcessOutputEvent {
944 process_id: inner.process_id,
945 channel: from_generated_stream_channel(inner.channel),
946 chunk: inner.chunk,
947 })
948 }
949 generated_protocol::EventPayload::ProcessExitedEvent(inner) => {
950 EventPayload::ProcessExited(inner)
951 }
952 generated_protocol::EventPayload::StructuredEvent(inner) => EventPayload::Structured(inner),
953 generated_protocol::EventPayload::ExtEnvelope(inner) => {
954 EventPayload::Ext(from_generated_ext_envelope(inner))
955 }
956 }
957}
958
959fn to_generated_sidecar_request_payload(
960 payload: &SidecarRequestPayload,
961) -> Result<generated_protocol::SidecarRequestPayload, ProtocolCodecError> {
962 Ok(match payload {
963 SidecarRequestPayload::HostCallback(inner) => {
964 generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner.clone())
965 }
966 SidecarRequestPayload::JsBridgeCall(inner) => {
967 generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner.clone())
968 }
969 SidecarRequestPayload::Ext(inner) => {
970 generated_protocol::SidecarRequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
971 }
972 })
973}
974
975fn from_generated_sidecar_request_payload(
976 payload: generated_protocol::SidecarRequestPayload,
977) -> Result<SidecarRequestPayload, ProtocolCodecError> {
978 Ok(match payload {
979 generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner) => {
980 SidecarRequestPayload::HostCallback(inner)
981 }
982 generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner) => {
983 SidecarRequestPayload::JsBridgeCall(inner)
984 }
985 generated_protocol::SidecarRequestPayload::ExtEnvelope(inner) => {
986 SidecarRequestPayload::Ext(from_generated_ext_envelope(inner))
987 }
988 })
989}
990
991fn to_generated_sidecar_response_payload(
992 payload: &SidecarResponsePayload,
993) -> Result<generated_protocol::SidecarResponsePayload, ProtocolCodecError> {
994 Ok(match payload {
995 SidecarResponsePayload::HostCallbackResult(inner) => {
996 generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner.clone())
997 }
998 SidecarResponsePayload::JsBridgeResult(inner) => {
999 generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner.clone())
1000 }
1001 SidecarResponsePayload::ExtResult(inner) => {
1002 generated_protocol::SidecarResponsePayload::ExtEnvelope(to_generated_ext_envelope(
1003 inner,
1004 ))
1005 }
1006 })
1007}
1008
1009fn from_generated_sidecar_response_payload(
1010 payload: generated_protocol::SidecarResponsePayload,
1011) -> Result<SidecarResponsePayload, ProtocolCodecError> {
1012 Ok(match payload {
1013 generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner) => {
1014 SidecarResponsePayload::HostCallbackResult(inner)
1015 }
1016 generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner) => {
1017 SidecarResponsePayload::JsBridgeResult(inner)
1018 }
1019 generated_protocol::SidecarResponsePayload::ExtEnvelope(inner) => {
1020 SidecarResponsePayload::ExtResult(from_generated_ext_envelope(inner))
1021 }
1022 })
1023}
1024
1025macro_rules! impl_bare_newtype_union_enum {
1026 (
1027 $name:ident,
1028 $json_name:ident,
1029 $(#[$json_attr:meta])*
1030 {
1031 $($variant:ident($ty:ty) = $tag:literal),+ $(,)?
1032 }
1033 ) => {
1034 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1035 $(#[$json_attr])*
1036 enum $json_name {
1037 $($variant($ty)),+
1038 }
1039
1040 impl From<&$name> for $json_name {
1041 fn from(value: &$name) -> Self {
1042 match value {
1043 $($name::$variant(inner) => Self::$variant(inner.clone()),)+
1044 }
1045 }
1046 }
1047
1048 impl From<$json_name> for $name {
1049 fn from(value: $json_name) -> Self {
1050 match value {
1051 $($json_name::$variant(inner) => Self::$variant(inner),)+
1052 }
1053 }
1054 }
1055
1056 impl Serialize for $name {
1057 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1058 where
1059 S: Serializer,
1060 {
1061 if serializer.is_human_readable() {
1062 $json_name::from(self).serialize(serializer)
1063 } else {
1064 match self {
1065 $(Self::$variant(inner) => serialize_bare_newtype_tag(serializer, $tag, inner),)+
1066 }
1067 }
1068 }
1069 }
1070
1071 impl<'de> Deserialize<'de> for $name {
1072 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1073 where
1074 D: Deserializer<'de>,
1075 {
1076 if deserializer.is_human_readable() {
1077 Ok($json_name::deserialize(deserializer)?.into())
1078 } else {
1079 struct UnionVisitor;
1080
1081 impl<'de> Visitor<'de> for UnionVisitor {
1082 type Value = $name;
1083
1084 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 write!(formatter, "a {} BARE union", stringify!($name))
1086 }
1087
1088 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1089 where
1090 A: SeqAccess<'de>,
1091 {
1092 let serde_bare::Uint(tag) = seq
1093 .next_element()?
1094 .ok_or_else(|| de::Error::custom(concat!("missing ", stringify!($name), " tag")))?;
1095 match tag {
1096 $(
1097 $tag => {
1098 let payload = seq.next_element::<$ty>()?.ok_or_else(|| {
1099 de::Error::custom(format!(
1100 "missing {} payload for tag {}",
1101 stringify!($variant),
1102 $tag
1103 ))
1104 })?;
1105 Ok($name::$variant(payload))
1106 }
1107 )+
1108 _ => Err(de::Error::custom(format!(
1109 "unknown {} tag: {}",
1110 stringify!($name),
1111 tag
1112 ))),
1113 }
1114 }
1115 }
1116
1117 deserializer.deserialize_tuple(2, UnionVisitor)
1118 }
1119 }
1120 }
1121 };
1122}
1123
1124pub type ProtocolSchema = crate::wire::ProtocolSchema;
1125
1126pub type OwnershipScope = crate::wire::OwnershipScope;
1127
1128#[derive(Debug, Clone, PartialEq, Eq)]
1129pub enum ProtocolFrame {
1130 Request(RequestFrame),
1131 Response(ResponseFrame),
1132 Event(EventFrame),
1133 SidecarRequest(SidecarRequestFrame),
1134 SidecarResponse(SidecarResponseFrame),
1135}
1136
1137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1138pub struct RequestFrame {
1139 pub schema: ProtocolSchema,
1140 pub request_id: RequestId,
1141 pub ownership: OwnershipScope,
1142 pub payload: RequestPayload,
1143}
1144
1145impl RequestFrame {
1146 pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: RequestPayload) -> Self {
1147 Self {
1148 schema: ProtocolSchema::current(),
1149 request_id,
1150 ownership,
1151 payload,
1152 }
1153 }
1154}
1155
1156#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1157pub struct ResponseFrame {
1158 pub schema: ProtocolSchema,
1159 pub request_id: RequestId,
1160 pub ownership: OwnershipScope,
1161 pub payload: ResponsePayload,
1162}
1163
1164impl ResponseFrame {
1165 pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: ResponsePayload) -> Self {
1166 Self {
1167 schema: ProtocolSchema::current(),
1168 request_id,
1169 ownership,
1170 payload,
1171 }
1172 }
1173}
1174
1175#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1176pub struct SidecarRequestFrame {
1177 pub schema: ProtocolSchema,
1178 pub request_id: RequestId,
1179 pub ownership: OwnershipScope,
1180 pub payload: SidecarRequestPayload,
1181}
1182
1183impl SidecarRequestFrame {
1184 pub fn new(
1185 request_id: RequestId,
1186 ownership: OwnershipScope,
1187 payload: SidecarRequestPayload,
1188 ) -> Self {
1189 Self {
1190 schema: ProtocolSchema::current(),
1191 request_id,
1192 ownership,
1193 payload,
1194 }
1195 }
1196}
1197
1198#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1199pub struct SidecarResponseFrame {
1200 pub schema: ProtocolSchema,
1201 pub request_id: RequestId,
1202 pub ownership: OwnershipScope,
1203 pub payload: SidecarResponsePayload,
1204}
1205
1206impl SidecarResponseFrame {
1207 pub fn new(
1208 request_id: RequestId,
1209 ownership: OwnershipScope,
1210 payload: SidecarResponsePayload,
1211 ) -> Self {
1212 Self {
1213 schema: ProtocolSchema::current(),
1214 request_id,
1215 ownership,
1216 payload,
1217 }
1218 }
1219}
1220
1221#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1222pub struct EventFrame {
1223 pub schema: ProtocolSchema,
1224 pub ownership: OwnershipScope,
1225 pub payload: EventPayload,
1226}
1227
1228impl EventFrame {
1229 pub fn new(ownership: OwnershipScope, payload: EventPayload) -> Self {
1230 Self {
1231 schema: ProtocolSchema::current(),
1232 ownership,
1233 payload,
1234 }
1235 }
1236}
1237
1238#[derive(Debug, Clone, PartialEq, Eq)]
1239pub enum RequestPayload {
1240 Authenticate(AuthenticateRequest),
1241 OpenSession(OpenSessionRequest),
1242 CreateVm(CreateVmRequest),
1243 DisposeVm(DisposeVmRequest),
1244 BootstrapRootFilesystem(BootstrapRootFilesystemRequest),
1245 ConfigureVm(ConfigureVmRequest),
1246 RegisterHostCallbacks(RegisterHostCallbacksRequest),
1247 CreateLayer(CreateLayerRequest),
1248 SealLayer(SealLayerRequest),
1249 ImportSnapshot(ImportSnapshotRequest),
1250 ExportSnapshot(ExportSnapshotRequest),
1251 CreateOverlay(CreateOverlayRequest),
1252 GuestFilesystemCall(GuestFilesystemCallRequest),
1253 SnapshotRootFilesystem(SnapshotRootFilesystemRequest),
1254 Execute(ExecuteRequest),
1255 WriteStdin(WriteStdinRequest),
1256 CloseStdin(CloseStdinRequest),
1257 KillProcess(KillProcessRequest),
1258 GetProcessSnapshot(GetProcessSnapshotRequest),
1259 FindListener(FindListenerRequest),
1260 FindBoundUdp(FindBoundUdpRequest),
1261 VmFetch(VmFetchRequest),
1262 GetSignalState(GetSignalStateRequest),
1263 GetZombieTimerCount(GetZombieTimerCountRequest),
1264 HostFilesystemCall(HostFilesystemCallRequest),
1265 PersistenceLoad(PersistenceLoadRequest),
1266 PersistenceFlush(PersistenceFlushRequest),
1267 Ext(ExtEnvelope),
1268 GuestKernelCall(GuestKernelCallRequest),
1269 ResizePty(ResizePtyRequest),
1270 GetResourceSnapshot(GetResourceSnapshotRequest),
1271 LinkPackage(LinkPackageRequest),
1272 ProvidedCommands(ProvidedCommandsRequest),
1273}
1274
1275#[derive(Debug, Clone, PartialEq, Eq)]
1276pub enum ResponsePayload {
1277 Authenticated(AuthenticatedResponse),
1278 SessionOpened(SessionOpenedResponse),
1279 VmCreated(VmCreatedResponse),
1280 VmDisposed(VmDisposedResponse),
1281 RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse),
1282 VmConfigured(VmConfiguredResponse),
1283 HostCallbacksRegistered(HostCallbacksRegisteredResponse),
1284 LayerCreated(LayerCreatedResponse),
1285 LayerSealed(LayerSealedResponse),
1286 SnapshotImported(SnapshotImportedResponse),
1287 SnapshotExported(SnapshotExportedResponse),
1288 OverlayCreated(OverlayCreatedResponse),
1289 GuestFilesystemResult(GuestFilesystemResultResponse),
1290 RootFilesystemSnapshot(RootFilesystemSnapshotResponse),
1291 ProcessStarted(ProcessStartedResponse),
1292 StdinWritten(StdinWrittenResponse),
1293 StdinClosed(StdinClosedResponse),
1294 ProcessKilled(ProcessKilledResponse),
1295 ProcessSnapshot(ProcessSnapshotResponse),
1296 ListenerSnapshot(ListenerSnapshotResponse),
1297 BoundUdpSnapshot(BoundUdpSnapshotResponse),
1298 VmFetchResult(VmFetchResponse),
1299 SignalState(SignalStateResponse),
1300 ZombieTimerCount(ZombieTimerCountResponse),
1301 FilesystemResult(FilesystemResultResponse),
1302 PermissionDecision(PermissionDecisionResponse),
1303 PersistenceState(PersistenceStateResponse),
1304 PersistenceFlushed(PersistenceFlushedResponse),
1305 Rejected(RejectedResponse),
1306 ExtResult(ExtEnvelope),
1307 GuestKernelResult(GuestKernelResultResponse),
1308 PtyResized(PtyResizedResponse),
1309 ResourceSnapshot(ResourceSnapshotResponse),
1310 PackageLinked(PackageLinkedResponse),
1311 ProvidedCommands(ProvidedCommandsResponse),
1312}
1313
1314#[derive(Debug, Clone, PartialEq, Eq)]
1315pub enum SidecarRequestPayload {
1316 HostCallback(HostCallbackRequest),
1317 JsBridgeCall(JsBridgeCallRequest),
1318 Ext(ExtEnvelope),
1319}
1320
1321#[derive(Debug, Clone, PartialEq, Eq)]
1322pub enum SidecarResponsePayload {
1323 HostCallbackResult(HostCallbackResultResponse),
1324 JsBridgeResult(JsBridgeResultResponse),
1325 ExtResult(ExtEnvelope),
1326}
1327
1328#[derive(Debug, Clone, PartialEq, Eq)]
1329pub enum EventPayload {
1330 VmLifecycle(VmLifecycleEvent),
1331 ProcessOutput(ProcessOutputEvent),
1332 ProcessExited(ProcessExitedEvent),
1333 Structured(StructuredEvent),
1334 Ext(ExtEnvelope),
1335}
1336
1337pub type SidecarPlacement = crate::wire::SidecarPlacement;
1338
1339pub type SidecarPlacementShared = crate::wire::SidecarPlacementShared;
1340
1341pub type SidecarPlacementExplicit = crate::wire::SidecarPlacementExplicit;
1342
1343pub type GuestRuntimeKind = crate::wire::GuestRuntimeKind;
1344
1345pub type DisposeReason = crate::wire::DisposeReason;
1346
1347pub type FilesystemOperation = crate::wire::FilesystemOperation;
1348
1349pub type GuestFilesystemOperation = crate::wire::GuestFilesystemOperation;
1350
1351pub type PermissionMode = crate::wire::PermissionMode;
1352
1353pub type FsPermissionRule = crate::wire::FsPermissionRule;
1354
1355pub type PatternPermissionRule = crate::wire::PatternPermissionRule;
1356
1357pub type FsPermissionRuleSet = crate::wire::FsPermissionRuleSet;
1358
1359pub type PatternPermissionRuleSet = crate::wire::PatternPermissionRuleSet;
1360
1361pub type FsPermissionScope = crate::wire::FsPermissionScope;
1362
1363pub type PatternPermissionScope = crate::wire::PatternPermissionScope;
1364
1365pub type PermissionsPolicy = crate::wire::PermissionsPolicy;
1366
1367pub type RootFilesystemEntryKind = crate::wire::RootFilesystemEntryKind;
1368
1369pub type RootFilesystemMode = crate::wire::RootFilesystemMode;
1370
1371pub type RootFilesystemLowerDescriptor = crate::wire::RootFilesystemLowerDescriptor;
1372
1373pub type SnapshotRootFilesystemLower = crate::wire::SnapshotRootFilesystemLower;
1374
1375pub type StreamChannel = crate::wire::StreamChannel;
1376
1377pub type VmLifecycleState = crate::wire::VmLifecycleState;
1378
1379pub type AuthenticateRequest = crate::wire::AuthenticateRequest;
1380
1381pub type OpenSessionRequest = crate::wire::OpenSessionRequest;
1382
1383pub type CreateVmRequest = crate::wire::CreateVmRequest;
1384
1385#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1386pub struct DisposeVmRequest {
1387 pub reason: DisposeReason,
1388}
1389
1390pub type BootstrapRootFilesystemRequest = crate::wire::BootstrapRootFilesystemRequest;
1391
1392pub type RootFilesystemDescriptor = crate::wire::RootFilesystemDescriptor;
1393
1394pub type RootFilesystemEntryEncoding = crate::wire::RootFilesystemEntryEncoding;
1395
1396pub type RootFilesystemEntry = crate::wire::RootFilesystemEntry;
1397
1398pub type ConfigureVmRequest = crate::wire::ConfigureVmRequest;
1399
1400#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1401pub struct CreateLayerRequest {}
1402
1403pub type SealLayerRequest = crate::wire::SealLayerRequest;
1404
1405pub type ImportSnapshotRequest = crate::wire::ImportSnapshotRequest;
1406
1407pub type ExportSnapshotRequest = crate::wire::ExportSnapshotRequest;
1408
1409pub type CreateOverlayRequest = crate::wire::CreateOverlayRequest;
1410
1411pub type GuestFilesystemCallRequest = crate::wire::GuestFilesystemCallRequest;
1412
1413pub type GuestKernelCallRequest = crate::wire::GuestKernelCallRequest;
1414pub type ResizePtyRequest = crate::wire::ResizePtyRequest;
1415pub type PackageDescriptor = crate::wire::PackageDescriptor;
1416pub type AgentosProjectedAgent = crate::wire::AgentosProjectedAgent;
1417pub type PackageCommands = crate::wire::PackageCommands;
1418pub type ProjectedCommand = crate::wire::ProjectedCommand;
1419pub type LinkPackageRequest = crate::wire::LinkPackageRequest;
1420
1421#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1422pub struct ProvidedCommandsRequest {}
1423
1424pub type GuestKernelResultResponse = crate::wire::GuestKernelResultResponse;
1425pub type PtyResizedResponse = crate::wire::PtyResizedResponse;
1426pub type PackageLinkedResponse = crate::wire::PackageLinkedResponse;
1427pub type ProvidedCommandsResponse = crate::wire::ProvidedCommandsResponse;
1428
1429#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1430pub struct SnapshotRootFilesystemRequest {}
1431
1432pub type MountDescriptor = crate::wire::MountDescriptor;
1433
1434pub type MountPluginDescriptor = crate::wire::MountPluginDescriptor;
1435
1436pub type SoftwareDescriptor = crate::wire::SoftwareDescriptor;
1437
1438pub type ProjectedModuleDescriptor = crate::wire::ProjectedModuleDescriptor;
1439
1440pub type WasmPermissionTier = crate::wire::WasmPermissionTier;
1441
1442pub type ExecuteRequest = crate::wire::ExecuteRequest;
1443
1444pub type WriteStdinRequest = crate::wire::WriteStdinRequest;
1445
1446pub type CloseStdinRequest = crate::wire::CloseStdinRequest;
1447
1448pub type KillProcessRequest = crate::wire::KillProcessRequest;
1449
1450#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1451pub struct GetProcessSnapshotRequest {}
1452
1453#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1454pub struct GetResourceSnapshotRequest {}
1455
1456pub type FindListenerRequest = crate::wire::FindListenerRequest;
1457
1458pub type FindBoundUdpRequest = crate::wire::FindBoundUdpRequest;
1459
1460pub type VmFetchRequest = crate::wire::VmFetchRequest;
1461
1462pub type GetSignalStateRequest = crate::wire::GetSignalStateRequest;
1463
1464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1465pub struct GetZombieTimerCountRequest {}
1466
1467pub type HostFilesystemCallRequest = crate::wire::HostFilesystemCallRequest;
1468
1469pub type PersistenceLoadRequest = crate::wire::PersistenceLoadRequest;
1470
1471pub type PersistenceFlushRequest = crate::wire::PersistenceFlushRequest;
1472
1473pub type RegisterHostCallbacksRequest = crate::wire::RegisterHostCallbacksRequest;
1474
1475pub type RegisteredHostCallbackDefinition = crate::wire::RegisteredHostCallbackDefinition;
1476
1477pub type RegisteredHostCallbackExample = crate::wire::RegisteredHostCallbackExample;
1478
1479pub type HostCallbackRequest = crate::wire::HostCallbackRequest;
1480
1481pub type JsBridgeCallRequest = crate::wire::JsBridgeCallRequest;
1482
1483pub type AuthenticatedResponse = crate::wire::AuthenticatedResponse;
1484
1485pub type SessionOpenedResponse = crate::wire::SessionOpenedResponse;
1486
1487pub type VmCreatedResponse = crate::wire::VmCreatedResponse;
1488
1489pub type VmDisposedResponse = crate::wire::VmDisposedResponse;
1490
1491pub type RootFilesystemBootstrappedResponse = crate::wire::RootFilesystemBootstrappedResponse;
1492
1493pub type VmConfiguredResponse = crate::wire::VmConfiguredResponse;
1494
1495pub type HostCallbacksRegisteredResponse = crate::wire::HostCallbacksRegisteredResponse;
1496
1497pub type GuestFilesystemStat = crate::wire::GuestFilesystemStat;
1498
1499pub type GuestDirEntry = crate::wire::GuestDirEntry;
1500
1501pub type GuestFilesystemResultResponse = crate::wire::GuestFilesystemResultResponse;
1502
1503pub type RootFilesystemSnapshotResponse = crate::wire::RootFilesystemSnapshotResponse;
1504
1505pub type LayerCreatedResponse = crate::wire::LayerCreatedResponse;
1506
1507pub type LayerSealedResponse = crate::wire::LayerSealedResponse;
1508
1509pub type SnapshotImportedResponse = crate::wire::SnapshotImportedResponse;
1510
1511pub type SnapshotExportedResponse = crate::wire::SnapshotExportedResponse;
1512
1513pub type OverlayCreatedResponse = crate::wire::OverlayCreatedResponse;
1514
1515pub type ProcessStartedResponse = crate::wire::ProcessStartedResponse;
1516
1517pub type StdinWrittenResponse = crate::wire::StdinWrittenResponse;
1518
1519pub type StdinClosedResponse = crate::wire::StdinClosedResponse;
1520
1521pub type ProcessKilledResponse = crate::wire::ProcessKilledResponse;
1522
1523pub type ProcessSnapshotStatus = crate::wire::ProcessSnapshotStatus;
1524
1525pub type ProcessSnapshotEntry = crate::wire::ProcessSnapshotEntry;
1526
1527pub type ProcessSnapshotResponse = crate::wire::ProcessSnapshotResponse;
1528
1529pub type QueueSnapshotEntry = crate::wire::QueueSnapshotEntry;
1530
1531pub type ResourceSnapshotResponse = crate::wire::ResourceSnapshotResponse;
1532
1533pub type SocketStateEntry = crate::wire::SocketStateEntry;
1534
1535pub type ListenerSnapshotResponse = crate::wire::ListenerSnapshotResponse;
1536
1537pub type BoundUdpSnapshotResponse = crate::wire::BoundUdpSnapshotResponse;
1538
1539pub type VmFetchResponse = crate::wire::VmFetchResponse;
1540
1541pub type SignalDispositionAction = crate::wire::SignalDispositionAction;
1542
1543pub type SignalHandlerRegistration = crate::wire::SignalHandlerRegistration;
1544
1545pub type SignalStateResponse = crate::wire::SignalStateResponse;
1546
1547pub type ZombieTimerCountResponse = crate::wire::ZombieTimerCountResponse;
1548
1549pub type FilesystemResultResponse = crate::wire::FilesystemResultResponse;
1550
1551pub type PermissionDecisionResponse = crate::wire::PermissionDecisionResponse;
1552
1553pub type PersistenceStateResponse = crate::wire::PersistenceStateResponse;
1554
1555pub type PersistenceFlushedResponse = crate::wire::PersistenceFlushedResponse;
1556
1557pub type HostCallbackResultResponse = crate::wire::HostCallbackResultResponse;
1558
1559pub type JsBridgeResultResponse = crate::wire::JsBridgeResultResponse;
1560
1561pub type RejectedResponse = crate::wire::RejectedResponse;
1562
1563pub type VmLifecycleEvent = crate::wire::VmLifecycleEvent;
1564
1565pub type ProcessOutputEvent = crate::wire::ProcessOutputEvent;
1566
1567pub type ProcessExitedEvent = crate::wire::ProcessExitedEvent;
1568
1569pub type StructuredEvent = crate::wire::StructuredEvent;
1570
1571impl_bare_newtype_union_enum!(
1572 ProtocolFrame,
1573 JsonProtocolFrame,
1574 #[serde(tag = "frame_type", rename_all = "snake_case")]
1575 {
1576 Request(RequestFrame) = 0,
1577 Response(ResponseFrame) = 1,
1578 Event(EventFrame) = 2,
1579 SidecarRequest(SidecarRequestFrame) = 3,
1580 SidecarResponse(SidecarResponseFrame) = 4,
1581 }
1582);
1583
1584impl_bare_newtype_union_enum!(
1585 RequestPayload,
1586 JsonRequestPayload,
1587 #[serde(tag = "type", rename_all = "snake_case")]
1588 {
1589 Authenticate(AuthenticateRequest) = 0,
1590 OpenSession(OpenSessionRequest) = 1,
1591 CreateVm(CreateVmRequest) = 2,
1592 DisposeVm(DisposeVmRequest) = 3,
1593 BootstrapRootFilesystem(BootstrapRootFilesystemRequest) = 4,
1594 ConfigureVm(ConfigureVmRequest) = 5,
1595 RegisterHostCallbacks(RegisterHostCallbacksRequest) = 6,
1596 CreateLayer(CreateLayerRequest) = 7,
1597 SealLayer(SealLayerRequest) = 8,
1598 ImportSnapshot(ImportSnapshotRequest) = 9,
1599 ExportSnapshot(ExportSnapshotRequest) = 10,
1600 CreateOverlay(CreateOverlayRequest) = 11,
1601 GuestFilesystemCall(GuestFilesystemCallRequest) = 12,
1602 SnapshotRootFilesystem(SnapshotRootFilesystemRequest) = 13,
1603 Execute(ExecuteRequest) = 14,
1604 WriteStdin(WriteStdinRequest) = 15,
1605 CloseStdin(CloseStdinRequest) = 16,
1606 KillProcess(KillProcessRequest) = 17,
1607 GetProcessSnapshot(GetProcessSnapshotRequest) = 18,
1608 FindListener(FindListenerRequest) = 19,
1609 FindBoundUdp(FindBoundUdpRequest) = 20,
1610 GetSignalState(GetSignalStateRequest) = 21,
1611 GetZombieTimerCount(GetZombieTimerCountRequest) = 22,
1612 HostFilesystemCall(HostFilesystemCallRequest) = 23,
1613 PersistenceLoad(PersistenceLoadRequest) = 24,
1614 PersistenceFlush(PersistenceFlushRequest) = 25,
1615 VmFetch(VmFetchRequest) = 26,
1616 Ext(ExtEnvelope) = 27,
1617 GuestKernelCall(GuestKernelCallRequest) = 28,
1618 ResizePty(ResizePtyRequest) = 29,
1619 GetResourceSnapshot(GetResourceSnapshotRequest) = 30,
1620 LinkPackage(LinkPackageRequest) = 31,
1621 ProvidedCommands(ProvidedCommandsRequest) = 32,
1622 }
1623);
1624
1625impl_bare_newtype_union_enum!(
1626 ResponsePayload,
1627 JsonResponsePayload,
1628 #[serde(tag = "type", rename_all = "snake_case")]
1629 {
1630 Authenticated(AuthenticatedResponse) = 0,
1631 SessionOpened(SessionOpenedResponse) = 1,
1632 VmCreated(VmCreatedResponse) = 2,
1633 VmDisposed(VmDisposedResponse) = 3,
1634 RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse) = 4,
1635 VmConfigured(VmConfiguredResponse) = 5,
1636 HostCallbacksRegistered(HostCallbacksRegisteredResponse) = 6,
1637 LayerCreated(LayerCreatedResponse) = 7,
1638 LayerSealed(LayerSealedResponse) = 8,
1639 SnapshotImported(SnapshotImportedResponse) = 9,
1640 SnapshotExported(SnapshotExportedResponse) = 10,
1641 OverlayCreated(OverlayCreatedResponse) = 11,
1642 GuestFilesystemResult(GuestFilesystemResultResponse) = 12,
1643 RootFilesystemSnapshot(RootFilesystemSnapshotResponse) = 13,
1644 ProcessStarted(ProcessStartedResponse) = 14,
1645 StdinWritten(StdinWrittenResponse) = 15,
1646 StdinClosed(StdinClosedResponse) = 16,
1647 ProcessKilled(ProcessKilledResponse) = 17,
1648 ProcessSnapshot(ProcessSnapshotResponse) = 18,
1649 ListenerSnapshot(ListenerSnapshotResponse) = 19,
1650 BoundUdpSnapshot(BoundUdpSnapshotResponse) = 20,
1651 SignalState(SignalStateResponse) = 21,
1652 ZombieTimerCount(ZombieTimerCountResponse) = 22,
1653 FilesystemResult(FilesystemResultResponse) = 23,
1654 PermissionDecision(PermissionDecisionResponse) = 24,
1655 PersistenceState(PersistenceStateResponse) = 25,
1656 PersistenceFlushed(PersistenceFlushedResponse) = 26,
1657 Rejected(RejectedResponse) = 27,
1658 VmFetchResult(VmFetchResponse) = 28,
1659 ExtResult(ExtEnvelope) = 29,
1660 GuestKernelResult(GuestKernelResultResponse) = 30,
1661 PtyResized(PtyResizedResponse) = 31,
1662 ResourceSnapshot(ResourceSnapshotResponse) = 32,
1663 PackageLinked(PackageLinkedResponse) = 33,
1664 ProvidedCommands(ProvidedCommandsResponse) = 34,
1665 }
1666);
1667
1668impl_bare_newtype_union_enum!(
1669 SidecarRequestPayload,
1670 JsonSidecarRequestPayload,
1671 #[serde(tag = "type", rename_all = "snake_case")]
1672 {
1673 HostCallback(HostCallbackRequest) = 0,
1674 JsBridgeCall(JsBridgeCallRequest) = 1,
1675 Ext(ExtEnvelope) = 2,
1676 }
1677);
1678
1679impl_bare_newtype_union_enum!(
1680 SidecarResponsePayload,
1681 JsonSidecarResponsePayload,
1682 #[allow(clippy::enum_variant_names)]
1683 #[serde(tag = "type", rename_all = "snake_case")]
1684 {
1685 HostCallbackResult(HostCallbackResultResponse) = 0,
1686 JsBridgeResult(JsBridgeResultResponse) = 1,
1687 ExtResult(ExtEnvelope) = 2,
1688 }
1689);
1690
1691impl_bare_newtype_union_enum!(
1692 EventPayload,
1693 JsonEventPayload,
1694 #[serde(tag = "type", rename_all = "snake_case")]
1695 {
1696 VmLifecycle(VmLifecycleEvent) = 0,
1697 ProcessOutput(ProcessOutputEvent) = 1,
1698 ProcessExited(ProcessExitedEvent) = 2,
1699 Structured(StructuredEvent) = 3,
1700 Ext(ExtEnvelope) = 4,
1701 }
1702);
1703
1704fn serialize_payload(
1705 frame: &ProtocolFrame,
1706 payload_codec: NativePayloadCodec,
1707) -> Result<Vec<u8>, ProtocolCodecError> {
1708 match payload_codec {
1709 NativePayloadCodec::Json => serde_json::to_vec(frame)
1710 .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
1711 NativePayloadCodec::Bare => serde_bare::to_vec(&to_generated_protocol_frame(frame)?)
1712 .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
1713 }
1714}
1715
1716fn deserialize_payload(
1717 payload: &[u8],
1718 payload_codec: NativePayloadCodec,
1719) -> Result<ProtocolFrame, ProtocolCodecError> {
1720 match payload_codec {
1721 NativePayloadCodec::Json => serde_json::from_slice(payload)
1722 .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string())),
1723 NativePayloadCodec::Bare => {
1724 let frame: generated_protocol::ProtocolFrame = serde_bare::from_slice(payload)
1725 .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string()))?;
1726 from_generated_protocol_frame(frame)
1727 }
1728 }
1729}
1730
1731#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1732pub enum NativePayloadCodec {
1733 Json,
1734 Bare,
1735}
1736
1737impl NativePayloadCodec {
1738 pub fn sniff(payload: &[u8]) -> Self {
1739 match payload.first() {
1740 Some(b'{') => Self::Json,
1741 _ => Self::Bare,
1742 }
1743 }
1744
1745 pub fn alternate(self) -> Self {
1746 match self {
1747 Self::Json => Self::Bare,
1748 Self::Bare => Self::Json,
1749 }
1750 }
1751}
1752
1753#[derive(Debug, Clone)]
1754pub struct NativeFrameCodec {
1755 max_frame_bytes: usize,
1756 payload_codec: NativePayloadCodec,
1757}
1758
1759impl NativeFrameCodec {
1760 pub fn new(max_frame_bytes: usize) -> Self {
1761 Self::with_payload_codec(max_frame_bytes, NativePayloadCodec::Json)
1762 }
1763
1764 pub fn with_payload_codec(max_frame_bytes: usize, payload_codec: NativePayloadCodec) -> Self {
1765 Self {
1766 max_frame_bytes,
1767 payload_codec,
1768 }
1769 }
1770
1771 pub fn max_frame_bytes(&self) -> usize {
1772 self.max_frame_bytes
1773 }
1774
1775 pub fn payload_codec(&self) -> NativePayloadCodec {
1776 self.payload_codec
1777 }
1778
1779 pub fn encode(&self, frame: &ProtocolFrame) -> Result<Vec<u8>, ProtocolCodecError> {
1780 self.encode_with_codec(frame, self.payload_codec)
1781 }
1782
1783 pub fn encode_with_codec(
1784 &self,
1785 frame: &ProtocolFrame,
1786 payload_codec: NativePayloadCodec,
1787 ) -> Result<Vec<u8>, ProtocolCodecError> {
1788 validate_frame(frame)?;
1789
1790 let payload = serialize_payload(frame, payload_codec)?;
1791 if payload.len() > self.max_frame_bytes {
1792 return Err(ProtocolCodecError::FrameTooLarge {
1793 size: payload.len(),
1794 max: self.max_frame_bytes,
1795 });
1796 }
1797
1798 let length =
1799 u32::try_from(payload.len()).map_err(|_| ProtocolCodecError::FrameTooLarge {
1800 size: payload.len(),
1801 max: u32::MAX as usize,
1802 })?;
1803
1804 let mut encoded = Vec::with_capacity(4 + payload.len());
1805 encoded.extend_from_slice(&length.to_be_bytes());
1806 encoded.extend_from_slice(&payload);
1807 Ok(encoded)
1808 }
1809
1810 pub fn decode(&self, bytes: &[u8]) -> Result<ProtocolFrame, ProtocolCodecError> {
1811 self.decode_detected(bytes).map(|(frame, _)| frame)
1812 }
1813
1814 pub fn decode_with_codec(
1815 &self,
1816 bytes: &[u8],
1817 payload_codec: NativePayloadCodec,
1818 ) -> Result<ProtocolFrame, ProtocolCodecError> {
1819 let payload = self.checked_payload(bytes)?;
1820 let frame = deserialize_payload(payload, payload_codec)?;
1821 validate_frame(&frame)?;
1822 Ok(frame)
1823 }
1824
1825 pub fn decode_detected(
1826 &self,
1827 bytes: &[u8],
1828 ) -> Result<(ProtocolFrame, NativePayloadCodec), ProtocolCodecError> {
1829 let payload = self.checked_payload(bytes)?;
1830 let primary = NativePayloadCodec::sniff(payload);
1831
1832 match deserialize_payload(payload, primary) {
1833 Ok(frame) => {
1834 validate_frame(&frame)?;
1835 Ok((frame, primary))
1836 }
1837 Err(primary_error) => {
1838 let alternate = primary.alternate();
1839 let frame = deserialize_payload(payload, alternate).map_err(|_| primary_error)?;
1840 validate_frame(&frame)?;
1841 Ok((frame, alternate))
1842 }
1843 }
1844 }
1845
1846 fn checked_payload<'a>(&self, bytes: &'a [u8]) -> Result<&'a [u8], ProtocolCodecError> {
1847 if bytes.len() < 4 {
1848 return Err(ProtocolCodecError::TruncatedFrame {
1849 actual: bytes.len(),
1850 });
1851 }
1852
1853 let declared =
1854 u32::from_be_bytes(bytes[..4].try_into().expect("length prefix is four bytes"))
1855 as usize;
1856 if declared > self.max_frame_bytes {
1857 return Err(ProtocolCodecError::FrameTooLarge {
1858 size: declared,
1859 max: self.max_frame_bytes,
1860 });
1861 }
1862
1863 let actual = bytes.len() - 4;
1864 if declared != actual {
1865 return Err(ProtocolCodecError::LengthPrefixMismatch { declared, actual });
1866 }
1867 Ok(&bytes[4..])
1868 }
1869}
1870
1871impl Default for NativeFrameCodec {
1872 fn default() -> Self {
1873 Self::new(DEFAULT_MAX_FRAME_BYTES)
1874 }
1875}
1876
1877#[derive(Debug)]
1878pub struct ResponseTracker {
1879 pending: HashMap<RequestId, PendingRequest>,
1880 completed: HashSet<RequestId>,
1881 completed_order: VecDeque<RequestId>,
1882 completed_cap: usize,
1883}
1884
1885#[derive(Debug)]
1886pub struct SidecarResponseTracker {
1887 pending: HashMap<RequestId, PendingSidecarRequest>,
1888 completed: HashSet<RequestId>,
1889 completed_order: VecDeque<RequestId>,
1890 completed_cap: usize,
1891}
1892
1893impl ResponseTracker {
1894 pub fn with_completed_cap(completed_cap: usize) -> Self {
1895 Self {
1896 pending: HashMap::new(),
1897 completed: HashSet::new(),
1898 completed_order: VecDeque::new(),
1899 completed_cap: completed_cap.max(1),
1900 }
1901 }
1902
1903 pub fn completed_count(&self) -> usize {
1904 self.completed.len()
1905 }
1906
1907 pub fn register_request(&mut self, request: &RequestFrame) -> Result<(), ResponseTrackerError> {
1908 if self.pending.contains_key(&request.request_id)
1909 || self.completed.contains(&request.request_id)
1910 {
1911 return Err(ResponseTrackerError::DuplicateRequestId {
1912 request_id: request.request_id,
1913 });
1914 }
1915
1916 self.pending.insert(
1917 request.request_id,
1918 PendingRequest {
1919 ownership: request.ownership.clone(),
1920 expected_response: request.payload.expected_response(),
1921 },
1922 );
1923 Ok(())
1924 }
1925
1926 pub fn accept_response(
1927 &mut self,
1928 response: &ResponseFrame,
1929 ) -> Result<(), ResponseTrackerError> {
1930 if self.completed.contains(&response.request_id) {
1931 return Err(ResponseTrackerError::DuplicateResponse {
1932 request_id: response.request_id,
1933 });
1934 }
1935
1936 let pending = self.pending.get(&response.request_id).ok_or(
1937 ResponseTrackerError::UnmatchedResponse {
1938 request_id: response.request_id,
1939 },
1940 )?;
1941
1942 if pending.ownership != response.ownership {
1943 return Err(ResponseTrackerError::OwnershipMismatch {
1944 request_id: response.request_id,
1945 expected: Box::new(pending.ownership.clone()),
1946 actual: Box::new(response.ownership.clone()),
1947 });
1948 }
1949
1950 if !pending.expected_response.matches(&response.payload) {
1951 return Err(ResponseTrackerError::ResponseKindMismatch {
1952 request_id: response.request_id,
1953 expected: pending.expected_response.as_str().to_string(),
1954 actual: response.payload.kind_name().to_string(),
1955 });
1956 }
1957
1958 self.pending
1959 .remove(&response.request_id)
1960 .expect("pending response should still exist after validation");
1961 self.completed.insert(response.request_id);
1962 self.completed_order.push_back(response.request_id);
1963 while self.completed.len() > self.completed_cap {
1964 if let Some(evicted) = self.completed_order.pop_front() {
1965 self.completed.remove(&evicted);
1966 }
1967 }
1968 Ok(())
1969 }
1970}
1971
1972impl Default for ResponseTracker {
1973 fn default() -> Self {
1974 Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
1975 }
1976}
1977
1978impl SidecarResponseTracker {
1979 pub fn with_completed_cap(completed_cap: usize) -> Self {
1980 Self {
1981 pending: HashMap::new(),
1982 completed: HashSet::new(),
1983 completed_order: VecDeque::new(),
1984 completed_cap: completed_cap.max(1),
1985 }
1986 }
1987
1988 pub fn pending_count(&self) -> usize {
1989 self.pending.len()
1990 }
1991
1992 pub fn completed_count(&self) -> usize {
1993 self.completed.len()
1994 }
1995
1996 pub fn register_request(
1997 &mut self,
1998 request: &SidecarRequestFrame,
1999 ) -> Result<(), SidecarResponseTrackerError> {
2000 if self.pending.contains_key(&request.request_id)
2001 || self.completed.contains(&request.request_id)
2002 {
2003 return Err(SidecarResponseTrackerError::DuplicateRequestId {
2004 request_id: request.request_id,
2005 });
2006 }
2007
2008 self.pending.insert(
2009 request.request_id,
2010 PendingSidecarRequest {
2011 ownership: request.ownership.clone(),
2012 expected_response: request.payload.expected_response(),
2013 },
2014 );
2015 Ok(())
2016 }
2017
2018 pub fn accept_response(
2019 &mut self,
2020 response: &SidecarResponseFrame,
2021 ) -> Result<(), SidecarResponseTrackerError> {
2022 if self.completed.contains(&response.request_id) {
2023 return Err(SidecarResponseTrackerError::DuplicateResponse {
2024 request_id: response.request_id,
2025 });
2026 }
2027
2028 let pending = self.pending.get(&response.request_id).ok_or(
2029 SidecarResponseTrackerError::UnmatchedResponse {
2030 request_id: response.request_id,
2031 },
2032 )?;
2033
2034 if pending.ownership != response.ownership {
2035 return Err(SidecarResponseTrackerError::OwnershipMismatch {
2036 request_id: response.request_id,
2037 expected: Box::new(pending.ownership.clone()),
2038 actual: Box::new(response.ownership.clone()),
2039 });
2040 }
2041
2042 if !pending.expected_response.matches(&response.payload) {
2043 return Err(SidecarResponseTrackerError::ResponseKindMismatch {
2044 request_id: response.request_id,
2045 expected: pending.expected_response.as_str().to_string(),
2046 actual: response.payload.kind_name().to_string(),
2047 });
2048 }
2049
2050 self.pending
2051 .remove(&response.request_id)
2052 .expect("pending sidecar response should still exist after validation");
2053 self.completed.insert(response.request_id);
2054 self.completed_order.push_back(response.request_id);
2055 while self.completed.len() > self.completed_cap {
2056 if let Some(evicted) = self.completed_order.pop_front() {
2057 self.completed.remove(&evicted);
2058 }
2059 }
2060 Ok(())
2061 }
2062}
2063
2064impl Default for SidecarResponseTracker {
2065 fn default() -> Self {
2066 Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2067 }
2068}
2069
2070#[derive(Debug, Clone, PartialEq, Eq)]
2071pub enum ResponseTrackerError {
2072 DuplicateRequestId {
2073 request_id: RequestId,
2074 },
2075 UnmatchedResponse {
2076 request_id: RequestId,
2077 },
2078 DuplicateResponse {
2079 request_id: RequestId,
2080 },
2081 OwnershipMismatch {
2082 request_id: RequestId,
2083 expected: Box<OwnershipScope>,
2084 actual: Box<OwnershipScope>,
2085 },
2086 ResponseKindMismatch {
2087 request_id: RequestId,
2088 expected: String,
2089 actual: String,
2090 },
2091}
2092
2093impl fmt::Display for ResponseTrackerError {
2094 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2095 match self {
2096 Self::DuplicateRequestId { request_id } => {
2097 write!(f, "request id {request_id} is already tracked")
2098 }
2099 Self::UnmatchedResponse { request_id } => {
2100 write!(
2101 f,
2102 "response id {request_id} does not match any pending request"
2103 )
2104 }
2105 Self::DuplicateResponse { request_id } => {
2106 write!(f, "response id {request_id} has already been completed")
2107 }
2108 Self::OwnershipMismatch {
2109 request_id,
2110 expected,
2111 actual,
2112 } => write!(
2113 f,
2114 "response id {request_id} used ownership {:?}, expected {:?}",
2115 actual, expected
2116 ),
2117 Self::ResponseKindMismatch {
2118 request_id,
2119 expected,
2120 actual,
2121 } => write!(
2122 f,
2123 "response id {request_id} carried {actual}, expected {expected}",
2124 ),
2125 }
2126 }
2127}
2128
2129impl Error for ResponseTrackerError {}
2130
2131#[derive(Debug, Clone, PartialEq, Eq)]
2132pub enum SidecarResponseTrackerError {
2133 DuplicateRequestId {
2134 request_id: RequestId,
2135 },
2136 UnmatchedResponse {
2137 request_id: RequestId,
2138 },
2139 DuplicateResponse {
2140 request_id: RequestId,
2141 },
2142 OwnershipMismatch {
2143 request_id: RequestId,
2144 expected: Box<OwnershipScope>,
2145 actual: Box<OwnershipScope>,
2146 },
2147 ResponseKindMismatch {
2148 request_id: RequestId,
2149 expected: String,
2150 actual: String,
2151 },
2152}
2153
2154impl fmt::Display for SidecarResponseTrackerError {
2155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2156 match self {
2157 Self::DuplicateRequestId { request_id } => {
2158 write!(f, "sidecar request id {request_id} is already tracked")
2159 }
2160 Self::UnmatchedResponse { request_id } => {
2161 write!(
2162 f,
2163 "sidecar response id {request_id} does not match any pending request"
2164 )
2165 }
2166 Self::DuplicateResponse { request_id } => {
2167 write!(
2168 f,
2169 "sidecar response id {request_id} has already been completed"
2170 )
2171 }
2172 Self::OwnershipMismatch {
2173 request_id,
2174 expected,
2175 actual,
2176 } => write!(
2177 f,
2178 "sidecar response id {request_id} used ownership {:?}, expected {:?}",
2179 actual, expected
2180 ),
2181 Self::ResponseKindMismatch {
2182 request_id,
2183 expected,
2184 actual,
2185 } => write!(
2186 f,
2187 "sidecar response id {request_id} carried {actual}, expected {expected}",
2188 ),
2189 }
2190 }
2191}
2192
2193impl Error for SidecarResponseTrackerError {}
2194
2195#[derive(Debug, Clone, PartialEq, Eq)]
2196struct PendingRequest {
2197 ownership: OwnershipScope,
2198 expected_response: ExpectedResponseKind,
2199}
2200
2201#[derive(Debug, Clone, PartialEq, Eq)]
2202struct PendingSidecarRequest {
2203 ownership: OwnershipScope,
2204 expected_response: ExpectedSidecarResponseKind,
2205}
2206
2207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2208enum ExpectedResponseKind {
2209 Authenticated,
2210 SessionOpened,
2211 VmCreated,
2212 VmDisposed,
2213 RootFilesystemBootstrapped,
2214 VmConfigured,
2215 HostCallbacksRegistered,
2216 LayerCreated,
2217 LayerSealed,
2218 SnapshotImported,
2219 SnapshotExported,
2220 OverlayCreated,
2221 GuestFilesystemResult,
2222 RootFilesystemSnapshot,
2223 ProcessStarted,
2224 StdinWritten,
2225 StdinClosed,
2226 ProcessKilled,
2227 ProcessSnapshot,
2228 ResourceSnapshot,
2229 ListenerSnapshot,
2230 BoundUdpSnapshot,
2231 VmFetchResult,
2232 SignalState,
2233 ZombieTimerCount,
2234 FilesystemResult,
2235 #[allow(dead_code)]
2238 PermissionDecision,
2239 PersistenceState,
2240 PersistenceFlushed,
2241 ExtResult,
2242 GuestKernelResult,
2243 PtyResized,
2244 PackageLinked,
2245 ProvidedCommands,
2246}
2247
2248#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2249enum ExpectedSidecarResponseKind {
2250 HostCallback,
2251 JsBridge,
2252 Ext,
2253}
2254
2255impl ExpectedResponseKind {
2256 fn as_str(self) -> &'static str {
2257 match self {
2258 Self::Authenticated => "authenticated",
2259 Self::SessionOpened => "session_opened",
2260 Self::VmCreated => "vm_created",
2261 Self::VmDisposed => "vm_disposed",
2262 Self::RootFilesystemBootstrapped => "root_filesystem_bootstrapped",
2263 Self::VmConfigured => "vm_configured",
2264 Self::HostCallbacksRegistered => "host_callbacks_registered",
2265 Self::LayerCreated => "layer_created",
2266 Self::LayerSealed => "layer_sealed",
2267 Self::SnapshotImported => "snapshot_imported",
2268 Self::SnapshotExported => "snapshot_exported",
2269 Self::OverlayCreated => "overlay_created",
2270 Self::GuestFilesystemResult => "guest_filesystem_result",
2271 Self::RootFilesystemSnapshot => "root_filesystem_snapshot",
2272 Self::ProcessStarted => "process_started",
2273 Self::StdinWritten => "stdin_written",
2274 Self::StdinClosed => "stdin_closed",
2275 Self::ProcessKilled => "process_killed",
2276 Self::ProcessSnapshot => "process_snapshot",
2277 Self::ResourceSnapshot => "resource_snapshot",
2278 Self::ListenerSnapshot => "listener_snapshot",
2279 Self::BoundUdpSnapshot => "bound_udp_snapshot",
2280 Self::VmFetchResult => "vm_fetch_result",
2281 Self::SignalState => "signal_state",
2282 Self::ZombieTimerCount => "zombie_timer_count",
2283 Self::FilesystemResult => "filesystem_result",
2284 Self::PermissionDecision => "permission_decision",
2285 Self::PersistenceState => "persistence_state",
2286 Self::PersistenceFlushed => "persistence_flushed",
2287 Self::ExtResult => "ext_result",
2288 Self::GuestKernelResult => "guest_kernel_result",
2289 Self::PtyResized => "pty_resized",
2290 Self::PackageLinked => "package_linked",
2291 Self::ProvidedCommands => "provided_commands_response",
2292 }
2293 }
2294
2295 fn matches(self, payload: &ResponsePayload) -> bool {
2296 match payload {
2297 ResponsePayload::Rejected(_) => true,
2298 _ => payload.kind_name() == self.as_str(),
2299 }
2300 }
2301}
2302
2303impl ExpectedSidecarResponseKind {
2304 fn as_str(self) -> &'static str {
2305 match self {
2306 Self::HostCallback => "host_callback_result",
2307 Self::JsBridge => "js_bridge_result",
2308 Self::Ext => "ext_result",
2309 }
2310 }
2311
2312 fn matches(self, payload: &SidecarResponsePayload) -> bool {
2313 payload.kind_name() == self.as_str()
2314 }
2315}
2316
2317impl RequestPayload {
2318 fn ownership_requirement(&self) -> OwnershipRequirement {
2319 match self {
2320 Self::Authenticate(_) | Self::OpenSession(_) => OwnershipRequirement::Connection,
2321 Self::CreateVm(_) | Self::PersistenceLoad(_) | Self::PersistenceFlush(_) => {
2322 OwnershipRequirement::Session
2323 }
2324 Self::DisposeVm(_)
2325 | Self::BootstrapRootFilesystem(_)
2326 | Self::ConfigureVm(_)
2327 | Self::RegisterHostCallbacks(_)
2328 | Self::CreateLayer(_)
2329 | Self::SealLayer(_)
2330 | Self::ImportSnapshot(_)
2331 | Self::ExportSnapshot(_)
2332 | Self::CreateOverlay(_)
2333 | Self::GuestFilesystemCall(_)
2334 | Self::SnapshotRootFilesystem(_)
2335 | Self::Execute(_)
2336 | Self::WriteStdin(_)
2337 | Self::CloseStdin(_)
2338 | Self::KillProcess(_)
2339 | Self::GetProcessSnapshot(_)
2340 | Self::GetResourceSnapshot(_)
2341 | Self::FindListener(_)
2342 | Self::FindBoundUdp(_)
2343 | Self::VmFetch(_)
2344 | Self::GetSignalState(_)
2345 | Self::GetZombieTimerCount(_)
2346 | Self::GuestKernelCall(_)
2347 | Self::ResizePty(_)
2348 | Self::LinkPackage(_)
2349 | Self::ProvidedCommands(_)
2350 | Self::HostFilesystemCall(_) => OwnershipRequirement::Vm,
2351 Self::Ext(_) => OwnershipRequirement::Any,
2352 }
2353 }
2354
2355 fn expected_response(&self) -> ExpectedResponseKind {
2356 match self {
2357 Self::Authenticate(_) => ExpectedResponseKind::Authenticated,
2358 Self::OpenSession(_) => ExpectedResponseKind::SessionOpened,
2359 Self::CreateVm(_) => ExpectedResponseKind::VmCreated,
2360 Self::DisposeVm(_) => ExpectedResponseKind::VmDisposed,
2361 Self::BootstrapRootFilesystem(_) => ExpectedResponseKind::RootFilesystemBootstrapped,
2362 Self::ConfigureVm(_) => ExpectedResponseKind::VmConfigured,
2363 Self::RegisterHostCallbacks(_) => ExpectedResponseKind::HostCallbacksRegistered,
2364 Self::CreateLayer(_) => ExpectedResponseKind::LayerCreated,
2365 Self::SealLayer(_) => ExpectedResponseKind::LayerSealed,
2366 Self::ImportSnapshot(_) => ExpectedResponseKind::SnapshotImported,
2367 Self::ExportSnapshot(_) => ExpectedResponseKind::SnapshotExported,
2368 Self::CreateOverlay(_) => ExpectedResponseKind::OverlayCreated,
2369 Self::GuestFilesystemCall(_) => ExpectedResponseKind::GuestFilesystemResult,
2370 Self::SnapshotRootFilesystem(_) => ExpectedResponseKind::RootFilesystemSnapshot,
2371 Self::Execute(_) => ExpectedResponseKind::ProcessStarted,
2372 Self::WriteStdin(_) => ExpectedResponseKind::StdinWritten,
2373 Self::CloseStdin(_) => ExpectedResponseKind::StdinClosed,
2374 Self::KillProcess(_) => ExpectedResponseKind::ProcessKilled,
2375 Self::GetProcessSnapshot(_) => ExpectedResponseKind::ProcessSnapshot,
2376 Self::GetResourceSnapshot(_) => ExpectedResponseKind::ResourceSnapshot,
2377 Self::FindListener(_) => ExpectedResponseKind::ListenerSnapshot,
2378 Self::FindBoundUdp(_) => ExpectedResponseKind::BoundUdpSnapshot,
2379 Self::VmFetch(_) => ExpectedResponseKind::VmFetchResult,
2380 Self::GetSignalState(_) => ExpectedResponseKind::SignalState,
2381 Self::GetZombieTimerCount(_) => ExpectedResponseKind::ZombieTimerCount,
2382 Self::HostFilesystemCall(_) => ExpectedResponseKind::FilesystemResult,
2383 Self::PersistenceLoad(_) => ExpectedResponseKind::PersistenceState,
2384 Self::PersistenceFlush(_) => ExpectedResponseKind::PersistenceFlushed,
2385 Self::Ext(_) => ExpectedResponseKind::ExtResult,
2386 Self::GuestKernelCall(_) => ExpectedResponseKind::GuestKernelResult,
2387 Self::ResizePty(_) => ExpectedResponseKind::PtyResized,
2388 Self::LinkPackage(_) => ExpectedResponseKind::PackageLinked,
2389 Self::ProvidedCommands(_) => ExpectedResponseKind::ProvidedCommands,
2390 }
2391 }
2392}
2393
2394impl SidecarRequestPayload {
2395 fn ownership_requirement(&self) -> OwnershipRequirement {
2396 OwnershipRequirement::Vm
2397 }
2398
2399 fn expected_response(&self) -> ExpectedSidecarResponseKind {
2400 match self {
2401 Self::HostCallback(_) => ExpectedSidecarResponseKind::HostCallback,
2402 Self::JsBridgeCall(_) => ExpectedSidecarResponseKind::JsBridge,
2403 Self::Ext(_) => ExpectedSidecarResponseKind::Ext,
2404 }
2405 }
2406}
2407
2408impl ResponsePayload {
2409 fn ownership_requirement(&self) -> OwnershipRequirement {
2410 match self {
2411 Self::Authenticated(_) | Self::SessionOpened(_) => OwnershipRequirement::Connection,
2412 Self::VmCreated(_) | Self::PersistenceState(_) | Self::PersistenceFlushed(_) => {
2413 OwnershipRequirement::Session
2414 }
2415 Self::Rejected(_) => OwnershipRequirement::Any,
2416 Self::VmDisposed(_)
2417 | Self::RootFilesystemBootstrapped(_)
2418 | Self::VmConfigured(_)
2419 | Self::HostCallbacksRegistered(_)
2420 | Self::LayerCreated(_)
2421 | Self::LayerSealed(_)
2422 | Self::SnapshotImported(_)
2423 | Self::SnapshotExported(_)
2424 | Self::OverlayCreated(_)
2425 | Self::GuestFilesystemResult(_)
2426 | Self::RootFilesystemSnapshot(_)
2427 | Self::ProcessStarted(_)
2428 | Self::StdinWritten(_)
2429 | Self::StdinClosed(_)
2430 | Self::ProcessKilled(_)
2431 | Self::ProcessSnapshot(_)
2432 | Self::ResourceSnapshot(_)
2433 | Self::ListenerSnapshot(_)
2434 | Self::BoundUdpSnapshot(_)
2435 | Self::VmFetchResult(_)
2436 | Self::SignalState(_)
2437 | Self::ZombieTimerCount(_)
2438 | Self::FilesystemResult(_)
2439 | Self::PermissionDecision(_)
2440 | Self::GuestKernelResult(_)
2441 | Self::PtyResized(_)
2442 | Self::PackageLinked(_)
2443 | Self::ProvidedCommands(_) => OwnershipRequirement::Vm,
2444 Self::ExtResult(_) => OwnershipRequirement::Any,
2445 }
2446 }
2447
2448 fn kind_name(&self) -> &'static str {
2449 match self {
2450 Self::Authenticated(_) => "authenticated",
2451 Self::SessionOpened(_) => "session_opened",
2452 Self::VmCreated(_) => "vm_created",
2453 Self::VmDisposed(_) => "vm_disposed",
2454 Self::RootFilesystemBootstrapped(_) => "root_filesystem_bootstrapped",
2455 Self::VmConfigured(_) => "vm_configured",
2456 Self::HostCallbacksRegistered(_) => "host_callbacks_registered",
2457 Self::LayerCreated(_) => "layer_created",
2458 Self::LayerSealed(_) => "layer_sealed",
2459 Self::SnapshotImported(_) => "snapshot_imported",
2460 Self::SnapshotExported(_) => "snapshot_exported",
2461 Self::OverlayCreated(_) => "overlay_created",
2462 Self::GuestFilesystemResult(_) => "guest_filesystem_result",
2463 Self::RootFilesystemSnapshot(_) => "root_filesystem_snapshot",
2464 Self::ProcessStarted(_) => "process_started",
2465 Self::StdinWritten(_) => "stdin_written",
2466 Self::StdinClosed(_) => "stdin_closed",
2467 Self::ProcessKilled(_) => "process_killed",
2468 Self::ProcessSnapshot(_) => "process_snapshot",
2469 Self::ResourceSnapshot(_) => "resource_snapshot",
2470 Self::ListenerSnapshot(_) => "listener_snapshot",
2471 Self::BoundUdpSnapshot(_) => "bound_udp_snapshot",
2472 Self::VmFetchResult(_) => "vm_fetch_result",
2473 Self::SignalState(_) => "signal_state",
2474 Self::ZombieTimerCount(_) => "zombie_timer_count",
2475 Self::FilesystemResult(_) => "filesystem_result",
2476 Self::PermissionDecision(_) => "permission_decision",
2477 Self::PersistenceState(_) => "persistence_state",
2478 Self::PersistenceFlushed(_) => "persistence_flushed",
2479 Self::Rejected(_) => "rejected",
2480 Self::ExtResult(_) => "ext_result",
2481 Self::GuestKernelResult(_) => "guest_kernel_result",
2482 Self::PtyResized(_) => "pty_resized",
2483 Self::PackageLinked(_) => "package_linked",
2484 Self::ProvidedCommands(_) => "provided_commands_response",
2485 }
2486 }
2487}
2488
2489impl SidecarResponsePayload {
2490 fn ownership_requirement(&self) -> OwnershipRequirement {
2491 OwnershipRequirement::Vm
2492 }
2493
2494 fn kind_name(&self) -> &'static str {
2495 match self {
2496 Self::HostCallbackResult(_) => "host_callback_result",
2497 Self::JsBridgeResult(_) => "js_bridge_result",
2498 Self::ExtResult(_) => "ext_result",
2499 }
2500 }
2501}
2502
2503impl EventPayload {
2504 fn ownership_requirement(&self) -> OwnershipRequirement {
2505 match self {
2506 Self::Structured(_) => OwnershipRequirement::SessionOrVm,
2507 Self::VmLifecycle(_) | Self::ProcessOutput(_) | Self::ProcessExited(_) => {
2508 OwnershipRequirement::Vm
2509 }
2510 Self::Ext(_) => OwnershipRequirement::Any,
2511 }
2512 }
2513}
2514
2515pub fn validate_frame(frame: &ProtocolFrame) -> Result<(), ProtocolCodecError> {
2516 match frame {
2517 ProtocolFrame::Request(request) => validate_request(request),
2518 ProtocolFrame::Response(response) => validate_response(response),
2519 ProtocolFrame::Event(event) => validate_event(event),
2520 ProtocolFrame::SidecarRequest(request) => validate_sidecar_request(request),
2521 ProtocolFrame::SidecarResponse(response) => validate_sidecar_response(response),
2522 }
2523}
2524
2525fn validate_request(request: &RequestFrame) -> Result<(), ProtocolCodecError> {
2526 validate_schema(&request.schema)?;
2527 validate_request_id_direction(request.request_id, RequestDirection::Host)?;
2528
2529 validate_ownership(&request.ownership)?;
2530 validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
2531 if let RequestPayload::Authenticate(authenticate) = &request.payload {
2532 if authenticate.auth_token.is_empty() {
2533 return Err(ProtocolCodecError::EmptyAuthToken);
2534 }
2535 }
2536
2537 Ok(())
2538}
2539
2540fn validate_response(response: &ResponseFrame) -> Result<(), ProtocolCodecError> {
2541 validate_schema(&response.schema)?;
2542 validate_request_id_direction(response.request_id, RequestDirection::Host)?;
2543
2544 validate_ownership(&response.ownership)?;
2545 validate_requirement(
2546 response.payload.ownership_requirement(),
2547 &response.ownership,
2548 )?;
2549 Ok(())
2550}
2551
2552fn validate_sidecar_request(request: &SidecarRequestFrame) -> Result<(), ProtocolCodecError> {
2553 validate_schema(&request.schema)?;
2554 validate_request_id_direction(request.request_id, RequestDirection::Sidecar)?;
2555 validate_ownership(&request.ownership)?;
2556 validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
2557 Ok(())
2558}
2559
2560fn validate_sidecar_response(response: &SidecarResponseFrame) -> Result<(), ProtocolCodecError> {
2561 validate_schema(&response.schema)?;
2562 validate_request_id_direction(response.request_id, RequestDirection::Sidecar)?;
2563 validate_ownership(&response.ownership)?;
2564 validate_requirement(
2565 response.payload.ownership_requirement(),
2566 &response.ownership,
2567 )?;
2568 Ok(())
2569}
2570
2571fn validate_event(event: &EventFrame) -> Result<(), ProtocolCodecError> {
2572 validate_schema(&event.schema)?;
2573 validate_ownership(&event.ownership)?;
2574 validate_requirement(event.payload.ownership_requirement(), &event.ownership)?;
2575 Ok(())
2576}
2577
2578fn validate_schema(schema: &ProtocolSchema) -> Result<(), ProtocolCodecError> {
2579 if schema.name != PROTOCOL_NAME || schema.version != PROTOCOL_VERSION {
2580 return Err(ProtocolCodecError::UnsupportedSchema {
2581 name: schema.name.clone(),
2582 version: schema.version,
2583 });
2584 }
2585
2586 Ok(())
2587}
2588
2589fn validate_ownership(ownership: &OwnershipScope) -> Result<(), ProtocolCodecError> {
2590 match ownership {
2591 OwnershipScope::ConnectionOwnership(inner) => {
2592 validate_non_empty("connection_id", &inner.connection_id)
2593 }
2594 OwnershipScope::SessionOwnership(inner) => {
2595 validate_non_empty("connection_id", &inner.connection_id)?;
2596 validate_non_empty("session_id", &inner.session_id)
2597 }
2598 OwnershipScope::VmOwnership(inner) => {
2599 validate_non_empty("connection_id", &inner.connection_id)?;
2600 validate_non_empty("session_id", &inner.session_id)?;
2601 validate_non_empty("vm_id", &inner.vm_id)
2602 }
2603 }
2604}
2605
2606fn validate_non_empty(field: &'static str, value: &str) -> Result<(), ProtocolCodecError> {
2607 if value.is_empty() {
2608 return Err(ProtocolCodecError::EmptyOwnershipField { field });
2609 }
2610
2611 Ok(())
2612}
2613
2614fn validate_request_id_direction(
2615 request_id: RequestId,
2616 direction: RequestDirection,
2617) -> Result<(), ProtocolCodecError> {
2618 if request_id == 0 {
2619 return Err(ProtocolCodecError::InvalidRequestId);
2620 }
2621
2622 let matches_direction = match direction {
2623 RequestDirection::Host => request_id > 0,
2624 RequestDirection::Sidecar => request_id < 0,
2625 };
2626 if matches_direction {
2627 Ok(())
2628 } else {
2629 Err(ProtocolCodecError::InvalidRequestDirection {
2630 request_id,
2631 expected: direction,
2632 })
2633 }
2634}
2635
2636fn validate_requirement(
2637 required: OwnershipRequirement,
2638 ownership: &OwnershipScope,
2639) -> Result<(), ProtocolCodecError> {
2640 let actual = match ownership {
2641 OwnershipScope::ConnectionOwnership(..) => OwnershipRequirement::Connection,
2642 OwnershipScope::SessionOwnership(..) => OwnershipRequirement::Session,
2643 OwnershipScope::VmOwnership(..) => OwnershipRequirement::Vm,
2644 };
2645
2646 let valid = match required {
2647 OwnershipRequirement::Any => true,
2648 OwnershipRequirement::Connection => {
2649 matches!(ownership, OwnershipScope::ConnectionOwnership(..))
2650 }
2651 OwnershipRequirement::Session => matches!(ownership, OwnershipScope::SessionOwnership(..)),
2652 OwnershipRequirement::Vm => matches!(ownership, OwnershipScope::VmOwnership(..)),
2653 OwnershipRequirement::SessionOrVm => {
2654 matches!(
2655 ownership,
2656 OwnershipScope::SessionOwnership(..) | OwnershipScope::VmOwnership(..)
2657 )
2658 }
2659 };
2660
2661 if valid {
2662 Ok(())
2663 } else {
2664 Err(ProtocolCodecError::InvalidOwnershipScope { required, actual })
2665 }
2666}
2667
2668#[derive(Debug, Deserialize, Default)]
2673pub struct JavascriptChildProcessSpawnOptions {
2674 #[serde(default)]
2675 pub cwd: Option<String>,
2676 #[serde(default)]
2677 pub env: BTreeMap<String, String>,
2678 #[serde(rename = "internalBootstrapEnv", default)]
2679 pub internal_bootstrap_env: BTreeMap<String, String>,
2680 #[serde(default)]
2681 pub input: Option<Value>,
2682 #[serde(default)]
2683 pub shell: bool,
2684 #[serde(default)]
2685 pub detached: bool,
2686 #[serde(default)]
2687 pub stdio: Vec<String>,
2688 #[serde(default)]
2689 pub timeout: Option<u64>,
2690 #[serde(rename = "killSignal", default)]
2691 pub kill_signal: Option<String>,
2692}
2693
2694#[derive(Debug, Deserialize)]
2695pub struct JavascriptChildProcessSpawnRequest {
2696 pub command: String,
2697 #[serde(default)]
2698 pub args: Vec<String>,
2699 #[serde(default)]
2700 pub options: JavascriptChildProcessSpawnOptions,
2701}
2702
2703#[derive(Debug, Deserialize)]
2704pub struct JavascriptNetConnectRequest {
2705 #[serde(default)]
2706 pub host: Option<String>,
2707 #[serde(default)]
2708 pub port: Option<u16>,
2709 #[serde(default)]
2710 pub path: Option<String>,
2711 #[serde(rename = "localAddress", default)]
2712 pub local_address: Option<String>,
2713 #[serde(rename = "localPort", default)]
2714 pub local_port: Option<u16>,
2715 #[serde(rename = "localReservation", default)]
2716 pub local_reservation: Option<String>,
2717}
2718
2719#[derive(Debug, Deserialize)]
2720pub struct JavascriptNetReserveTcpPortRequest {
2721 #[serde(default)]
2722 pub host: Option<String>,
2723 #[serde(default)]
2724 pub port: Option<u16>,
2725}
2726
2727#[derive(Debug, Deserialize)]
2728pub struct JavascriptNetListenRequest {
2729 #[serde(default)]
2730 pub host: Option<String>,
2731 #[serde(default)]
2732 pub port: Option<u16>,
2733 #[serde(default)]
2734 pub path: Option<String>,
2735 #[serde(default)]
2736 pub backlog: Option<u32>,
2737 #[serde(rename = "localReservation", default)]
2738 pub local_reservation: Option<String>,
2739}
2740
2741#[derive(Debug, Deserialize)]
2742pub struct JavascriptDgramCreateSocketRequest {
2743 #[serde(rename = "type")]
2744 pub socket_type: String,
2745}
2746
2747#[derive(Debug, Deserialize)]
2748pub struct JavascriptDgramBindRequest {
2749 #[serde(default)]
2750 pub address: Option<String>,
2751 #[serde(default)]
2752 pub port: u16,
2753}
2754
2755#[derive(Debug, Deserialize)]
2756pub struct JavascriptDgramSendRequest {
2757 #[serde(default)]
2758 pub address: Option<String>,
2759 pub port: u16,
2760}
2761
2762#[derive(Debug, Deserialize)]
2763pub struct JavascriptDnsLookupRequest {
2764 pub hostname: String,
2765 #[serde(default)]
2766 pub family: Option<u8>,
2767}
2768
2769#[derive(Debug, Deserialize)]
2770pub struct JavascriptDnsResolveRequest {
2771 pub hostname: String,
2772 #[serde(default)]
2773 pub rrtype: Option<String>,
2774}