Skip to main content

agentos_sidecar_protocol/
protocol.rs

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
30/// Convert the compatibility protocol frame into the generated wire frame.
31pub 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        ProtocolFrame::Control(frame) => {
79            generated_protocol::ProtocolFrame::ControlFrame(frame.clone())
80        }
81    })
82}
83
84/// Convert the generated wire frame into the compatibility protocol frame.
85pub fn from_generated_protocol_frame(
86    frame: generated_protocol::ProtocolFrame,
87) -> Result<ProtocolFrame, ProtocolCodecError> {
88    Ok(match frame {
89        generated_protocol::ProtocolFrame::RequestFrame(frame) => {
90            ProtocolFrame::Request(RequestFrame {
91                schema: from_generated_protocol_schema(frame.schema),
92                request_id: frame.request_id,
93                ownership: from_generated_ownership_scope(frame.ownership),
94                payload: from_generated_request_payload(frame.payload)?,
95            })
96        }
97        generated_protocol::ProtocolFrame::ResponseFrame(frame) => {
98            ProtocolFrame::Response(ResponseFrame {
99                schema: from_generated_protocol_schema(frame.schema),
100                request_id: frame.request_id,
101                ownership: from_generated_ownership_scope(frame.ownership),
102                payload: from_generated_response_payload(frame.payload)?,
103            })
104        }
105        generated_protocol::ProtocolFrame::EventFrame(frame) => ProtocolFrame::Event(EventFrame {
106            schema: from_generated_protocol_schema(frame.schema),
107            ownership: from_generated_ownership_scope(frame.ownership),
108            payload: from_generated_event_payload(frame.payload),
109        }),
110        generated_protocol::ProtocolFrame::SidecarRequestFrame(frame) => {
111            ProtocolFrame::SidecarRequest(SidecarRequestFrame {
112                schema: from_generated_protocol_schema(frame.schema),
113                request_id: frame.request_id,
114                ownership: from_generated_ownership_scope(frame.ownership),
115                payload: from_generated_sidecar_request_payload(frame.payload)?,
116            })
117        }
118        generated_protocol::ProtocolFrame::SidecarResponseFrame(frame) => {
119            ProtocolFrame::SidecarResponse(SidecarResponseFrame {
120                schema: from_generated_protocol_schema(frame.schema),
121                request_id: frame.request_id,
122                ownership: from_generated_ownership_scope(frame.ownership),
123                payload: from_generated_sidecar_response_payload(frame.payload)?,
124            })
125        }
126        generated_protocol::ProtocolFrame::ControlFrame(frame) => ProtocolFrame::Control(frame),
127    })
128}
129
130fn to_generated_protocol_schema(schema: &ProtocolSchema) -> generated_protocol::ProtocolSchema {
131    schema.clone()
132}
133
134fn from_generated_protocol_schema(schema: generated_protocol::ProtocolSchema) -> ProtocolSchema {
135    schema
136}
137
138// `OwnershipScope` is now an alias for the generated `crate::wire::OwnershipScope`, so the
139// compat<->generated converters are identity functions. They are retained so the JSON-carrying
140// frame-conversion chain (still hand-written, out of scope for this pass) keeps compiling
141// without site-by-site rewiring.
142pub(crate) fn to_generated_ownership_scope(
143    ownership: &OwnershipScope,
144) -> generated_protocol::OwnershipScope {
145    ownership.clone()
146}
147
148pub(crate) fn from_generated_ownership_scope(
149    ownership: generated_protocol::OwnershipScope,
150) -> OwnershipScope {
151    ownership
152}
153
154fn to_generated_dispose_reason(reason: &DisposeReason) -> generated_protocol::DisposeReason {
155    match reason {
156        DisposeReason::Requested => generated_protocol::DisposeReason::Requested,
157        DisposeReason::ConnectionClosed => generated_protocol::DisposeReason::ConnectionClosed,
158        DisposeReason::HostShutdown => generated_protocol::DisposeReason::HostShutdown,
159    }
160}
161
162fn from_generated_dispose_reason(reason: generated_protocol::DisposeReason) -> DisposeReason {
163    match reason {
164        generated_protocol::DisposeReason::Requested => DisposeReason::Requested,
165        generated_protocol::DisposeReason::ConnectionClosed => DisposeReason::ConnectionClosed,
166        generated_protocol::DisposeReason::HostShutdown => DisposeReason::HostShutdown,
167    }
168}
169
170fn to_generated_filesystem_operation(
171    operation: &FilesystemOperation,
172) -> generated_protocol::FilesystemOperation {
173    match operation {
174        FilesystemOperation::Read => generated_protocol::FilesystemOperation::Read,
175        FilesystemOperation::Write => generated_protocol::FilesystemOperation::Write,
176        FilesystemOperation::Stat => generated_protocol::FilesystemOperation::Stat,
177        FilesystemOperation::ReadDir => generated_protocol::FilesystemOperation::ReadDir,
178        FilesystemOperation::Mkdir => generated_protocol::FilesystemOperation::Mkdir,
179        FilesystemOperation::Remove => generated_protocol::FilesystemOperation::Remove,
180        FilesystemOperation::Rename => generated_protocol::FilesystemOperation::Rename,
181    }
182}
183
184fn from_generated_filesystem_operation(
185    operation: generated_protocol::FilesystemOperation,
186) -> FilesystemOperation {
187    match operation {
188        generated_protocol::FilesystemOperation::Read => FilesystemOperation::Read,
189        generated_protocol::FilesystemOperation::Write => FilesystemOperation::Write,
190        generated_protocol::FilesystemOperation::Stat => FilesystemOperation::Stat,
191        generated_protocol::FilesystemOperation::ReadDir => FilesystemOperation::ReadDir,
192        generated_protocol::FilesystemOperation::Mkdir => FilesystemOperation::Mkdir,
193        generated_protocol::FilesystemOperation::Remove => FilesystemOperation::Remove,
194        generated_protocol::FilesystemOperation::Rename => FilesystemOperation::Rename,
195    }
196}
197
198fn to_generated_guest_filesystem_operation(
199    operation: &GuestFilesystemOperation,
200) -> generated_protocol::GuestFilesystemOperation {
201    match operation {
202        GuestFilesystemOperation::ReadFile => {
203            generated_protocol::GuestFilesystemOperation::ReadFile
204        }
205        GuestFilesystemOperation::WriteFile => {
206            generated_protocol::GuestFilesystemOperation::WriteFile
207        }
208        GuestFilesystemOperation::CreateDir => {
209            generated_protocol::GuestFilesystemOperation::CreateDir
210        }
211        GuestFilesystemOperation::Mkdir => generated_protocol::GuestFilesystemOperation::Mkdir,
212        GuestFilesystemOperation::Exists => generated_protocol::GuestFilesystemOperation::Exists,
213        GuestFilesystemOperation::Stat => generated_protocol::GuestFilesystemOperation::Stat,
214        GuestFilesystemOperation::Lstat => generated_protocol::GuestFilesystemOperation::Lstat,
215        GuestFilesystemOperation::ReadDir => generated_protocol::GuestFilesystemOperation::ReadDir,
216        GuestFilesystemOperation::ReadDirRecursive => {
217            generated_protocol::GuestFilesystemOperation::ReadDirRecursive
218        }
219        GuestFilesystemOperation::RemoveFile => {
220            generated_protocol::GuestFilesystemOperation::RemoveFile
221        }
222        GuestFilesystemOperation::RemoveDir => {
223            generated_protocol::GuestFilesystemOperation::RemoveDir
224        }
225        GuestFilesystemOperation::Remove => generated_protocol::GuestFilesystemOperation::Remove,
226        GuestFilesystemOperation::Copy => generated_protocol::GuestFilesystemOperation::Copy,
227        GuestFilesystemOperation::Move => generated_protocol::GuestFilesystemOperation::Move,
228        GuestFilesystemOperation::Rename => generated_protocol::GuestFilesystemOperation::Rename,
229        GuestFilesystemOperation::Realpath => {
230            generated_protocol::GuestFilesystemOperation::Realpath
231        }
232        GuestFilesystemOperation::Symlink => generated_protocol::GuestFilesystemOperation::Symlink,
233        GuestFilesystemOperation::ReadLink => {
234            generated_protocol::GuestFilesystemOperation::ReadLink
235        }
236        GuestFilesystemOperation::Link => generated_protocol::GuestFilesystemOperation::Link,
237        GuestFilesystemOperation::Chmod => generated_protocol::GuestFilesystemOperation::Chmod,
238        GuestFilesystemOperation::Chown => generated_protocol::GuestFilesystemOperation::Chown,
239        GuestFilesystemOperation::Utimes => generated_protocol::GuestFilesystemOperation::Utimes,
240        GuestFilesystemOperation::Truncate => {
241            generated_protocol::GuestFilesystemOperation::Truncate
242        }
243        GuestFilesystemOperation::Pread => generated_protocol::GuestFilesystemOperation::Pread,
244        GuestFilesystemOperation::Pwrite => generated_protocol::GuestFilesystemOperation::Pwrite,
245    }
246}
247
248fn from_generated_guest_filesystem_operation(
249    operation: generated_protocol::GuestFilesystemOperation,
250) -> GuestFilesystemOperation {
251    match operation {
252        generated_protocol::GuestFilesystemOperation::ReadFile => {
253            GuestFilesystemOperation::ReadFile
254        }
255        generated_protocol::GuestFilesystemOperation::WriteFile => {
256            GuestFilesystemOperation::WriteFile
257        }
258        generated_protocol::GuestFilesystemOperation::CreateDir => {
259            GuestFilesystemOperation::CreateDir
260        }
261        generated_protocol::GuestFilesystemOperation::Mkdir => GuestFilesystemOperation::Mkdir,
262        generated_protocol::GuestFilesystemOperation::Exists => GuestFilesystemOperation::Exists,
263        generated_protocol::GuestFilesystemOperation::Stat => GuestFilesystemOperation::Stat,
264        generated_protocol::GuestFilesystemOperation::Lstat => GuestFilesystemOperation::Lstat,
265        generated_protocol::GuestFilesystemOperation::ReadDir => GuestFilesystemOperation::ReadDir,
266        generated_protocol::GuestFilesystemOperation::ReadDirRecursive => {
267            GuestFilesystemOperation::ReadDirRecursive
268        }
269        generated_protocol::GuestFilesystemOperation::RemoveFile => {
270            GuestFilesystemOperation::RemoveFile
271        }
272        generated_protocol::GuestFilesystemOperation::RemoveDir => {
273            GuestFilesystemOperation::RemoveDir
274        }
275        generated_protocol::GuestFilesystemOperation::Remove => GuestFilesystemOperation::Remove,
276        generated_protocol::GuestFilesystemOperation::Copy => GuestFilesystemOperation::Copy,
277        generated_protocol::GuestFilesystemOperation::Move => GuestFilesystemOperation::Move,
278        generated_protocol::GuestFilesystemOperation::Rename => GuestFilesystemOperation::Rename,
279        generated_protocol::GuestFilesystemOperation::Realpath => {
280            GuestFilesystemOperation::Realpath
281        }
282        generated_protocol::GuestFilesystemOperation::Symlink => GuestFilesystemOperation::Symlink,
283        generated_protocol::GuestFilesystemOperation::ReadLink => {
284            GuestFilesystemOperation::ReadLink
285        }
286        generated_protocol::GuestFilesystemOperation::Link => GuestFilesystemOperation::Link,
287        generated_protocol::GuestFilesystemOperation::Chmod => GuestFilesystemOperation::Chmod,
288        generated_protocol::GuestFilesystemOperation::Chown => GuestFilesystemOperation::Chown,
289        generated_protocol::GuestFilesystemOperation::Utimes => GuestFilesystemOperation::Utimes,
290        generated_protocol::GuestFilesystemOperation::Truncate => {
291            GuestFilesystemOperation::Truncate
292        }
293        generated_protocol::GuestFilesystemOperation::Pread => GuestFilesystemOperation::Pread,
294        generated_protocol::GuestFilesystemOperation::Pwrite => GuestFilesystemOperation::Pwrite,
295    }
296}
297
298fn to_generated_permission_mode(mode: &PermissionMode) -> generated_protocol::PermissionMode {
299    mode.clone()
300}
301
302fn from_generated_permission_mode(mode: generated_protocol::PermissionMode) -> PermissionMode {
303    mode
304}
305
306fn to_generated_root_filesystem_entry_encoding(
307    encoding: &RootFilesystemEntryEncoding,
308) -> generated_protocol::RootFilesystemEntryEncoding {
309    match encoding {
310        RootFilesystemEntryEncoding::Utf8 => generated_protocol::RootFilesystemEntryEncoding::Utf8,
311        RootFilesystemEntryEncoding::Base64 => {
312            generated_protocol::RootFilesystemEntryEncoding::Base64
313        }
314    }
315}
316
317fn from_generated_root_filesystem_entry_encoding(
318    encoding: generated_protocol::RootFilesystemEntryEncoding,
319) -> RootFilesystemEntryEncoding {
320    match encoding {
321        generated_protocol::RootFilesystemEntryEncoding::Utf8 => RootFilesystemEntryEncoding::Utf8,
322        generated_protocol::RootFilesystemEntryEncoding::Base64 => {
323            RootFilesystemEntryEncoding::Base64
324        }
325    }
326}
327
328fn to_generated_stream_channel(channel: &StreamChannel) -> generated_protocol::StreamChannel {
329    match channel {
330        StreamChannel::Stdout => generated_protocol::StreamChannel::Stdout,
331        StreamChannel::Stderr => generated_protocol::StreamChannel::Stderr,
332    }
333}
334
335fn from_generated_stream_channel(channel: generated_protocol::StreamChannel) -> StreamChannel {
336    match channel {
337        generated_protocol::StreamChannel::Stdout => StreamChannel::Stdout,
338        generated_protocol::StreamChannel::Stderr => StreamChannel::Stderr,
339    }
340}
341
342fn to_generated_vm_lifecycle_state(
343    state: &VmLifecycleState,
344) -> generated_protocol::VmLifecycleState {
345    match state {
346        VmLifecycleState::Creating => generated_protocol::VmLifecycleState::Creating,
347        VmLifecycleState::Ready => generated_protocol::VmLifecycleState::Ready,
348        VmLifecycleState::Disposing => generated_protocol::VmLifecycleState::Disposing,
349        VmLifecycleState::Disposed => generated_protocol::VmLifecycleState::Disposed,
350        VmLifecycleState::Failed => generated_protocol::VmLifecycleState::Failed,
351    }
352}
353
354fn from_generated_vm_lifecycle_state(
355    state: generated_protocol::VmLifecycleState,
356) -> VmLifecycleState {
357    match state {
358        generated_protocol::VmLifecycleState::Creating => VmLifecycleState::Creating,
359        generated_protocol::VmLifecycleState::Ready => VmLifecycleState::Ready,
360        generated_protocol::VmLifecycleState::Disposing => VmLifecycleState::Disposing,
361        generated_protocol::VmLifecycleState::Disposed => VmLifecycleState::Disposed,
362        generated_protocol::VmLifecycleState::Failed => VmLifecycleState::Failed,
363    }
364}
365
366fn to_generated_guest_filesystem_stat(
367    stat: &GuestFilesystemStat,
368) -> generated_protocol::GuestFilesystemStat {
369    stat.clone()
370}
371
372fn from_generated_guest_filesystem_stat(
373    stat: generated_protocol::GuestFilesystemStat,
374) -> GuestFilesystemStat {
375    stat
376}
377
378fn to_generated_process_snapshot_entry(
379    entry: &ProcessSnapshotEntry,
380) -> generated_protocol::ProcessSnapshotEntry {
381    entry.clone()
382}
383
384fn from_generated_process_snapshot_entry(
385    entry: generated_protocol::ProcessSnapshotEntry,
386) -> ProcessSnapshotEntry {
387    entry
388}
389
390fn to_generated_ext_envelope(envelope: &ExtEnvelope) -> generated_protocol::ExtEnvelope {
391    envelope.clone()
392}
393
394fn from_generated_ext_envelope(envelope: generated_protocol::ExtEnvelope) -> ExtEnvelope {
395    envelope
396}
397
398fn to_generated_request_payload(
399    payload: &RequestPayload,
400) -> Result<generated_protocol::RequestPayload, ProtocolCodecError> {
401    Ok(match payload {
402        RequestPayload::Authenticate(inner) => {
403            generated_protocol::RequestPayload::AuthenticateRequest(inner.clone())
404        }
405        RequestPayload::OpenSession(inner) => {
406            generated_protocol::RequestPayload::OpenSessionRequest(inner.clone())
407        }
408        RequestPayload::CreateVm(inner) => {
409            generated_protocol::RequestPayload::CreateVmRequest(inner.clone())
410        }
411        RequestPayload::CompareVmConfig(inner) => {
412            generated_protocol::RequestPayload::CompareVmConfigRequest(inner.clone())
413        }
414        RequestPayload::DisposeVm(inner) => generated_protocol::RequestPayload::DisposeVmRequest(
415            generated_protocol::DisposeVmRequest {
416                reason: to_generated_dispose_reason(&inner.reason),
417            },
418        ),
419        RequestPayload::BootstrapRootFilesystem(inner) => {
420            generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner.clone())
421        }
422        RequestPayload::ConfigureVm(inner) => {
423            generated_protocol::RequestPayload::ConfigureVmRequest(inner.clone())
424        }
425        RequestPayload::RegisterHostCallbacks(inner) => {
426            generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner.clone())
427        }
428        RequestPayload::CreateLayer(_) => generated_protocol::RequestPayload::CreateLayerRequest,
429        RequestPayload::SealLayer(inner) => {
430            generated_protocol::RequestPayload::SealLayerRequest(inner.clone())
431        }
432        RequestPayload::ImportSnapshot(inner) => {
433            generated_protocol::RequestPayload::ImportSnapshotRequest(inner.clone())
434        }
435        RequestPayload::ExportSnapshot(inner) => {
436            generated_protocol::RequestPayload::ExportSnapshotRequest(inner.clone())
437        }
438        RequestPayload::CreateOverlay(inner) => {
439            generated_protocol::RequestPayload::CreateOverlayRequest(inner.clone())
440        }
441        RequestPayload::GuestFilesystemCall(inner) => {
442            generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner.clone())
443        }
444        RequestPayload::SnapshotRootFilesystem(inner) => {
445            generated_protocol::RequestPayload::SnapshotRootFilesystemRequest(inner.clone())
446        }
447        RequestPayload::ListMounts(_) => generated_protocol::RequestPayload::ListMountsRequest,
448        RequestPayload::Execute(inner) => {
449            generated_protocol::RequestPayload::ExecuteRequest(inner.clone())
450        }
451        RequestPayload::WriteStdin(inner) => {
452            generated_protocol::RequestPayload::WriteStdinRequest(inner.clone())
453        }
454        RequestPayload::CloseStdin(inner) => {
455            generated_protocol::RequestPayload::CloseStdinRequest(inner.clone())
456        }
457        RequestPayload::KillProcess(inner) => {
458            generated_protocol::RequestPayload::KillProcessRequest(inner.clone())
459        }
460        RequestPayload::GetProcessSnapshot(_) => {
461            generated_protocol::RequestPayload::GetProcessSnapshotRequest
462        }
463        RequestPayload::GetResourceSnapshot(_) => {
464            generated_protocol::RequestPayload::GetResourceSnapshotRequest
465        }
466        RequestPayload::FindListener(inner) => {
467            generated_protocol::RequestPayload::FindListenerRequest(inner.clone())
468        }
469        RequestPayload::FindBoundUdp(inner) => {
470            generated_protocol::RequestPayload::FindBoundUdpRequest(inner.clone())
471        }
472        RequestPayload::VmFetch(inner) => {
473            generated_protocol::RequestPayload::VmFetchRequest(inner.clone())
474        }
475        RequestPayload::GetSignalState(inner) => {
476            generated_protocol::RequestPayload::GetSignalStateRequest(inner.clone())
477        }
478        RequestPayload::GetZombieTimerCount(_) => {
479            generated_protocol::RequestPayload::GetZombieTimerCountRequest
480        }
481        RequestPayload::HostFilesystemCall(inner) => {
482            generated_protocol::RequestPayload::HostFilesystemCallRequest(
483                generated_protocol::HostFilesystemCallRequest {
484                    operation: to_generated_filesystem_operation(&inner.operation),
485                    path: inner.path.clone(),
486                    payload_size_bytes: inner.payload_size_bytes,
487                },
488            )
489        }
490        RequestPayload::PersistenceLoad(inner) => {
491            generated_protocol::RequestPayload::PersistenceLoadRequest(inner.clone())
492        }
493        RequestPayload::PersistenceFlush(inner) => {
494            generated_protocol::RequestPayload::PersistenceFlushRequest(inner.clone())
495        }
496        RequestPayload::Ext(inner) => {
497            generated_protocol::RequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
498        }
499        RequestPayload::GuestKernelCall(inner) => {
500            generated_protocol::RequestPayload::GuestKernelCallRequest(inner.clone())
501        }
502        RequestPayload::ResizePty(inner) => {
503            generated_protocol::RequestPayload::ResizePtyRequest(inner.clone())
504        }
505        RequestPayload::LinkPackage(inner) => {
506            generated_protocol::RequestPayload::LinkPackageRequest(inner.clone())
507        }
508        RequestPayload::UnlinkPackage(inner) => {
509            generated_protocol::RequestPayload::UnlinkPackageRequest(inner.clone())
510        }
511        RequestPayload::AcquirePackage(inner) => {
512            generated_protocol::RequestPayload::AcquirePackageRequest(inner.clone())
513        }
514        RequestPayload::InstallPackage(inner) => {
515            generated_protocol::RequestPayload::InstallPackageRequest(inner.clone())
516        }
517        RequestPayload::GetPackageCacheStats(_) => {
518            generated_protocol::RequestPayload::GetPackageCacheStatsRequest
519        }
520        RequestPayload::ProvidedCommands(_) => {
521            generated_protocol::RequestPayload::ProvidedCommandsRequest
522        }
523        RequestPayload::ShellExecution(inner) => {
524            generated_protocol::RequestPayload::ShellExecutionRequest(inner.clone())
525        }
526        RequestPayload::ArgvExecution(inner) => {
527            generated_protocol::RequestPayload::ArgvExecutionRequest(inner.clone())
528        }
529        RequestPayload::JavaScriptExecution(inner) => {
530            generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner.clone())
531        }
532        RequestPayload::JavaScriptEvaluation(inner) => {
533            generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner.clone())
534        }
535        RequestPayload::JavaScriptFileExecution(inner) => {
536            generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner.clone())
537        }
538        RequestPayload::TypeScriptExecution(inner) => {
539            generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner.clone())
540        }
541        RequestPayload::TypeScriptEvaluation(inner) => {
542            generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner.clone())
543        }
544        RequestPayload::TypeScriptFileExecution(inner) => {
545            generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner.clone())
546        }
547        RequestPayload::TypeScriptCheck(inner) => {
548            generated_protocol::RequestPayload::TypeScriptCheckRequest(inner.clone())
549        }
550        RequestPayload::TypeScriptProjectCheck(inner) => {
551            generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner.clone())
552        }
553        RequestPayload::NpmProjectInstall(inner) => {
554            generated_protocol::RequestPayload::NpmProjectInstallRequest(inner.clone())
555        }
556        RequestPayload::NpmPackageInstall(inner) => {
557            generated_protocol::RequestPayload::NpmPackageInstallRequest(inner.clone())
558        }
559        RequestPayload::NpmScriptExecution(inner) => {
560            generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner.clone())
561        }
562        RequestPayload::NpmPackageExecution(inner) => {
563            generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner.clone())
564        }
565        RequestPayload::PythonExecution(inner) => {
566            generated_protocol::RequestPayload::PythonExecutionRequest(inner.clone())
567        }
568        RequestPayload::PythonEvaluation(inner) => {
569            generated_protocol::RequestPayload::PythonEvaluationRequest(inner.clone())
570        }
571        RequestPayload::PythonFileExecution(inner) => {
572            generated_protocol::RequestPayload::PythonFileExecutionRequest(inner.clone())
573        }
574        RequestPayload::PythonModuleExecution(inner) => {
575            generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner.clone())
576        }
577        RequestPayload::PythonInstall(inner) => {
578            generated_protocol::RequestPayload::PythonInstallRequest(inner.clone())
579        }
580        RequestPayload::CreateContext(inner) => {
581            generated_protocol::RequestPayload::CreateContextRequest(inner.clone())
582        }
583        RequestPayload::GetExecution(inner) => {
584            generated_protocol::RequestPayload::GetExecutionRequest(inner.clone())
585        }
586        RequestPayload::ListExecutions(_) => {
587            generated_protocol::RequestPayload::ListExecutionsRequest
588        }
589        RequestPayload::WaitExecution(inner) => {
590            generated_protocol::RequestPayload::WaitExecutionRequest(inner.clone())
591        }
592        RequestPayload::CancelExecution(inner) => {
593            generated_protocol::RequestPayload::CancelExecutionRequest(inner.clone())
594        }
595        RequestPayload::SignalExecution(inner) => {
596            generated_protocol::RequestPayload::SignalExecutionRequest(inner.clone())
597        }
598        RequestPayload::ResetExecution(inner) => {
599            generated_protocol::RequestPayload::ResetExecutionRequest(inner.clone())
600        }
601        RequestPayload::DeleteExecution(inner) => {
602            generated_protocol::RequestPayload::DeleteExecutionRequest(inner.clone())
603        }
604        RequestPayload::WriteExecutionStdin(inner) => {
605            generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner.clone())
606        }
607        RequestPayload::CloseExecutionStdin(inner) => {
608            generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner.clone())
609        }
610        RequestPayload::ResizeExecutionPty(inner) => {
611            generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner.clone())
612        }
613        RequestPayload::ReadExecutionOutput(inner) => {
614            generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner.clone())
615        }
616        RequestPayload::ReadProcessOutput(inner) => {
617            generated_protocol::RequestPayload::ReadProcessOutputRequest(inner.clone())
618        }
619    })
620}
621
622fn from_generated_request_payload(
623    payload: generated_protocol::RequestPayload,
624) -> Result<RequestPayload, ProtocolCodecError> {
625    Ok(match payload {
626        generated_protocol::RequestPayload::AuthenticateRequest(inner) => {
627            RequestPayload::Authenticate(inner)
628        }
629        generated_protocol::RequestPayload::OpenSessionRequest(inner) => {
630            RequestPayload::OpenSession(inner)
631        }
632        generated_protocol::RequestPayload::CreateVmRequest(inner) => {
633            RequestPayload::CreateVm(inner)
634        }
635        generated_protocol::RequestPayload::CompareVmConfigRequest(inner) => {
636            RequestPayload::CompareVmConfig(inner)
637        }
638        generated_protocol::RequestPayload::DisposeVmRequest(inner) => {
639            RequestPayload::DisposeVm(DisposeVmRequest {
640                reason: from_generated_dispose_reason(inner.reason),
641            })
642        }
643        generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner) => {
644            RequestPayload::BootstrapRootFilesystem(inner)
645        }
646        generated_protocol::RequestPayload::ConfigureVmRequest(inner) => {
647            RequestPayload::ConfigureVm(inner)
648        }
649        generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner) => {
650            RequestPayload::RegisterHostCallbacks(inner)
651        }
652        generated_protocol::RequestPayload::CreateLayerRequest => {
653            RequestPayload::CreateLayer(CreateLayerRequest {})
654        }
655        generated_protocol::RequestPayload::SealLayerRequest(inner) => {
656            RequestPayload::SealLayer(inner)
657        }
658        generated_protocol::RequestPayload::ImportSnapshotRequest(inner) => {
659            RequestPayload::ImportSnapshot(inner)
660        }
661        generated_protocol::RequestPayload::ExportSnapshotRequest(inner) => {
662            RequestPayload::ExportSnapshot(inner)
663        }
664        generated_protocol::RequestPayload::CreateOverlayRequest(inner) => {
665            RequestPayload::CreateOverlay(inner)
666        }
667        generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner) => {
668            RequestPayload::GuestFilesystemCall(inner)
669        }
670        generated_protocol::RequestPayload::SnapshotRootFilesystemRequest(inner) => {
671            RequestPayload::SnapshotRootFilesystem(inner)
672        }
673        generated_protocol::RequestPayload::ListMountsRequest => {
674            RequestPayload::ListMounts(ListMountsRequest {})
675        }
676        generated_protocol::RequestPayload::ExecuteRequest(inner) => RequestPayload::Execute(inner),
677        generated_protocol::RequestPayload::WriteStdinRequest(inner) => {
678            RequestPayload::WriteStdin(inner)
679        }
680        generated_protocol::RequestPayload::CloseStdinRequest(inner) => {
681            RequestPayload::CloseStdin(inner)
682        }
683        generated_protocol::RequestPayload::KillProcessRequest(inner) => {
684            RequestPayload::KillProcess(inner)
685        }
686        generated_protocol::RequestPayload::GetProcessSnapshotRequest => {
687            RequestPayload::GetProcessSnapshot(GetProcessSnapshotRequest {})
688        }
689        generated_protocol::RequestPayload::GetResourceSnapshotRequest => {
690            RequestPayload::GetResourceSnapshot(GetResourceSnapshotRequest {})
691        }
692        generated_protocol::RequestPayload::FindListenerRequest(inner) => {
693            RequestPayload::FindListener(inner)
694        }
695        generated_protocol::RequestPayload::FindBoundUdpRequest(inner) => {
696            RequestPayload::FindBoundUdp(inner)
697        }
698        generated_protocol::RequestPayload::VmFetchRequest(inner) => RequestPayload::VmFetch(inner),
699        generated_protocol::RequestPayload::GetSignalStateRequest(inner) => {
700            RequestPayload::GetSignalState(inner)
701        }
702        generated_protocol::RequestPayload::GetZombieTimerCountRequest => {
703            RequestPayload::GetZombieTimerCount(GetZombieTimerCountRequest {})
704        }
705        generated_protocol::RequestPayload::HostFilesystemCallRequest(inner) => {
706            RequestPayload::HostFilesystemCall(HostFilesystemCallRequest {
707                operation: from_generated_filesystem_operation(inner.operation),
708                path: inner.path,
709                payload_size_bytes: inner.payload_size_bytes,
710            })
711        }
712        generated_protocol::RequestPayload::PersistenceLoadRequest(inner) => {
713            RequestPayload::PersistenceLoad(inner)
714        }
715        generated_protocol::RequestPayload::PersistenceFlushRequest(inner) => {
716            RequestPayload::PersistenceFlush(inner)
717        }
718        generated_protocol::RequestPayload::ExtEnvelope(inner) => {
719            RequestPayload::Ext(from_generated_ext_envelope(inner))
720        }
721        generated_protocol::RequestPayload::GuestKernelCallRequest(inner) => {
722            RequestPayload::GuestKernelCall(inner)
723        }
724        generated_protocol::RequestPayload::ResizePtyRequest(inner) => {
725            RequestPayload::ResizePty(inner)
726        }
727        generated_protocol::RequestPayload::LinkPackageRequest(inner) => {
728            RequestPayload::LinkPackage(inner)
729        }
730        generated_protocol::RequestPayload::UnlinkPackageRequest(inner) => {
731            RequestPayload::UnlinkPackage(inner)
732        }
733        generated_protocol::RequestPayload::AcquirePackageRequest(inner) => {
734            RequestPayload::AcquirePackage(inner)
735        }
736        generated_protocol::RequestPayload::InstallPackageRequest(inner) => {
737            RequestPayload::InstallPackage(inner)
738        }
739        generated_protocol::RequestPayload::GetPackageCacheStatsRequest => {
740            RequestPayload::GetPackageCacheStats(())
741        }
742        generated_protocol::RequestPayload::ProvidedCommandsRequest => {
743            RequestPayload::ProvidedCommands(ProvidedCommandsRequest {})
744        }
745        generated_protocol::RequestPayload::ShellExecutionRequest(inner) => {
746            RequestPayload::ShellExecution(inner)
747        }
748        generated_protocol::RequestPayload::ArgvExecutionRequest(inner) => {
749            RequestPayload::ArgvExecution(inner)
750        }
751        generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner) => {
752            RequestPayload::JavaScriptExecution(inner)
753        }
754        generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner) => {
755            RequestPayload::JavaScriptEvaluation(inner)
756        }
757        generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner) => {
758            RequestPayload::JavaScriptFileExecution(inner)
759        }
760        generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner) => {
761            RequestPayload::TypeScriptExecution(inner)
762        }
763        generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner) => {
764            RequestPayload::TypeScriptEvaluation(inner)
765        }
766        generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner) => {
767            RequestPayload::TypeScriptFileExecution(inner)
768        }
769        generated_protocol::RequestPayload::TypeScriptCheckRequest(inner) => {
770            RequestPayload::TypeScriptCheck(inner)
771        }
772        generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner) => {
773            RequestPayload::TypeScriptProjectCheck(inner)
774        }
775        generated_protocol::RequestPayload::NpmProjectInstallRequest(inner) => {
776            RequestPayload::NpmProjectInstall(inner)
777        }
778        generated_protocol::RequestPayload::NpmPackageInstallRequest(inner) => {
779            RequestPayload::NpmPackageInstall(inner)
780        }
781        generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner) => {
782            RequestPayload::NpmScriptExecution(inner)
783        }
784        generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner) => {
785            RequestPayload::NpmPackageExecution(inner)
786        }
787        generated_protocol::RequestPayload::PythonExecutionRequest(inner) => {
788            RequestPayload::PythonExecution(inner)
789        }
790        generated_protocol::RequestPayload::PythonEvaluationRequest(inner) => {
791            RequestPayload::PythonEvaluation(inner)
792        }
793        generated_protocol::RequestPayload::PythonFileExecutionRequest(inner) => {
794            RequestPayload::PythonFileExecution(inner)
795        }
796        generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner) => {
797            RequestPayload::PythonModuleExecution(inner)
798        }
799        generated_protocol::RequestPayload::PythonInstallRequest(inner) => {
800            RequestPayload::PythonInstall(inner)
801        }
802        generated_protocol::RequestPayload::CreateContextRequest(inner) => {
803            RequestPayload::CreateContext(inner)
804        }
805        generated_protocol::RequestPayload::GetExecutionRequest(inner) => {
806            RequestPayload::GetExecution(inner)
807        }
808        generated_protocol::RequestPayload::ListExecutionsRequest => {
809            RequestPayload::ListExecutions(ListExecutionsRequest {})
810        }
811        generated_protocol::RequestPayload::WaitExecutionRequest(inner) => {
812            RequestPayload::WaitExecution(inner)
813        }
814        generated_protocol::RequestPayload::CancelExecutionRequest(inner) => {
815            RequestPayload::CancelExecution(inner)
816        }
817        generated_protocol::RequestPayload::SignalExecutionRequest(inner) => {
818            RequestPayload::SignalExecution(inner)
819        }
820        generated_protocol::RequestPayload::ResetExecutionRequest(inner) => {
821            RequestPayload::ResetExecution(inner)
822        }
823        generated_protocol::RequestPayload::DeleteExecutionRequest(inner) => {
824            RequestPayload::DeleteExecution(inner)
825        }
826        generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner) => {
827            RequestPayload::WriteExecutionStdin(inner)
828        }
829        generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner) => {
830            RequestPayload::CloseExecutionStdin(inner)
831        }
832        generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner) => {
833            RequestPayload::ResizeExecutionPty(inner)
834        }
835        generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner) => {
836            RequestPayload::ReadExecutionOutput(inner)
837        }
838        generated_protocol::RequestPayload::ReadProcessOutputRequest(inner) => {
839            RequestPayload::ReadProcessOutput(inner)
840        }
841    })
842}
843
844fn to_generated_response_payload(
845    payload: &ResponsePayload,
846) -> Result<generated_protocol::ResponsePayload, ProtocolCodecError> {
847    Ok(match payload {
848        ResponsePayload::Authenticated(inner) => {
849            generated_protocol::ResponsePayload::AuthenticatedResponse(inner.clone())
850        }
851        ResponsePayload::SessionOpened(inner) => {
852            generated_protocol::ResponsePayload::SessionOpenedResponse(inner.clone())
853        }
854        ResponsePayload::VmCreated(inner) => {
855            generated_protocol::ResponsePayload::VmCreatedResponse(inner.clone())
856        }
857        ResponsePayload::VmConfigCompared(inner) => {
858            generated_protocol::ResponsePayload::VmConfigComparedResponse(inner.clone())
859        }
860        ResponsePayload::VmDisposed(inner) => {
861            generated_protocol::ResponsePayload::VmDisposedResponse(inner.clone())
862        }
863        ResponsePayload::RootFilesystemBootstrapped(inner) => {
864            generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner.clone())
865        }
866        ResponsePayload::VmConfigured(inner) => {
867            generated_protocol::ResponsePayload::VmConfiguredResponse(inner.clone())
868        }
869        ResponsePayload::HostCallbacksRegistered(inner) => {
870            generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner.clone())
871        }
872        ResponsePayload::LayerCreated(inner) => {
873            generated_protocol::ResponsePayload::LayerCreatedResponse(inner.clone())
874        }
875        ResponsePayload::LayerSealed(inner) => {
876            generated_protocol::ResponsePayload::LayerSealedResponse(inner.clone())
877        }
878        ResponsePayload::SnapshotImported(inner) => {
879            generated_protocol::ResponsePayload::SnapshotImportedResponse(inner.clone())
880        }
881        ResponsePayload::SnapshotExported(inner) => {
882            generated_protocol::ResponsePayload::SnapshotExportedResponse(
883                generated_protocol::SnapshotExportedResponse {
884                    layer_id: inner.layer_id.clone(),
885                    entries: inner.entries.clone(),
886                },
887            )
888        }
889        ResponsePayload::OverlayCreated(inner) => {
890            generated_protocol::ResponsePayload::OverlayCreatedResponse(inner.clone())
891        }
892        ResponsePayload::GuestFilesystemResult(inner) => {
893            generated_protocol::ResponsePayload::GuestFilesystemResultResponse(
894                generated_protocol::GuestFilesystemResultResponse {
895                    operation: to_generated_guest_filesystem_operation(&inner.operation),
896                    path: inner.path.clone(),
897                    content: inner.content.clone(),
898                    encoding: inner
899                        .encoding
900                        .as_ref()
901                        .map(to_generated_root_filesystem_entry_encoding),
902                    entries: inner.entries.clone(),
903                    stat: inner.stat.as_ref().map(to_generated_guest_filesystem_stat),
904                    exists: inner.exists,
905                    target: inner.target.clone(),
906                },
907            )
908        }
909        ResponsePayload::RootFilesystemSnapshot(inner) => {
910            generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(
911                generated_protocol::RootFilesystemSnapshotResponse {
912                    entries: inner.entries.clone(),
913                },
914            )
915        }
916        ResponsePayload::MountsListed(inner) => {
917            generated_protocol::ResponsePayload::ListMountsResponse(inner.clone())
918        }
919        ResponsePayload::ProcessStarted(inner) => {
920            generated_protocol::ResponsePayload::ProcessStartedResponse(inner.clone())
921        }
922        ResponsePayload::StdinWritten(inner) => {
923            generated_protocol::ResponsePayload::StdinWrittenResponse(inner.clone())
924        }
925        ResponsePayload::StdinClosed(inner) => {
926            generated_protocol::ResponsePayload::StdinClosedResponse(inner.clone())
927        }
928        ResponsePayload::ProcessKilled(inner) => {
929            generated_protocol::ResponsePayload::ProcessKilledResponse(inner.clone())
930        }
931        ResponsePayload::ProcessSnapshot(inner) => {
932            generated_protocol::ResponsePayload::ProcessSnapshotResponse(
933                generated_protocol::ProcessSnapshotResponse {
934                    processes: inner
935                        .processes
936                        .iter()
937                        .map(to_generated_process_snapshot_entry)
938                        .collect(),
939                },
940            )
941        }
942        ResponsePayload::ResourceSnapshot(inner) => {
943            generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner.clone())
944        }
945        ResponsePayload::ListenerSnapshot(inner) => {
946            generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner.clone())
947        }
948        ResponsePayload::BoundUdpSnapshot(inner) => {
949            generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner.clone())
950        }
951        ResponsePayload::VmFetchResult(inner) => {
952            generated_protocol::ResponsePayload::VmFetchResponse(inner.clone())
953        }
954        ResponsePayload::SignalState(inner) => {
955            generated_protocol::ResponsePayload::SignalStateResponse(inner.clone())
956        }
957        ResponsePayload::ZombieTimerCount(inner) => {
958            generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner.clone())
959        }
960        ResponsePayload::FilesystemResult(inner) => {
961            generated_protocol::ResponsePayload::FilesystemResultResponse(
962                generated_protocol::FilesystemResultResponse {
963                    operation: to_generated_filesystem_operation(&inner.operation),
964                    status: inner.status.clone(),
965                    payload_size_bytes: inner.payload_size_bytes,
966                },
967            )
968        }
969        ResponsePayload::PermissionDecision(inner) => {
970            generated_protocol::ResponsePayload::PermissionDecisionResponse(
971                generated_protocol::PermissionDecisionResponse {
972                    capability: inner.capability.clone(),
973                    decision: to_generated_permission_mode(&inner.decision),
974                },
975            )
976        }
977        ResponsePayload::PersistenceState(inner) => {
978            generated_protocol::ResponsePayload::PersistenceStateResponse(inner.clone())
979        }
980        ResponsePayload::PersistenceFlushed(inner) => {
981            generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner.clone())
982        }
983        ResponsePayload::Rejected(inner) => {
984            generated_protocol::ResponsePayload::RejectedResponse(inner.clone())
985        }
986        ResponsePayload::ExtResult(inner) => {
987            generated_protocol::ResponsePayload::ExtEnvelope(to_generated_ext_envelope(inner))
988        }
989        ResponsePayload::GuestKernelResult(inner) => {
990            generated_protocol::ResponsePayload::GuestKernelResultResponse(inner.clone())
991        }
992        ResponsePayload::PtyResized(inner) => {
993            generated_protocol::ResponsePayload::PtyResizedResponse(inner.clone())
994        }
995        ResponsePayload::PackageLinked(inner) => {
996            generated_protocol::ResponsePayload::PackageLinkedResponse(inner.clone())
997        }
998        ResponsePayload::PackageUnlinked(inner) => {
999            generated_protocol::ResponsePayload::PackageUnlinkedResponse(inner.clone())
1000        }
1001        ResponsePayload::PackageAcquired(inner) => {
1002            generated_protocol::ResponsePayload::PackageAcquiredResponse(inner.clone())
1003        }
1004        ResponsePayload::PackageInstalled(inner) => {
1005            generated_protocol::ResponsePayload::PackageInstalledResponse(inner.clone())
1006        }
1007        ResponsePayload::PackageCacheStats(inner) => {
1008            generated_protocol::ResponsePayload::PackageCacheStatsResponse(inner.clone())
1009        }
1010        ResponsePayload::ProvidedCommands(inner) => {
1011            generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner.clone())
1012        }
1013        ResponsePayload::ExecutionAccepted(inner) => {
1014            generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner.clone())
1015        }
1016        ResponsePayload::ExecutionCompleted(inner) => {
1017            generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner.clone())
1018        }
1019        ResponsePayload::ExecutionEvaluation(inner) => {
1020            generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner.clone())
1021        }
1022        ResponsePayload::TypeScriptCheck(inner) => {
1023            generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner.clone())
1024        }
1025        ResponsePayload::ExecutionDescriptor(inner) => {
1026            generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner.clone())
1027        }
1028        ResponsePayload::ExecutionList(inner) => {
1029            generated_protocol::ResponsePayload::ExecutionListResponse(inner.clone())
1030        }
1031        ResponsePayload::ExecutionDeleted(inner) => {
1032            generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner.clone())
1033        }
1034        ResponsePayload::ExecutionIo(inner) => {
1035            generated_protocol::ResponsePayload::ExecutionIoResponse(inner.clone())
1036        }
1037        ResponsePayload::ExecutionOutputPage(inner) => {
1038            generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner.clone())
1039        }
1040        ResponsePayload::ProcessOutputPage(inner) => {
1041            generated_protocol::ResponsePayload::ProcessOutputPageResponse(inner.clone())
1042        }
1043    })
1044}
1045
1046fn from_generated_response_payload(
1047    payload: generated_protocol::ResponsePayload,
1048) -> Result<ResponsePayload, ProtocolCodecError> {
1049    Ok(match payload {
1050        generated_protocol::ResponsePayload::AuthenticatedResponse(inner) => {
1051            ResponsePayload::Authenticated(inner)
1052        }
1053        generated_protocol::ResponsePayload::SessionOpenedResponse(inner) => {
1054            ResponsePayload::SessionOpened(inner)
1055        }
1056        generated_protocol::ResponsePayload::VmCreatedResponse(inner) => {
1057            ResponsePayload::VmCreated(inner)
1058        }
1059        generated_protocol::ResponsePayload::VmConfigComparedResponse(inner) => {
1060            ResponsePayload::VmConfigCompared(inner)
1061        }
1062        generated_protocol::ResponsePayload::VmDisposedResponse(inner) => {
1063            ResponsePayload::VmDisposed(inner)
1064        }
1065        generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner) => {
1066            ResponsePayload::RootFilesystemBootstrapped(inner)
1067        }
1068        generated_protocol::ResponsePayload::VmConfiguredResponse(inner) => {
1069            ResponsePayload::VmConfigured(inner)
1070        }
1071        generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner) => {
1072            ResponsePayload::HostCallbacksRegistered(inner)
1073        }
1074        generated_protocol::ResponsePayload::LayerCreatedResponse(inner) => {
1075            ResponsePayload::LayerCreated(inner)
1076        }
1077        generated_protocol::ResponsePayload::LayerSealedResponse(inner) => {
1078            ResponsePayload::LayerSealed(inner)
1079        }
1080        generated_protocol::ResponsePayload::SnapshotImportedResponse(inner) => {
1081            ResponsePayload::SnapshotImported(inner)
1082        }
1083        generated_protocol::ResponsePayload::SnapshotExportedResponse(inner) => {
1084            ResponsePayload::SnapshotExported(SnapshotExportedResponse {
1085                layer_id: inner.layer_id,
1086                entries: inner.entries,
1087            })
1088        }
1089        generated_protocol::ResponsePayload::OverlayCreatedResponse(inner) => {
1090            ResponsePayload::OverlayCreated(inner)
1091        }
1092        generated_protocol::ResponsePayload::GuestFilesystemResultResponse(inner) => {
1093            ResponsePayload::GuestFilesystemResult(GuestFilesystemResultResponse {
1094                operation: from_generated_guest_filesystem_operation(inner.operation),
1095                path: inner.path,
1096                content: inner.content,
1097                encoding: inner
1098                    .encoding
1099                    .map(from_generated_root_filesystem_entry_encoding),
1100                entries: inner.entries,
1101                stat: inner.stat.map(from_generated_guest_filesystem_stat),
1102                exists: inner.exists,
1103                target: inner.target,
1104            })
1105        }
1106        generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(inner) => {
1107            ResponsePayload::RootFilesystemSnapshot(RootFilesystemSnapshotResponse {
1108                entries: inner.entries,
1109            })
1110        }
1111        generated_protocol::ResponsePayload::ListMountsResponse(inner) => {
1112            ResponsePayload::MountsListed(inner)
1113        }
1114        generated_protocol::ResponsePayload::ProcessStartedResponse(inner) => {
1115            ResponsePayload::ProcessStarted(inner)
1116        }
1117        generated_protocol::ResponsePayload::StdinWrittenResponse(inner) => {
1118            ResponsePayload::StdinWritten(inner)
1119        }
1120        generated_protocol::ResponsePayload::StdinClosedResponse(inner) => {
1121            ResponsePayload::StdinClosed(inner)
1122        }
1123        generated_protocol::ResponsePayload::ProcessKilledResponse(inner) => {
1124            ResponsePayload::ProcessKilled(inner)
1125        }
1126        generated_protocol::ResponsePayload::ProcessSnapshotResponse(inner) => {
1127            ResponsePayload::ProcessSnapshot(ProcessSnapshotResponse {
1128                processes: inner
1129                    .processes
1130                    .into_iter()
1131                    .map(from_generated_process_snapshot_entry)
1132                    .collect(),
1133            })
1134        }
1135        generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner) => {
1136            ResponsePayload::ResourceSnapshot(inner)
1137        }
1138        generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner) => {
1139            ResponsePayload::ListenerSnapshot(inner)
1140        }
1141        generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner) => {
1142            ResponsePayload::BoundUdpSnapshot(inner)
1143        }
1144        generated_protocol::ResponsePayload::VmFetchResponse(inner) => {
1145            ResponsePayload::VmFetchResult(inner)
1146        }
1147        generated_protocol::ResponsePayload::SignalStateResponse(inner) => {
1148            ResponsePayload::SignalState(inner)
1149        }
1150        generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner) => {
1151            ResponsePayload::ZombieTimerCount(inner)
1152        }
1153        generated_protocol::ResponsePayload::FilesystemResultResponse(inner) => {
1154            ResponsePayload::FilesystemResult(FilesystemResultResponse {
1155                operation: from_generated_filesystem_operation(inner.operation),
1156                status: inner.status,
1157                payload_size_bytes: inner.payload_size_bytes,
1158            })
1159        }
1160        generated_protocol::ResponsePayload::PermissionDecisionResponse(inner) => {
1161            ResponsePayload::PermissionDecision(PermissionDecisionResponse {
1162                capability: inner.capability,
1163                decision: from_generated_permission_mode(inner.decision),
1164            })
1165        }
1166        generated_protocol::ResponsePayload::PersistenceStateResponse(inner) => {
1167            ResponsePayload::PersistenceState(inner)
1168        }
1169        generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner) => {
1170            ResponsePayload::PersistenceFlushed(inner)
1171        }
1172        generated_protocol::ResponsePayload::RejectedResponse(inner) => {
1173            ResponsePayload::Rejected(inner)
1174        }
1175        generated_protocol::ResponsePayload::ExtEnvelope(inner) => {
1176            ResponsePayload::ExtResult(from_generated_ext_envelope(inner))
1177        }
1178        generated_protocol::ResponsePayload::GuestKernelResultResponse(inner) => {
1179            ResponsePayload::GuestKernelResult(inner)
1180        }
1181        generated_protocol::ResponsePayload::PtyResizedResponse(inner) => {
1182            ResponsePayload::PtyResized(inner)
1183        }
1184        generated_protocol::ResponsePayload::PackageLinkedResponse(inner) => {
1185            ResponsePayload::PackageLinked(inner)
1186        }
1187        generated_protocol::ResponsePayload::PackageUnlinkedResponse(inner) => {
1188            ResponsePayload::PackageUnlinked(inner)
1189        }
1190        generated_protocol::ResponsePayload::PackageAcquiredResponse(inner) => {
1191            ResponsePayload::PackageAcquired(inner)
1192        }
1193        generated_protocol::ResponsePayload::PackageInstalledResponse(inner) => {
1194            ResponsePayload::PackageInstalled(inner)
1195        }
1196        generated_protocol::ResponsePayload::PackageCacheStatsResponse(inner) => {
1197            ResponsePayload::PackageCacheStats(inner)
1198        }
1199        generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner) => {
1200            ResponsePayload::ProvidedCommands(inner)
1201        }
1202        generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner) => {
1203            ResponsePayload::ExecutionAccepted(inner)
1204        }
1205        generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner) => {
1206            ResponsePayload::ExecutionCompleted(inner)
1207        }
1208        generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner) => {
1209            ResponsePayload::ExecutionEvaluation(inner)
1210        }
1211        generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner) => {
1212            ResponsePayload::TypeScriptCheck(inner)
1213        }
1214        generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner) => {
1215            ResponsePayload::ExecutionDescriptor(inner)
1216        }
1217        generated_protocol::ResponsePayload::ExecutionListResponse(inner) => {
1218            ResponsePayload::ExecutionList(inner)
1219        }
1220        generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner) => {
1221            ResponsePayload::ExecutionDeleted(inner)
1222        }
1223        generated_protocol::ResponsePayload::ExecutionIoResponse(inner) => {
1224            ResponsePayload::ExecutionIo(inner)
1225        }
1226        generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner) => {
1227            ResponsePayload::ExecutionOutputPage(inner)
1228        }
1229        generated_protocol::ResponsePayload::ProcessOutputPageResponse(inner) => {
1230            ResponsePayload::ProcessOutputPage(inner)
1231        }
1232    })
1233}
1234
1235fn to_generated_event_payload(payload: &EventPayload) -> generated_protocol::EventPayload {
1236    match payload {
1237        EventPayload::VmLifecycle(inner) => generated_protocol::EventPayload::VmLifecycleEvent(
1238            generated_protocol::VmLifecycleEvent {
1239                state: to_generated_vm_lifecycle_state(&inner.state),
1240            },
1241        ),
1242        EventPayload::ProcessOutput(inner) => generated_protocol::EventPayload::ProcessOutputEvent(
1243            generated_protocol::ProcessOutputEvent {
1244                process_id: inner.process_id.clone(),
1245                channel: to_generated_stream_channel(&inner.channel),
1246                chunk: inner.chunk.clone(),
1247                sequence: inner.sequence,
1248                timestamp_ms: inner.timestamp_ms,
1249            },
1250        ),
1251        EventPayload::ProcessExited(inner) => {
1252            generated_protocol::EventPayload::ProcessExitedEvent(inner.clone())
1253        }
1254        EventPayload::Structured(inner) => {
1255            generated_protocol::EventPayload::StructuredEvent(inner.clone())
1256        }
1257        EventPayload::Ext(inner) => {
1258            generated_protocol::EventPayload::ExtEnvelope(to_generated_ext_envelope(inner))
1259        }
1260        EventPayload::ExecutionOutput(inner) => {
1261            generated_protocol::EventPayload::ExecutionOutputEvent(inner.clone())
1262        }
1263        EventPayload::ExecutionCompleted(inner) => {
1264            generated_protocol::EventPayload::ExecutionCompletedEvent(inner.clone())
1265        }
1266    }
1267}
1268
1269fn from_generated_event_payload(payload: generated_protocol::EventPayload) -> EventPayload {
1270    match payload {
1271        generated_protocol::EventPayload::VmLifecycleEvent(inner) => {
1272            EventPayload::VmLifecycle(VmLifecycleEvent {
1273                state: from_generated_vm_lifecycle_state(inner.state),
1274            })
1275        }
1276        generated_protocol::EventPayload::ProcessOutputEvent(inner) => {
1277            EventPayload::ProcessOutput(ProcessOutputEvent {
1278                process_id: inner.process_id,
1279                channel: from_generated_stream_channel(inner.channel),
1280                chunk: inner.chunk,
1281                sequence: inner.sequence,
1282                timestamp_ms: inner.timestamp_ms,
1283            })
1284        }
1285        generated_protocol::EventPayload::ProcessExitedEvent(inner) => {
1286            EventPayload::ProcessExited(inner)
1287        }
1288        generated_protocol::EventPayload::StructuredEvent(inner) => EventPayload::Structured(inner),
1289        generated_protocol::EventPayload::ExtEnvelope(inner) => {
1290            EventPayload::Ext(from_generated_ext_envelope(inner))
1291        }
1292        generated_protocol::EventPayload::ExecutionOutputEvent(inner) => {
1293            EventPayload::ExecutionOutput(inner)
1294        }
1295        generated_protocol::EventPayload::ExecutionCompletedEvent(inner) => {
1296            EventPayload::ExecutionCompleted(inner)
1297        }
1298    }
1299}
1300
1301fn to_generated_sidecar_request_payload(
1302    payload: &SidecarRequestPayload,
1303) -> Result<generated_protocol::SidecarRequestPayload, ProtocolCodecError> {
1304    Ok(match payload {
1305        SidecarRequestPayload::HostCallback(inner) => {
1306            generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner.clone())
1307        }
1308        SidecarRequestPayload::JsBridgeCall(inner) => {
1309            generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner.clone())
1310        }
1311        SidecarRequestPayload::Ext(inner) => {
1312            generated_protocol::SidecarRequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
1313        }
1314    })
1315}
1316
1317fn from_generated_sidecar_request_payload(
1318    payload: generated_protocol::SidecarRequestPayload,
1319) -> Result<SidecarRequestPayload, ProtocolCodecError> {
1320    Ok(match payload {
1321        generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner) => {
1322            SidecarRequestPayload::HostCallback(inner)
1323        }
1324        generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner) => {
1325            SidecarRequestPayload::JsBridgeCall(inner)
1326        }
1327        generated_protocol::SidecarRequestPayload::ExtEnvelope(inner) => {
1328            SidecarRequestPayload::Ext(from_generated_ext_envelope(inner))
1329        }
1330    })
1331}
1332
1333fn to_generated_sidecar_response_payload(
1334    payload: &SidecarResponsePayload,
1335) -> Result<generated_protocol::SidecarResponsePayload, ProtocolCodecError> {
1336    Ok(match payload {
1337        SidecarResponsePayload::HostCallbackResult(inner) => {
1338            generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner.clone())
1339        }
1340        SidecarResponsePayload::JsBridgeResult(inner) => {
1341            generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner.clone())
1342        }
1343        SidecarResponsePayload::ExtResult(inner) => {
1344            generated_protocol::SidecarResponsePayload::ExtEnvelope(to_generated_ext_envelope(
1345                inner,
1346            ))
1347        }
1348    })
1349}
1350
1351fn from_generated_sidecar_response_payload(
1352    payload: generated_protocol::SidecarResponsePayload,
1353) -> Result<SidecarResponsePayload, ProtocolCodecError> {
1354    Ok(match payload {
1355        generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner) => {
1356            SidecarResponsePayload::HostCallbackResult(inner)
1357        }
1358        generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner) => {
1359            SidecarResponsePayload::JsBridgeResult(inner)
1360        }
1361        generated_protocol::SidecarResponsePayload::ExtEnvelope(inner) => {
1362            SidecarResponsePayload::ExtResult(from_generated_ext_envelope(inner))
1363        }
1364    })
1365}
1366
1367macro_rules! impl_bare_newtype_union_enum {
1368    (
1369        $name:ident,
1370        $json_name:ident,
1371        $(#[$json_attr:meta])*
1372        {
1373            $($variant:ident($ty:ty) = $tag:literal),+ $(,)?
1374        }
1375    ) => {
1376        #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1377        $(#[$json_attr])*
1378        enum $json_name {
1379            $($variant($ty)),+
1380        }
1381
1382        impl From<&$name> for $json_name {
1383            fn from(value: &$name) -> Self {
1384                match value {
1385                    $($name::$variant(inner) => Self::$variant(inner.clone()),)+
1386                }
1387            }
1388        }
1389
1390        impl From<$json_name> for $name {
1391            fn from(value: $json_name) -> Self {
1392                match value {
1393                    $($json_name::$variant(inner) => Self::$variant(inner),)+
1394                }
1395            }
1396        }
1397
1398        impl Serialize for $name {
1399            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1400            where
1401                S: Serializer,
1402            {
1403                if serializer.is_human_readable() {
1404                    $json_name::from(self).serialize(serializer)
1405                } else {
1406                    match self {
1407                        $(Self::$variant(inner) => serialize_bare_newtype_tag(serializer, $tag, inner),)+
1408                    }
1409                }
1410            }
1411        }
1412
1413        impl<'de> Deserialize<'de> for $name {
1414            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1415            where
1416                D: Deserializer<'de>,
1417            {
1418                if deserializer.is_human_readable() {
1419                    Ok($json_name::deserialize(deserializer)?.into())
1420                } else {
1421                    struct UnionVisitor;
1422
1423                    impl<'de> Visitor<'de> for UnionVisitor {
1424                        type Value = $name;
1425
1426                        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1427                            write!(formatter, "a {} BARE union", stringify!($name))
1428                        }
1429
1430                        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1431                        where
1432                            A: SeqAccess<'de>,
1433                        {
1434                            let serde_bare::Uint(tag) = seq
1435                                .next_element()?
1436                                .ok_or_else(|| de::Error::custom(concat!("missing ", stringify!($name), " tag")))?;
1437                            match tag {
1438                                $(
1439                                    $tag => {
1440                                        let payload = seq.next_element::<$ty>()?.ok_or_else(|| {
1441                                            de::Error::custom(format!(
1442                                                "missing {} payload for tag {}",
1443                                                stringify!($variant),
1444                                                $tag
1445                                            ))
1446                                        })?;
1447                                        Ok($name::$variant(payload))
1448                                    }
1449                                )+
1450                                _ => Err(de::Error::custom(format!(
1451                                    "unknown {} tag: {}",
1452                                    stringify!($name),
1453                                    tag
1454                                ))),
1455                            }
1456                        }
1457                    }
1458
1459                    deserializer.deserialize_tuple(2, UnionVisitor)
1460                }
1461            }
1462        }
1463    };
1464}
1465
1466pub type ProtocolSchema = crate::wire::ProtocolSchema;
1467
1468pub type OwnershipScope = crate::wire::OwnershipScope;
1469
1470#[derive(Debug, Clone, PartialEq, Eq)]
1471pub enum ProtocolFrame {
1472    Request(RequestFrame),
1473    Response(ResponseFrame),
1474    Event(EventFrame),
1475    SidecarRequest(SidecarRequestFrame),
1476    SidecarResponse(SidecarResponseFrame),
1477    Control(ControlFrame),
1478}
1479
1480pub type ControlFrame = crate::wire::ControlFrame;
1481pub type ControlPayload = crate::wire::ControlPayload;
1482pub type ShutdownControl = crate::wire::ShutdownControl;
1483
1484#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1485pub struct RequestFrame {
1486    pub schema: ProtocolSchema,
1487    pub request_id: RequestId,
1488    pub ownership: OwnershipScope,
1489    pub payload: RequestPayload,
1490}
1491
1492impl RequestFrame {
1493    pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: RequestPayload) -> Self {
1494        Self {
1495            schema: ProtocolSchema::current(),
1496            request_id,
1497            ownership,
1498            payload,
1499        }
1500    }
1501}
1502
1503#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1504pub struct ResponseFrame {
1505    pub schema: ProtocolSchema,
1506    pub request_id: RequestId,
1507    pub ownership: OwnershipScope,
1508    pub payload: ResponsePayload,
1509}
1510
1511impl ResponseFrame {
1512    pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: ResponsePayload) -> Self {
1513        Self {
1514            schema: ProtocolSchema::current(),
1515            request_id,
1516            ownership,
1517            payload,
1518        }
1519    }
1520}
1521
1522#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1523pub struct SidecarRequestFrame {
1524    pub schema: ProtocolSchema,
1525    pub request_id: RequestId,
1526    pub ownership: OwnershipScope,
1527    pub payload: SidecarRequestPayload,
1528}
1529
1530impl SidecarRequestFrame {
1531    pub fn new(
1532        request_id: RequestId,
1533        ownership: OwnershipScope,
1534        payload: SidecarRequestPayload,
1535    ) -> Self {
1536        Self {
1537            schema: ProtocolSchema::current(),
1538            request_id,
1539            ownership,
1540            payload,
1541        }
1542    }
1543}
1544
1545#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1546pub struct SidecarResponseFrame {
1547    pub schema: ProtocolSchema,
1548    pub request_id: RequestId,
1549    pub ownership: OwnershipScope,
1550    pub payload: SidecarResponsePayload,
1551}
1552
1553impl SidecarResponseFrame {
1554    pub fn new(
1555        request_id: RequestId,
1556        ownership: OwnershipScope,
1557        payload: SidecarResponsePayload,
1558    ) -> Self {
1559        Self {
1560            schema: ProtocolSchema::current(),
1561            request_id,
1562            ownership,
1563            payload,
1564        }
1565    }
1566}
1567
1568#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1569pub struct EventFrame {
1570    pub schema: ProtocolSchema,
1571    pub ownership: OwnershipScope,
1572    pub payload: EventPayload,
1573}
1574
1575impl EventFrame {
1576    pub fn new(ownership: OwnershipScope, payload: EventPayload) -> Self {
1577        Self {
1578            schema: ProtocolSchema::current(),
1579            ownership,
1580            payload,
1581        }
1582    }
1583}
1584
1585#[derive(Debug, Clone, PartialEq, Eq)]
1586pub enum RequestPayload {
1587    Authenticate(AuthenticateRequest),
1588    OpenSession(OpenSessionRequest),
1589    CreateVm(CreateVmRequest),
1590    CompareVmConfig(CompareVmConfigRequest),
1591    DisposeVm(DisposeVmRequest),
1592    BootstrapRootFilesystem(BootstrapRootFilesystemRequest),
1593    ConfigureVm(ConfigureVmRequest),
1594    RegisterHostCallbacks(RegisterHostCallbacksRequest),
1595    CreateLayer(CreateLayerRequest),
1596    SealLayer(SealLayerRequest),
1597    ImportSnapshot(ImportSnapshotRequest),
1598    ExportSnapshot(ExportSnapshotRequest),
1599    CreateOverlay(CreateOverlayRequest),
1600    GuestFilesystemCall(GuestFilesystemCallRequest),
1601    SnapshotRootFilesystem(SnapshotRootFilesystemRequest),
1602    ListMounts(ListMountsRequest),
1603    Execute(ExecuteRequest),
1604    WriteStdin(WriteStdinRequest),
1605    CloseStdin(CloseStdinRequest),
1606    KillProcess(KillProcessRequest),
1607    GetProcessSnapshot(GetProcessSnapshotRequest),
1608    FindListener(FindListenerRequest),
1609    FindBoundUdp(FindBoundUdpRequest),
1610    VmFetch(VmFetchRequest),
1611    GetSignalState(GetSignalStateRequest),
1612    GetZombieTimerCount(GetZombieTimerCountRequest),
1613    HostFilesystemCall(HostFilesystemCallRequest),
1614    PersistenceLoad(PersistenceLoadRequest),
1615    PersistenceFlush(PersistenceFlushRequest),
1616    Ext(ExtEnvelope),
1617    GuestKernelCall(GuestKernelCallRequest),
1618    ResizePty(ResizePtyRequest),
1619    GetResourceSnapshot(GetResourceSnapshotRequest),
1620    LinkPackage(LinkPackageRequest),
1621    UnlinkPackage(UnlinkPackageRequest),
1622    AcquirePackage(AcquirePackageRequest),
1623    InstallPackage(InstallPackageRequest),
1624    GetPackageCacheStats(GetPackageCacheStatsRequest),
1625    ProvidedCommands(ProvidedCommandsRequest),
1626    ShellExecution(ShellExecutionRequest),
1627    ArgvExecution(ArgvExecutionRequest),
1628    JavaScriptExecution(JavaScriptExecutionRequest),
1629    JavaScriptEvaluation(JavaScriptEvaluationRequest),
1630    JavaScriptFileExecution(JavaScriptFileExecutionRequest),
1631    TypeScriptExecution(TypeScriptExecutionRequest),
1632    TypeScriptEvaluation(TypeScriptEvaluationRequest),
1633    TypeScriptFileExecution(TypeScriptFileExecutionRequest),
1634    TypeScriptCheck(TypeScriptCheckRequest),
1635    TypeScriptProjectCheck(TypeScriptProjectCheckRequest),
1636    NpmProjectInstall(NpmProjectInstallRequest),
1637    NpmPackageInstall(NpmPackageInstallRequest),
1638    NpmScriptExecution(NpmScriptExecutionRequest),
1639    NpmPackageExecution(NpmPackageExecutionRequest),
1640    PythonExecution(PythonExecutionRequest),
1641    PythonEvaluation(PythonEvaluationRequest),
1642    PythonFileExecution(PythonFileExecutionRequest),
1643    PythonModuleExecution(PythonModuleExecutionRequest),
1644    PythonInstall(PythonInstallRequest),
1645    CreateContext(CreateContextRequest),
1646    GetExecution(GetExecutionRequest),
1647    ListExecutions(ListExecutionsRequest),
1648    WaitExecution(WaitExecutionRequest),
1649    CancelExecution(CancelExecutionRequest),
1650    SignalExecution(SignalExecutionRequest),
1651    ResetExecution(ResetExecutionRequest),
1652    DeleteExecution(DeleteExecutionRequest),
1653    WriteExecutionStdin(WriteExecutionStdinRequest),
1654    CloseExecutionStdin(CloseExecutionStdinRequest),
1655    ResizeExecutionPty(ResizeExecutionPtyRequest),
1656    ReadExecutionOutput(ReadExecutionOutputRequest),
1657    ReadProcessOutput(ReadProcessOutputRequest),
1658}
1659
1660#[derive(Debug, Clone, PartialEq, Eq)]
1661pub enum ResponsePayload {
1662    Authenticated(AuthenticatedResponse),
1663    SessionOpened(SessionOpenedResponse),
1664    VmCreated(VmCreatedResponse),
1665    VmConfigCompared(VmConfigComparedResponse),
1666    VmDisposed(VmDisposedResponse),
1667    RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse),
1668    VmConfigured(VmConfiguredResponse),
1669    HostCallbacksRegistered(HostCallbacksRegisteredResponse),
1670    LayerCreated(LayerCreatedResponse),
1671    LayerSealed(LayerSealedResponse),
1672    SnapshotImported(SnapshotImportedResponse),
1673    SnapshotExported(SnapshotExportedResponse),
1674    OverlayCreated(OverlayCreatedResponse),
1675    GuestFilesystemResult(GuestFilesystemResultResponse),
1676    RootFilesystemSnapshot(RootFilesystemSnapshotResponse),
1677    MountsListed(ListMountsResponse),
1678    ProcessStarted(ProcessStartedResponse),
1679    StdinWritten(StdinWrittenResponse),
1680    StdinClosed(StdinClosedResponse),
1681    ProcessKilled(ProcessKilledResponse),
1682    ProcessSnapshot(ProcessSnapshotResponse),
1683    ListenerSnapshot(ListenerSnapshotResponse),
1684    BoundUdpSnapshot(BoundUdpSnapshotResponse),
1685    VmFetchResult(VmFetchResponse),
1686    SignalState(SignalStateResponse),
1687    ZombieTimerCount(ZombieTimerCountResponse),
1688    FilesystemResult(FilesystemResultResponse),
1689    PermissionDecision(PermissionDecisionResponse),
1690    PersistenceState(PersistenceStateResponse),
1691    PersistenceFlushed(PersistenceFlushedResponse),
1692    Rejected(RejectedResponse),
1693    ExtResult(ExtEnvelope),
1694    GuestKernelResult(GuestKernelResultResponse),
1695    PtyResized(PtyResizedResponse),
1696    ResourceSnapshot(ResourceSnapshotResponse),
1697    PackageLinked(PackageLinkedResponse),
1698    PackageUnlinked(PackageUnlinkedResponse),
1699    PackageAcquired(PackageAcquiredResponse),
1700    PackageInstalled(PackageInstalledResponse),
1701    PackageCacheStats(PackageCacheStatsResponse),
1702    ProvidedCommands(ProvidedCommandsResponse),
1703    ExecutionAccepted(ExecutionAcceptedResponse),
1704    ExecutionCompleted(ExecutionCompletedResponse),
1705    ExecutionEvaluation(ExecutionEvaluationResponse),
1706    TypeScriptCheck(TypeScriptCheckResponse),
1707    ExecutionDescriptor(ExecutionDescriptorResponse),
1708    ExecutionList(ExecutionListResponse),
1709    ExecutionDeleted(ExecutionDeletedResponse),
1710    ExecutionIo(ExecutionIoResponse),
1711    ExecutionOutputPage(ExecutionOutputPageResponse),
1712    ProcessOutputPage(ProcessOutputPageResponse),
1713}
1714
1715#[derive(Debug, Clone, PartialEq, Eq)]
1716pub enum SidecarRequestPayload {
1717    HostCallback(HostCallbackRequest),
1718    JsBridgeCall(JsBridgeCallRequest),
1719    Ext(ExtEnvelope),
1720}
1721
1722#[derive(Debug, Clone, PartialEq, Eq)]
1723pub enum SidecarResponsePayload {
1724    HostCallbackResult(HostCallbackResultResponse),
1725    JsBridgeResult(JsBridgeResultResponse),
1726    ExtResult(ExtEnvelope),
1727}
1728
1729#[derive(Debug, Clone, PartialEq, Eq)]
1730pub enum EventPayload {
1731    VmLifecycle(VmLifecycleEvent),
1732    ProcessOutput(ProcessOutputEvent),
1733    ProcessExited(ProcessExitedEvent),
1734    Structured(StructuredEvent),
1735    Ext(ExtEnvelope),
1736    ExecutionOutput(ExecutionOutputEvent),
1737    ExecutionCompleted(ExecutionCompletedEvent),
1738}
1739
1740pub type SidecarPlacement = crate::wire::SidecarPlacement;
1741
1742pub type SidecarPlacementShared = crate::wire::SidecarPlacementShared;
1743
1744pub type SidecarPlacementExplicit = crate::wire::SidecarPlacementExplicit;
1745
1746pub type GuestRuntimeKind = crate::wire::GuestRuntimeKind;
1747
1748pub type DisposeReason = crate::wire::DisposeReason;
1749
1750pub type FilesystemOperation = crate::wire::FilesystemOperation;
1751
1752pub type GuestFilesystemOperation = crate::wire::GuestFilesystemOperation;
1753
1754pub type PermissionMode = crate::wire::PermissionMode;
1755
1756pub type FsPermissionRule = crate::wire::FsPermissionRule;
1757
1758pub type PatternPermissionRule = crate::wire::PatternPermissionRule;
1759
1760pub type FsPermissionRuleSet = crate::wire::FsPermissionRuleSet;
1761
1762pub type PatternPermissionRuleSet = crate::wire::PatternPermissionRuleSet;
1763
1764pub type FsPermissionScope = crate::wire::FsPermissionScope;
1765
1766pub type PatternPermissionScope = crate::wire::PatternPermissionScope;
1767
1768pub type PermissionsPolicy = crate::wire::PermissionsPolicy;
1769
1770pub type RootFilesystemEntryKind = crate::wire::RootFilesystemEntryKind;
1771
1772pub type RootFilesystemMode = crate::wire::RootFilesystemMode;
1773
1774pub type RootFilesystemLowerDescriptor = crate::wire::RootFilesystemLowerDescriptor;
1775
1776pub type SnapshotRootFilesystemLower = crate::wire::SnapshotRootFilesystemLower;
1777
1778pub type StreamChannel = crate::wire::StreamChannel;
1779
1780pub type VmLifecycleState = crate::wire::VmLifecycleState;
1781
1782pub type AuthenticateRequest = crate::wire::AuthenticateRequest;
1783
1784pub type OpenSessionRequest = crate::wire::OpenSessionRequest;
1785
1786pub type CreateVmRequest = crate::wire::CreateVmRequest;
1787pub type CompareVmConfigRequest = crate::wire::CompareVmConfigRequest;
1788
1789#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1790pub struct DisposeVmRequest {
1791    pub reason: DisposeReason,
1792}
1793
1794pub type BootstrapRootFilesystemRequest = crate::wire::BootstrapRootFilesystemRequest;
1795
1796pub type RootFilesystemDescriptor = crate::wire::RootFilesystemDescriptor;
1797
1798pub type RootFilesystemEntryEncoding = crate::wire::RootFilesystemEntryEncoding;
1799
1800pub type RootFilesystemEntry = crate::wire::RootFilesystemEntry;
1801
1802pub type ConfigureVmRequest = crate::wire::ConfigureVmRequest;
1803
1804#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1805pub struct CreateLayerRequest {}
1806
1807pub type SealLayerRequest = crate::wire::SealLayerRequest;
1808
1809pub type ImportSnapshotRequest = crate::wire::ImportSnapshotRequest;
1810
1811pub type ExportSnapshotRequest = crate::wire::ExportSnapshotRequest;
1812
1813pub type CreateOverlayRequest = crate::wire::CreateOverlayRequest;
1814
1815pub type GuestFilesystemCallRequest = crate::wire::GuestFilesystemCallRequest;
1816
1817pub type GuestKernelCallRequest = crate::wire::GuestKernelCallRequest;
1818pub type ResizePtyRequest = crate::wire::ResizePtyRequest;
1819pub type PackageDescriptor = crate::wire::PackageDescriptor;
1820pub type PackageCommands = crate::wire::PackageCommands;
1821pub type ProjectedCommand = crate::wire::ProjectedCommand;
1822pub type LinkPackageRequest = crate::wire::LinkPackageRequest;
1823pub type UnlinkPackageRequest = crate::wire::UnlinkPackageRequest;
1824pub type PackageAcquisitionSource = crate::wire::PackageAcquisitionSource;
1825pub type PackageUrlSource = crate::wire::PackageUrlSource;
1826pub type PackagePathSource = crate::wire::PackagePathSource;
1827pub type AcquirePackageRequest = crate::wire::AcquirePackageRequest;
1828pub type PackageAcquiredResponse = crate::wire::PackageAcquiredResponse;
1829pub type InstallPackageRequest = crate::wire::InstallPackageRequest;
1830pub type PackageInstalledResponse = crate::wire::PackageInstalledResponse;
1831pub type GetPackageCacheStatsRequest = crate::wire::GetPackageCacheStatsRequest;
1832pub type PackageCacheStatsResponse = crate::wire::PackageCacheStatsResponse;
1833
1834#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1835pub struct ProvidedCommandsRequest {}
1836
1837pub type GuestKernelResultResponse = crate::wire::GuestKernelResultResponse;
1838pub type PtyResizedResponse = crate::wire::PtyResizedResponse;
1839pub type PackageLinkedResponse = crate::wire::PackageLinkedResponse;
1840pub type PackageUnlinkedResponse = crate::wire::PackageUnlinkedResponse;
1841pub type ProvidedCommandsResponse = crate::wire::ProvidedCommandsResponse;
1842
1843pub type SnapshotRootFilesystemRequest = crate::wire::SnapshotRootFilesystemRequest;
1844
1845#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1846pub struct ListMountsRequest {}
1847
1848pub type MountDescriptor = crate::wire::MountDescriptor;
1849
1850pub type MountInfo = crate::wire::MountInfo;
1851
1852pub type MountPluginDescriptor = crate::wire::MountPluginDescriptor;
1853
1854pub type SoftwareDescriptor = crate::wire::SoftwareDescriptor;
1855
1856pub type ProjectedModuleDescriptor = crate::wire::ProjectedModuleDescriptor;
1857
1858pub type WasmPermissionTier = crate::wire::WasmPermissionTier;
1859
1860pub type ExecuteRequest = crate::wire::ExecuteRequest;
1861pub type ReadProcessOutputRequest = crate::wire::ReadProcessOutputRequest;
1862
1863pub type ExecutionState = crate::wire::ExecutionState;
1864pub type ExecutionOutcome = crate::wire::ExecutionOutcome;
1865pub type RetainedExecutionLanguage = crate::wire::RetainedExecutionLanguage;
1866pub type ExecutionStreamChannel = crate::wire::ExecutionStreamChannel;
1867pub type JavaScriptModuleFormat = crate::wire::JavaScriptModuleFormat;
1868pub type ExecutionIdentityOptions = crate::wire::ExecutionIdentityOptions;
1869pub type ExecutionPtyOptions = crate::wire::ExecutionPtyOptions;
1870pub type ExecutionOutputCapture = crate::wire::ExecutionOutputCapture;
1871pub type ExecutionOutputOptions = crate::wire::ExecutionOutputOptions;
1872pub type ProcessExecutionOptions = crate::wire::ProcessExecutionOptions;
1873pub type ShellExecutionRequest = crate::wire::ShellExecutionRequest;
1874pub type ArgvExecutionRequest = crate::wire::ArgvExecutionRequest;
1875pub type JavaScriptExecutionRequest = crate::wire::JavaScriptExecutionRequest;
1876pub type JavaScriptEvaluationRequest = crate::wire::JavaScriptEvaluationRequest;
1877pub type JavaScriptFileExecutionRequest = crate::wire::JavaScriptFileExecutionRequest;
1878pub type TypeScriptExecutionRequest = crate::wire::TypeScriptExecutionRequest;
1879pub type TypeScriptEvaluationRequest = crate::wire::TypeScriptEvaluationRequest;
1880pub type TypeScriptFileExecutionRequest = crate::wire::TypeScriptFileExecutionRequest;
1881pub type TypeScriptCheckRequest = crate::wire::TypeScriptCheckRequest;
1882pub type TypeScriptProjectCheckRequest = crate::wire::TypeScriptProjectCheckRequest;
1883pub type NpmProjectInstallRequest = crate::wire::NpmProjectInstallRequest;
1884pub type NpmPackageInstallRequest = crate::wire::NpmPackageInstallRequest;
1885pub type NpmScriptExecutionRequest = crate::wire::NpmScriptExecutionRequest;
1886pub type NpmPackageExecutionRequest = crate::wire::NpmPackageExecutionRequest;
1887pub type PythonExecutionRequest = crate::wire::PythonExecutionRequest;
1888pub type PythonEvaluationRequest = crate::wire::PythonEvaluationRequest;
1889pub type PythonFileExecutionRequest = crate::wire::PythonFileExecutionRequest;
1890pub type PythonModuleExecutionRequest = crate::wire::PythonModuleExecutionRequest;
1891pub type PythonInstallRequest = crate::wire::PythonInstallRequest;
1892pub type CreateContextRequest = crate::wire::CreateContextRequest;
1893pub type GetExecutionRequest = crate::wire::GetExecutionRequest;
1894#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1895pub struct ListExecutionsRequest {}
1896pub type WaitExecutionRequest = crate::wire::WaitExecutionRequest;
1897pub type CancelExecutionRequest = crate::wire::CancelExecutionRequest;
1898pub type SignalExecutionRequest = crate::wire::SignalExecutionRequest;
1899pub type ResetExecutionRequest = crate::wire::ResetExecutionRequest;
1900pub type DeleteExecutionRequest = crate::wire::DeleteExecutionRequest;
1901pub type WriteExecutionStdinRequest = crate::wire::WriteExecutionStdinRequest;
1902pub type CloseExecutionStdinRequest = crate::wire::CloseExecutionStdinRequest;
1903pub type ResizeExecutionPtyRequest = crate::wire::ResizeExecutionPtyRequest;
1904pub type ReadExecutionOutputRequest = crate::wire::ReadExecutionOutputRequest;
1905
1906pub type WriteStdinRequest = crate::wire::WriteStdinRequest;
1907
1908pub type CloseStdinRequest = crate::wire::CloseStdinRequest;
1909
1910pub type KillProcessRequest = crate::wire::KillProcessRequest;
1911
1912#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1913pub struct GetProcessSnapshotRequest {}
1914
1915#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1916pub struct GetResourceSnapshotRequest {}
1917
1918pub type FindListenerRequest = crate::wire::FindListenerRequest;
1919
1920pub type FindBoundUdpRequest = crate::wire::FindBoundUdpRequest;
1921
1922pub type VmFetchRequest = crate::wire::VmFetchRequest;
1923
1924pub type GetSignalStateRequest = crate::wire::GetSignalStateRequest;
1925
1926#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1927pub struct GetZombieTimerCountRequest {}
1928
1929pub type HostFilesystemCallRequest = crate::wire::HostFilesystemCallRequest;
1930
1931pub type PersistenceLoadRequest = crate::wire::PersistenceLoadRequest;
1932
1933pub type PersistenceFlushRequest = crate::wire::PersistenceFlushRequest;
1934
1935pub type RegisterHostCallbacksRequest = crate::wire::RegisterHostCallbacksRequest;
1936
1937pub type RegisteredHostCallbackDefinition = crate::wire::RegisteredHostCallbackDefinition;
1938
1939pub type RegisteredHostCallbackExample = crate::wire::RegisteredHostCallbackExample;
1940
1941pub type HostCallbackRequest = crate::wire::HostCallbackRequest;
1942
1943pub type JsBridgeCallRequest = crate::wire::JsBridgeCallRequest;
1944
1945pub type AuthenticatedResponse = crate::wire::AuthenticatedResponse;
1946
1947pub type SessionOpenedResponse = crate::wire::SessionOpenedResponse;
1948
1949pub type VmCreatedResponse = crate::wire::VmCreatedResponse;
1950pub type VmConfigComparedResponse = crate::wire::VmConfigComparedResponse;
1951
1952pub type VmDisposedResponse = crate::wire::VmDisposedResponse;
1953
1954pub type RootFilesystemBootstrappedResponse = crate::wire::RootFilesystemBootstrappedResponse;
1955
1956pub type VmConfiguredResponse = crate::wire::VmConfiguredResponse;
1957
1958pub type HostCallbacksRegisteredResponse = crate::wire::HostCallbacksRegisteredResponse;
1959
1960pub type GuestFilesystemStat = crate::wire::GuestFilesystemStat;
1961
1962pub type GuestDirEntry = crate::wire::GuestDirEntry;
1963
1964pub type GuestFilesystemResultResponse = crate::wire::GuestFilesystemResultResponse;
1965
1966pub type RootFilesystemSnapshotResponse = crate::wire::RootFilesystemSnapshotResponse;
1967
1968pub type ListMountsResponse = crate::wire::ListMountsResponse;
1969
1970pub type LayerCreatedResponse = crate::wire::LayerCreatedResponse;
1971
1972pub type LayerSealedResponse = crate::wire::LayerSealedResponse;
1973
1974pub type SnapshotImportedResponse = crate::wire::SnapshotImportedResponse;
1975
1976pub type SnapshotExportedResponse = crate::wire::SnapshotExportedResponse;
1977
1978pub type OverlayCreatedResponse = crate::wire::OverlayCreatedResponse;
1979
1980pub type ProcessStartedResponse = crate::wire::ProcessStartedResponse;
1981
1982pub type StdinWrittenResponse = crate::wire::StdinWrittenResponse;
1983
1984pub type StdinClosedResponse = crate::wire::StdinClosedResponse;
1985
1986pub type ProcessKilledResponse = crate::wire::ProcessKilledResponse;
1987
1988pub type ProcessSnapshotStatus = crate::wire::ProcessSnapshotStatus;
1989
1990pub type ProcessSnapshotEntry = crate::wire::ProcessSnapshotEntry;
1991
1992pub type ProcessSnapshotResponse = crate::wire::ProcessSnapshotResponse;
1993pub type ProcessOutputReplayEvent = crate::wire::ProcessOutputReplayEvent;
1994pub type ProcessOutputPageResponse = crate::wire::ProcessOutputPageResponse;
1995
1996pub type QueueSnapshotEntry = crate::wire::QueueSnapshotEntry;
1997
1998pub type ResourceSnapshotResponse = crate::wire::ResourceSnapshotResponse;
1999
2000pub type SocketStateEntry = crate::wire::SocketStateEntry;
2001
2002pub type ListenerSnapshotResponse = crate::wire::ListenerSnapshotResponse;
2003
2004pub type BoundUdpSnapshotResponse = crate::wire::BoundUdpSnapshotResponse;
2005
2006pub type VmFetchResponse = crate::wire::VmFetchResponse;
2007pub type ExecutionDescriptor = crate::wire::ExecutionDescriptor;
2008pub type ExecutionErrorData = crate::wire::ExecutionErrorData;
2009pub type ExecutionAcceptedResponse = crate::wire::ExecutionAcceptedResponse;
2010pub type ExecutionCompletedResponse = crate::wire::ExecutionCompletedResponse;
2011pub type ExecutionEvaluationResponse = crate::wire::ExecutionEvaluationResponse;
2012pub type TypeScriptDiagnostic = crate::wire::TypeScriptDiagnostic;
2013pub type TypeScriptCheckResponse = crate::wire::TypeScriptCheckResponse;
2014pub type ExecutionDescriptorResponse = crate::wire::ExecutionDescriptorResponse;
2015pub type ExecutionListResponse = crate::wire::ExecutionListResponse;
2016pub type ExecutionDeletedResponse = crate::wire::ExecutionDeletedResponse;
2017pub type ExecutionIoResponse = crate::wire::ExecutionIoResponse;
2018pub type ExecutionOutputEvent = crate::wire::ExecutionOutputEvent;
2019pub type ExecutionOutputPageResponse = crate::wire::ExecutionOutputPageResponse;
2020pub type ExecutionCompletedEvent = crate::wire::ExecutionCompletedEvent;
2021
2022pub type SignalDispositionAction = crate::wire::SignalDispositionAction;
2023
2024pub type SignalHandlerRegistration = crate::wire::SignalHandlerRegistration;
2025
2026pub type SignalStateResponse = crate::wire::SignalStateResponse;
2027
2028pub type ZombieTimerCountResponse = crate::wire::ZombieTimerCountResponse;
2029
2030pub type FilesystemResultResponse = crate::wire::FilesystemResultResponse;
2031
2032pub type PermissionDecisionResponse = crate::wire::PermissionDecisionResponse;
2033
2034pub type PersistenceStateResponse = crate::wire::PersistenceStateResponse;
2035
2036pub type PersistenceFlushedResponse = crate::wire::PersistenceFlushedResponse;
2037
2038pub type HostCallbackResultResponse = crate::wire::HostCallbackResultResponse;
2039
2040pub type JsBridgeResultResponse = crate::wire::JsBridgeResultResponse;
2041
2042pub type RejectedResponse = crate::wire::RejectedResponse;
2043
2044pub type VmLifecycleEvent = crate::wire::VmLifecycleEvent;
2045
2046pub type ProcessOutputEvent = crate::wire::ProcessOutputEvent;
2047
2048pub type ProcessExitedEvent = crate::wire::ProcessExitedEvent;
2049
2050pub type StructuredEvent = crate::wire::StructuredEvent;
2051
2052impl_bare_newtype_union_enum!(
2053    ProtocolFrame,
2054    JsonProtocolFrame,
2055    #[serde(tag = "frame_type", rename_all = "snake_case")]
2056    {
2057        Request(RequestFrame) = 0,
2058        Response(ResponseFrame) = 1,
2059        Event(EventFrame) = 2,
2060        SidecarRequest(SidecarRequestFrame) = 3,
2061        SidecarResponse(SidecarResponseFrame) = 4,
2062        Control(ControlFrame) = 5,
2063    }
2064);
2065
2066impl_bare_newtype_union_enum!(
2067    RequestPayload,
2068    JsonRequestPayload,
2069    #[serde(tag = "type", rename_all = "snake_case")]
2070    {
2071        Authenticate(AuthenticateRequest) = 0,
2072        OpenSession(OpenSessionRequest) = 1,
2073        CreateVm(CreateVmRequest) = 2,
2074        DisposeVm(DisposeVmRequest) = 3,
2075        BootstrapRootFilesystem(BootstrapRootFilesystemRequest) = 4,
2076        ConfigureVm(ConfigureVmRequest) = 5,
2077        RegisterHostCallbacks(RegisterHostCallbacksRequest) = 6,
2078        CreateLayer(CreateLayerRequest) = 7,
2079        SealLayer(SealLayerRequest) = 8,
2080        ImportSnapshot(ImportSnapshotRequest) = 9,
2081        ExportSnapshot(ExportSnapshotRequest) = 10,
2082        CreateOverlay(CreateOverlayRequest) = 11,
2083        GuestFilesystemCall(GuestFilesystemCallRequest) = 12,
2084        SnapshotRootFilesystem(SnapshotRootFilesystemRequest) = 13,
2085        Execute(ExecuteRequest) = 14,
2086        WriteStdin(WriteStdinRequest) = 15,
2087        CloseStdin(CloseStdinRequest) = 16,
2088        KillProcess(KillProcessRequest) = 17,
2089        GetProcessSnapshot(GetProcessSnapshotRequest) = 18,
2090        FindListener(FindListenerRequest) = 19,
2091        FindBoundUdp(FindBoundUdpRequest) = 20,
2092        GetSignalState(GetSignalStateRequest) = 21,
2093        GetZombieTimerCount(GetZombieTimerCountRequest) = 22,
2094        HostFilesystemCall(HostFilesystemCallRequest) = 23,
2095        PersistenceLoad(PersistenceLoadRequest) = 24,
2096        PersistenceFlush(PersistenceFlushRequest) = 25,
2097        VmFetch(VmFetchRequest) = 26,
2098        Ext(ExtEnvelope) = 27,
2099        GuestKernelCall(GuestKernelCallRequest) = 28,
2100        ResizePty(ResizePtyRequest) = 29,
2101        GetResourceSnapshot(GetResourceSnapshotRequest) = 30,
2102        LinkPackage(LinkPackageRequest) = 31,
2103        ProvidedCommands(ProvidedCommandsRequest) = 32,
2104        ListMounts(ListMountsRequest) = 33,
2105        ShellExecution(ShellExecutionRequest) = 34,
2106        ArgvExecution(ArgvExecutionRequest) = 35,
2107        JavaScriptExecution(JavaScriptExecutionRequest) = 36,
2108        JavaScriptEvaluation(JavaScriptEvaluationRequest) = 37,
2109        JavaScriptFileExecution(JavaScriptFileExecutionRequest) = 38,
2110        TypeScriptExecution(TypeScriptExecutionRequest) = 39,
2111        TypeScriptEvaluation(TypeScriptEvaluationRequest) = 40,
2112        TypeScriptFileExecution(TypeScriptFileExecutionRequest) = 41,
2113        TypeScriptCheck(TypeScriptCheckRequest) = 42,
2114        TypeScriptProjectCheck(TypeScriptProjectCheckRequest) = 43,
2115        NpmProjectInstall(NpmProjectInstallRequest) = 44,
2116        NpmPackageInstall(NpmPackageInstallRequest) = 45,
2117        NpmScriptExecution(NpmScriptExecutionRequest) = 46,
2118        NpmPackageExecution(NpmPackageExecutionRequest) = 47,
2119        PythonExecution(PythonExecutionRequest) = 48,
2120        PythonEvaluation(PythonEvaluationRequest) = 49,
2121        PythonFileExecution(PythonFileExecutionRequest) = 50,
2122        PythonModuleExecution(PythonModuleExecutionRequest) = 51,
2123        PythonInstall(PythonInstallRequest) = 52,
2124        CreateContext(CreateContextRequest) = 53,
2125        GetExecution(GetExecutionRequest) = 54,
2126        ListExecutions(ListExecutionsRequest) = 55,
2127        WaitExecution(WaitExecutionRequest) = 56,
2128        CancelExecution(CancelExecutionRequest) = 57,
2129        SignalExecution(SignalExecutionRequest) = 58,
2130        ResetExecution(ResetExecutionRequest) = 59,
2131        DeleteExecution(DeleteExecutionRequest) = 60,
2132        WriteExecutionStdin(WriteExecutionStdinRequest) = 61,
2133        CloseExecutionStdin(CloseExecutionStdinRequest) = 62,
2134        ResizeExecutionPty(ResizeExecutionPtyRequest) = 63,
2135        ReadExecutionOutput(ReadExecutionOutputRequest) = 64,
2136        UnlinkPackage(UnlinkPackageRequest) = 65,
2137        CompareVmConfig(CompareVmConfigRequest) = 66,
2138        AcquirePackage(AcquirePackageRequest) = 67,
2139        InstallPackage(InstallPackageRequest) = 68,
2140        GetPackageCacheStats(GetPackageCacheStatsRequest) = 69,
2141        ReadProcessOutput(ReadProcessOutputRequest) = 70,
2142    }
2143);
2144
2145impl_bare_newtype_union_enum!(
2146    ResponsePayload,
2147    JsonResponsePayload,
2148    #[serde(tag = "type", rename_all = "snake_case")]
2149    {
2150        Authenticated(AuthenticatedResponse) = 0,
2151        SessionOpened(SessionOpenedResponse) = 1,
2152        VmCreated(VmCreatedResponse) = 2,
2153        VmDisposed(VmDisposedResponse) = 3,
2154        RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse) = 4,
2155        VmConfigured(VmConfiguredResponse) = 5,
2156        HostCallbacksRegistered(HostCallbacksRegisteredResponse) = 6,
2157        LayerCreated(LayerCreatedResponse) = 7,
2158        LayerSealed(LayerSealedResponse) = 8,
2159        SnapshotImported(SnapshotImportedResponse) = 9,
2160        SnapshotExported(SnapshotExportedResponse) = 10,
2161        OverlayCreated(OverlayCreatedResponse) = 11,
2162        GuestFilesystemResult(GuestFilesystemResultResponse) = 12,
2163        RootFilesystemSnapshot(RootFilesystemSnapshotResponse) = 13,
2164        ProcessStarted(ProcessStartedResponse) = 14,
2165        StdinWritten(StdinWrittenResponse) = 15,
2166        StdinClosed(StdinClosedResponse) = 16,
2167        ProcessKilled(ProcessKilledResponse) = 17,
2168        ProcessSnapshot(ProcessSnapshotResponse) = 18,
2169        ListenerSnapshot(ListenerSnapshotResponse) = 19,
2170        BoundUdpSnapshot(BoundUdpSnapshotResponse) = 20,
2171        SignalState(SignalStateResponse) = 21,
2172        ZombieTimerCount(ZombieTimerCountResponse) = 22,
2173        FilesystemResult(FilesystemResultResponse) = 23,
2174        PermissionDecision(PermissionDecisionResponse) = 24,
2175        PersistenceState(PersistenceStateResponse) = 25,
2176        PersistenceFlushed(PersistenceFlushedResponse) = 26,
2177        Rejected(RejectedResponse) = 27,
2178        VmFetchResult(VmFetchResponse) = 28,
2179        ExtResult(ExtEnvelope) = 29,
2180        GuestKernelResult(GuestKernelResultResponse) = 30,
2181        PtyResized(PtyResizedResponse) = 31,
2182        ResourceSnapshot(ResourceSnapshotResponse) = 32,
2183        PackageLinked(PackageLinkedResponse) = 33,
2184        ProvidedCommands(ProvidedCommandsResponse) = 34,
2185        MountsListed(ListMountsResponse) = 35,
2186        ExecutionAccepted(ExecutionAcceptedResponse) = 36,
2187        ExecutionCompleted(ExecutionCompletedResponse) = 37,
2188        ExecutionEvaluation(ExecutionEvaluationResponse) = 38,
2189        TypeScriptCheck(TypeScriptCheckResponse) = 39,
2190        ExecutionDescriptor(ExecutionDescriptorResponse) = 40,
2191        ExecutionList(ExecutionListResponse) = 41,
2192        ExecutionDeleted(ExecutionDeletedResponse) = 42,
2193        ExecutionIo(ExecutionIoResponse) = 43,
2194        ExecutionOutputPage(ExecutionOutputPageResponse) = 44,
2195        PackageUnlinked(PackageUnlinkedResponse) = 45,
2196        VmConfigCompared(VmConfigComparedResponse) = 46,
2197        PackageAcquired(PackageAcquiredResponse) = 47,
2198        PackageInstalled(PackageInstalledResponse) = 48,
2199        PackageCacheStats(PackageCacheStatsResponse) = 49,
2200        ProcessOutputPage(ProcessOutputPageResponse) = 50,
2201    }
2202);
2203
2204impl_bare_newtype_union_enum!(
2205    SidecarRequestPayload,
2206    JsonSidecarRequestPayload,
2207    #[serde(tag = "type", rename_all = "snake_case")]
2208    {
2209        HostCallback(HostCallbackRequest) = 0,
2210        JsBridgeCall(JsBridgeCallRequest) = 1,
2211        Ext(ExtEnvelope) = 2,
2212    }
2213);
2214
2215impl_bare_newtype_union_enum!(
2216    SidecarResponsePayload,
2217    JsonSidecarResponsePayload,
2218    #[allow(clippy::enum_variant_names)]
2219    #[serde(tag = "type", rename_all = "snake_case")]
2220    {
2221        HostCallbackResult(HostCallbackResultResponse) = 0,
2222        JsBridgeResult(JsBridgeResultResponse) = 1,
2223        ExtResult(ExtEnvelope) = 2,
2224    }
2225);
2226
2227impl_bare_newtype_union_enum!(
2228    EventPayload,
2229    JsonEventPayload,
2230    #[serde(tag = "type", rename_all = "snake_case")]
2231    {
2232        VmLifecycle(VmLifecycleEvent) = 0,
2233        ProcessOutput(ProcessOutputEvent) = 1,
2234        ProcessExited(ProcessExitedEvent) = 2,
2235        Structured(StructuredEvent) = 3,
2236        Ext(ExtEnvelope) = 4,
2237        ExecutionOutput(ExecutionOutputEvent) = 5,
2238        ExecutionCompleted(ExecutionCompletedEvent) = 6,
2239    }
2240);
2241
2242fn serialize_payload(
2243    frame: &ProtocolFrame,
2244    payload_codec: NativePayloadCodec,
2245) -> Result<Vec<u8>, ProtocolCodecError> {
2246    match payload_codec {
2247        NativePayloadCodec::Json => serde_json::to_vec(frame)
2248            .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
2249        NativePayloadCodec::Bare => serde_bare::to_vec(&to_generated_protocol_frame(frame)?)
2250            .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
2251    }
2252}
2253
2254fn deserialize_payload(
2255    payload: &[u8],
2256    payload_codec: NativePayloadCodec,
2257) -> Result<ProtocolFrame, ProtocolCodecError> {
2258    match payload_codec {
2259        NativePayloadCodec::Json => serde_json::from_slice(payload)
2260            .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string())),
2261        NativePayloadCodec::Bare => {
2262            let frame: generated_protocol::ProtocolFrame = serde_bare::from_slice(payload)
2263                .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string()))?;
2264            from_generated_protocol_frame(frame)
2265        }
2266    }
2267}
2268
2269#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2270pub enum NativePayloadCodec {
2271    Json,
2272    Bare,
2273}
2274
2275impl NativePayloadCodec {
2276    pub fn sniff(payload: &[u8]) -> Self {
2277        match payload.first() {
2278            Some(b'{') => Self::Json,
2279            _ => Self::Bare,
2280        }
2281    }
2282
2283    pub fn alternate(self) -> Self {
2284        match self {
2285            Self::Json => Self::Bare,
2286            Self::Bare => Self::Json,
2287        }
2288    }
2289}
2290
2291#[derive(Debug, Clone)]
2292pub struct NativeFrameCodec {
2293    max_frame_bytes: usize,
2294    payload_codec: NativePayloadCodec,
2295}
2296
2297impl NativeFrameCodec {
2298    pub fn new(max_frame_bytes: usize) -> Self {
2299        Self::with_payload_codec(max_frame_bytes, NativePayloadCodec::Json)
2300    }
2301
2302    pub fn with_payload_codec(max_frame_bytes: usize, payload_codec: NativePayloadCodec) -> Self {
2303        Self {
2304            max_frame_bytes,
2305            payload_codec,
2306        }
2307    }
2308
2309    pub fn max_frame_bytes(&self) -> usize {
2310        self.max_frame_bytes
2311    }
2312
2313    pub fn payload_codec(&self) -> NativePayloadCodec {
2314        self.payload_codec
2315    }
2316
2317    pub fn encode(&self, frame: &ProtocolFrame) -> Result<Vec<u8>, ProtocolCodecError> {
2318        self.encode_with_codec(frame, self.payload_codec)
2319    }
2320
2321    pub fn encode_with_codec(
2322        &self,
2323        frame: &ProtocolFrame,
2324        payload_codec: NativePayloadCodec,
2325    ) -> Result<Vec<u8>, ProtocolCodecError> {
2326        validate_frame(frame)?;
2327
2328        let payload = serialize_payload(frame, payload_codec)?;
2329        if payload.len() > self.max_frame_bytes {
2330            return Err(ProtocolCodecError::FrameTooLarge {
2331                size: payload.len(),
2332                max: self.max_frame_bytes,
2333            });
2334        }
2335
2336        let length =
2337            u32::try_from(payload.len()).map_err(|_| ProtocolCodecError::FrameTooLarge {
2338                size: payload.len(),
2339                max: u32::MAX as usize,
2340            })?;
2341
2342        let mut encoded = Vec::with_capacity(4 + payload.len());
2343        encoded.extend_from_slice(&length.to_be_bytes());
2344        encoded.extend_from_slice(&payload);
2345        Ok(encoded)
2346    }
2347
2348    pub fn decode(&self, bytes: &[u8]) -> Result<ProtocolFrame, ProtocolCodecError> {
2349        self.decode_detected(bytes).map(|(frame, _)| frame)
2350    }
2351
2352    pub fn decode_with_codec(
2353        &self,
2354        bytes: &[u8],
2355        payload_codec: NativePayloadCodec,
2356    ) -> Result<ProtocolFrame, ProtocolCodecError> {
2357        let payload = self.checked_payload(bytes)?;
2358        let frame = deserialize_payload(payload, payload_codec)?;
2359        validate_frame(&frame)?;
2360        Ok(frame)
2361    }
2362
2363    pub fn decode_detected(
2364        &self,
2365        bytes: &[u8],
2366    ) -> Result<(ProtocolFrame, NativePayloadCodec), ProtocolCodecError> {
2367        let payload = self.checked_payload(bytes)?;
2368        let primary = NativePayloadCodec::sniff(payload);
2369
2370        match deserialize_payload(payload, primary) {
2371            Ok(frame) => {
2372                validate_frame(&frame)?;
2373                Ok((frame, primary))
2374            }
2375            Err(primary_error) => {
2376                let alternate = primary.alternate();
2377                let frame = deserialize_payload(payload, alternate).map_err(|_| primary_error)?;
2378                validate_frame(&frame)?;
2379                Ok((frame, alternate))
2380            }
2381        }
2382    }
2383
2384    fn checked_payload<'a>(&self, bytes: &'a [u8]) -> Result<&'a [u8], ProtocolCodecError> {
2385        if bytes.len() < 4 {
2386            return Err(ProtocolCodecError::TruncatedFrame {
2387                actual: bytes.len(),
2388            });
2389        }
2390
2391        let declared =
2392            u32::from_be_bytes(bytes[..4].try_into().expect("length prefix is four bytes"))
2393                as usize;
2394        if declared > self.max_frame_bytes {
2395            return Err(ProtocolCodecError::FrameTooLarge {
2396                size: declared,
2397                max: self.max_frame_bytes,
2398            });
2399        }
2400
2401        let actual = bytes.len() - 4;
2402        if declared != actual {
2403            return Err(ProtocolCodecError::LengthPrefixMismatch { declared, actual });
2404        }
2405        Ok(&bytes[4..])
2406    }
2407}
2408
2409impl Default for NativeFrameCodec {
2410    fn default() -> Self {
2411        Self::new(DEFAULT_MAX_FRAME_BYTES)
2412    }
2413}
2414
2415#[derive(Debug)]
2416pub struct ResponseTracker {
2417    pending: HashMap<RequestId, PendingRequest>,
2418    completed: HashSet<RequestId>,
2419    completed_order: VecDeque<RequestId>,
2420    completed_cap: usize,
2421}
2422
2423#[derive(Debug)]
2424pub struct SidecarResponseTracker {
2425    pending: HashMap<RequestId, PendingSidecarRequest>,
2426    completed: HashSet<RequestId>,
2427    completed_order: VecDeque<RequestId>,
2428    completed_cap: usize,
2429}
2430
2431impl ResponseTracker {
2432    pub fn with_completed_cap(completed_cap: usize) -> Self {
2433        Self {
2434            pending: HashMap::new(),
2435            completed: HashSet::new(),
2436            completed_order: VecDeque::new(),
2437            completed_cap: completed_cap.max(1),
2438        }
2439    }
2440
2441    pub fn completed_count(&self) -> usize {
2442        self.completed.len()
2443    }
2444
2445    pub fn register_request(&mut self, request: &RequestFrame) -> Result<(), ResponseTrackerError> {
2446        if self.pending.contains_key(&request.request_id)
2447            || self.completed.contains(&request.request_id)
2448        {
2449            return Err(ResponseTrackerError::DuplicateRequestId {
2450                request_id: request.request_id,
2451            });
2452        }
2453
2454        self.pending.insert(
2455            request.request_id,
2456            PendingRequest {
2457                ownership: request.ownership.clone(),
2458                expected_response: request.payload.expected_response(),
2459            },
2460        );
2461        Ok(())
2462    }
2463
2464    pub fn accept_response(
2465        &mut self,
2466        response: &ResponseFrame,
2467    ) -> Result<(), ResponseTrackerError> {
2468        if self.completed.contains(&response.request_id) {
2469            return Err(ResponseTrackerError::DuplicateResponse {
2470                request_id: response.request_id,
2471            });
2472        }
2473
2474        let pending = self.pending.get(&response.request_id).ok_or(
2475            ResponseTrackerError::UnmatchedResponse {
2476                request_id: response.request_id,
2477            },
2478        )?;
2479
2480        if pending.ownership != response.ownership {
2481            return Err(ResponseTrackerError::OwnershipMismatch {
2482                request_id: response.request_id,
2483                expected: Box::new(pending.ownership.clone()),
2484                actual: Box::new(response.ownership.clone()),
2485            });
2486        }
2487
2488        if !pending.expected_response.matches(&response.payload) {
2489            return Err(ResponseTrackerError::ResponseKindMismatch {
2490                request_id: response.request_id,
2491                expected: pending.expected_response.as_str().to_string(),
2492                actual: response.payload.kind_name().to_string(),
2493            });
2494        }
2495
2496        self.pending
2497            .remove(&response.request_id)
2498            .expect("pending response should still exist after validation");
2499        self.completed.insert(response.request_id);
2500        self.completed_order.push_back(response.request_id);
2501        while self.completed.len() > self.completed_cap {
2502            if let Some(evicted) = self.completed_order.pop_front() {
2503                self.completed.remove(&evicted);
2504            }
2505        }
2506        Ok(())
2507    }
2508}
2509
2510impl Default for ResponseTracker {
2511    fn default() -> Self {
2512        Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2513    }
2514}
2515
2516impl SidecarResponseTracker {
2517    pub fn with_completed_cap(completed_cap: usize) -> Self {
2518        Self {
2519            pending: HashMap::new(),
2520            completed: HashSet::new(),
2521            completed_order: VecDeque::new(),
2522            completed_cap: completed_cap.max(1),
2523        }
2524    }
2525
2526    pub fn pending_count(&self) -> usize {
2527        self.pending.len()
2528    }
2529
2530    pub fn completed_count(&self) -> usize {
2531        self.completed.len()
2532    }
2533
2534    pub fn register_request(
2535        &mut self,
2536        request: &SidecarRequestFrame,
2537    ) -> Result<(), SidecarResponseTrackerError> {
2538        if self.pending.contains_key(&request.request_id)
2539            || self.completed.contains(&request.request_id)
2540        {
2541            return Err(SidecarResponseTrackerError::DuplicateRequestId {
2542                request_id: request.request_id,
2543            });
2544        }
2545
2546        self.pending.insert(
2547            request.request_id,
2548            PendingSidecarRequest {
2549                ownership: request.ownership.clone(),
2550                expected_response: request.payload.expected_response(),
2551            },
2552        );
2553        Ok(())
2554    }
2555
2556    pub fn accept_response(
2557        &mut self,
2558        response: &SidecarResponseFrame,
2559    ) -> Result<(), SidecarResponseTrackerError> {
2560        if self.completed.contains(&response.request_id) {
2561            return Err(SidecarResponseTrackerError::DuplicateResponse {
2562                request_id: response.request_id,
2563            });
2564        }
2565
2566        let pending = self.pending.get(&response.request_id).ok_or(
2567            SidecarResponseTrackerError::UnmatchedResponse {
2568                request_id: response.request_id,
2569            },
2570        )?;
2571
2572        if pending.ownership != response.ownership {
2573            return Err(SidecarResponseTrackerError::OwnershipMismatch {
2574                request_id: response.request_id,
2575                expected: Box::new(pending.ownership.clone()),
2576                actual: Box::new(response.ownership.clone()),
2577            });
2578        }
2579
2580        if !pending.expected_response.matches(&response.payload) {
2581            return Err(SidecarResponseTrackerError::ResponseKindMismatch {
2582                request_id: response.request_id,
2583                expected: pending.expected_response.as_str().to_string(),
2584                actual: response.payload.kind_name().to_string(),
2585            });
2586        }
2587
2588        self.pending
2589            .remove(&response.request_id)
2590            .expect("pending sidecar response should still exist after validation");
2591        self.completed.insert(response.request_id);
2592        self.completed_order.push_back(response.request_id);
2593        while self.completed.len() > self.completed_cap {
2594            if let Some(evicted) = self.completed_order.pop_front() {
2595                self.completed.remove(&evicted);
2596            }
2597        }
2598        Ok(())
2599    }
2600}
2601
2602impl Default for SidecarResponseTracker {
2603    fn default() -> Self {
2604        Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2605    }
2606}
2607
2608#[derive(Debug, Clone, PartialEq, Eq)]
2609pub enum ResponseTrackerError {
2610    DuplicateRequestId {
2611        request_id: RequestId,
2612    },
2613    UnmatchedResponse {
2614        request_id: RequestId,
2615    },
2616    DuplicateResponse {
2617        request_id: RequestId,
2618    },
2619    OwnershipMismatch {
2620        request_id: RequestId,
2621        expected: Box<OwnershipScope>,
2622        actual: Box<OwnershipScope>,
2623    },
2624    ResponseKindMismatch {
2625        request_id: RequestId,
2626        expected: String,
2627        actual: String,
2628    },
2629}
2630
2631impl fmt::Display for ResponseTrackerError {
2632    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2633        match self {
2634            Self::DuplicateRequestId { request_id } => {
2635                write!(f, "request id {request_id} is already tracked")
2636            }
2637            Self::UnmatchedResponse { request_id } => {
2638                write!(
2639                    f,
2640                    "response id {request_id} does not match any pending request"
2641                )
2642            }
2643            Self::DuplicateResponse { request_id } => {
2644                write!(f, "response id {request_id} has already been completed")
2645            }
2646            Self::OwnershipMismatch {
2647                request_id,
2648                expected,
2649                actual,
2650            } => write!(
2651                f,
2652                "response id {request_id} used ownership {:?}, expected {:?}",
2653                actual, expected
2654            ),
2655            Self::ResponseKindMismatch {
2656                request_id,
2657                expected,
2658                actual,
2659            } => write!(
2660                f,
2661                "response id {request_id} carried {actual}, expected {expected}",
2662            ),
2663        }
2664    }
2665}
2666
2667impl Error for ResponseTrackerError {}
2668
2669#[derive(Debug, Clone, PartialEq, Eq)]
2670pub enum SidecarResponseTrackerError {
2671    DuplicateRequestId {
2672        request_id: RequestId,
2673    },
2674    UnmatchedResponse {
2675        request_id: RequestId,
2676    },
2677    DuplicateResponse {
2678        request_id: RequestId,
2679    },
2680    OwnershipMismatch {
2681        request_id: RequestId,
2682        expected: Box<OwnershipScope>,
2683        actual: Box<OwnershipScope>,
2684    },
2685    ResponseKindMismatch {
2686        request_id: RequestId,
2687        expected: String,
2688        actual: String,
2689    },
2690}
2691
2692impl fmt::Display for SidecarResponseTrackerError {
2693    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2694        match self {
2695            Self::DuplicateRequestId { request_id } => {
2696                write!(f, "sidecar request id {request_id} is already tracked")
2697            }
2698            Self::UnmatchedResponse { request_id } => {
2699                write!(
2700                    f,
2701                    "sidecar response id {request_id} does not match any pending request"
2702                )
2703            }
2704            Self::DuplicateResponse { request_id } => {
2705                write!(
2706                    f,
2707                    "sidecar response id {request_id} has already been completed"
2708                )
2709            }
2710            Self::OwnershipMismatch {
2711                request_id,
2712                expected,
2713                actual,
2714            } => write!(
2715                f,
2716                "sidecar response id {request_id} used ownership {:?}, expected {:?}",
2717                actual, expected
2718            ),
2719            Self::ResponseKindMismatch {
2720                request_id,
2721                expected,
2722                actual,
2723            } => write!(
2724                f,
2725                "sidecar response id {request_id} carried {actual}, expected {expected}",
2726            ),
2727        }
2728    }
2729}
2730
2731impl Error for SidecarResponseTrackerError {}
2732
2733#[derive(Debug, Clone, PartialEq, Eq)]
2734struct PendingRequest {
2735    ownership: OwnershipScope,
2736    expected_response: ExpectedResponseKind,
2737}
2738
2739#[derive(Debug, Clone, PartialEq, Eq)]
2740struct PendingSidecarRequest {
2741    ownership: OwnershipScope,
2742    expected_response: ExpectedSidecarResponseKind,
2743}
2744
2745#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2746enum ExpectedResponseKind {
2747    Authenticated,
2748    SessionOpened,
2749    VmCreated,
2750    VmConfigCompared,
2751    VmDisposed,
2752    RootFilesystemBootstrapped,
2753    VmConfigured,
2754    HostCallbacksRegistered,
2755    LayerCreated,
2756    LayerSealed,
2757    SnapshotImported,
2758    SnapshotExported,
2759    OverlayCreated,
2760    GuestFilesystemResult,
2761    RootFilesystemSnapshot,
2762    ProcessStarted,
2763    StdinWritten,
2764    StdinClosed,
2765    ProcessKilled,
2766    ProcessSnapshot,
2767    ResourceSnapshot,
2768    ListenerSnapshot,
2769    BoundUdpSnapshot,
2770    VmFetchResult,
2771    SignalState,
2772    ZombieTimerCount,
2773    FilesystemResult,
2774    // `PermissionDecision` is a sidecar-initiated callback response, so no host
2775    // request maps to it in `expected_response_kind`; kept for protocol symmetry.
2776    #[allow(dead_code)]
2777    PermissionDecision,
2778    PersistenceState,
2779    PersistenceFlushed,
2780    ExtResult,
2781    GuestKernelResult,
2782    PtyResized,
2783    PackageLinked,
2784    PackageUnlinked,
2785    PackageAcquired,
2786    PackageInstalled,
2787    PackageCacheStats,
2788    ProvidedCommands,
2789    MountsListed,
2790    ExecutionOperation,
2791    ExecutionCompleted,
2792    ExecutionEvaluation,
2793    TypeScriptCheck,
2794    ExecutionDescriptor,
2795    ExecutionList,
2796    ExecutionDeleted,
2797    ExecutionIo,
2798    ExecutionOutputPage,
2799    ProcessOutputPage,
2800}
2801
2802#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2803enum ExpectedSidecarResponseKind {
2804    HostCallback,
2805    JsBridge,
2806    Ext,
2807}
2808
2809impl ExpectedResponseKind {
2810    fn as_str(self) -> &'static str {
2811        match self {
2812            Self::Authenticated => "authenticated",
2813            Self::SessionOpened => "session_opened",
2814            Self::VmCreated => "vm_created",
2815            Self::VmConfigCompared => "vm_config_compared",
2816            Self::VmDisposed => "vm_disposed",
2817            Self::RootFilesystemBootstrapped => "root_filesystem_bootstrapped",
2818            Self::VmConfigured => "vm_configured",
2819            Self::HostCallbacksRegistered => "host_callbacks_registered",
2820            Self::LayerCreated => "layer_created",
2821            Self::LayerSealed => "layer_sealed",
2822            Self::SnapshotImported => "snapshot_imported",
2823            Self::SnapshotExported => "snapshot_exported",
2824            Self::OverlayCreated => "overlay_created",
2825            Self::GuestFilesystemResult => "guest_filesystem_result",
2826            Self::RootFilesystemSnapshot => "root_filesystem_snapshot",
2827            Self::ProcessStarted => "process_started",
2828            Self::StdinWritten => "stdin_written",
2829            Self::StdinClosed => "stdin_closed",
2830            Self::ProcessKilled => "process_killed",
2831            Self::ProcessSnapshot => "process_snapshot",
2832            Self::ResourceSnapshot => "resource_snapshot",
2833            Self::ListenerSnapshot => "listener_snapshot",
2834            Self::BoundUdpSnapshot => "bound_udp_snapshot",
2835            Self::VmFetchResult => "vm_fetch_result",
2836            Self::SignalState => "signal_state",
2837            Self::ZombieTimerCount => "zombie_timer_count",
2838            Self::FilesystemResult => "filesystem_result",
2839            Self::PermissionDecision => "permission_decision",
2840            Self::PersistenceState => "persistence_state",
2841            Self::PersistenceFlushed => "persistence_flushed",
2842            Self::ExtResult => "ext_result",
2843            Self::GuestKernelResult => "guest_kernel_result",
2844            Self::PtyResized => "pty_resized",
2845            Self::PackageLinked => "package_linked",
2846            Self::PackageUnlinked => "package_unlinked",
2847            Self::PackageAcquired => "package_acquired",
2848            Self::PackageInstalled => "package_installed",
2849            Self::PackageCacheStats => "package_cache_stats",
2850            Self::ProvidedCommands => "provided_commands_response",
2851            Self::MountsListed => "mounts_listed",
2852            Self::ExecutionOperation => "execution_operation",
2853            Self::ExecutionCompleted => "execution_completed",
2854            Self::ExecutionEvaluation => "execution_evaluation",
2855            Self::TypeScriptCheck => "type_script_check",
2856            Self::ExecutionDescriptor => "execution_descriptor",
2857            Self::ExecutionList => "execution_list",
2858            Self::ExecutionDeleted => "execution_deleted",
2859            Self::ExecutionIo => "execution_io",
2860            Self::ExecutionOutputPage => "execution_output_page",
2861            Self::ProcessOutputPage => "process_output_page",
2862        }
2863    }
2864
2865    fn matches(self, payload: &ResponsePayload) -> bool {
2866        match payload {
2867            ResponsePayload::Rejected(_) => true,
2868            ResponsePayload::ExecutionAccepted(_) | ResponsePayload::ExecutionCompleted(_)
2869                if self == Self::ExecutionOperation =>
2870            {
2871                true
2872            }
2873            _ => payload.kind_name() == self.as_str(),
2874        }
2875    }
2876}
2877
2878impl ExpectedSidecarResponseKind {
2879    fn as_str(self) -> &'static str {
2880        match self {
2881            Self::HostCallback => "host_callback_result",
2882            Self::JsBridge => "js_bridge_result",
2883            Self::Ext => "ext_result",
2884        }
2885    }
2886
2887    fn matches(self, payload: &SidecarResponsePayload) -> bool {
2888        payload.kind_name() == self.as_str()
2889    }
2890}
2891
2892impl RequestPayload {
2893    fn ownership_requirement(&self) -> OwnershipRequirement {
2894        match self {
2895            Self::Authenticate(_) | Self::OpenSession(_) => OwnershipRequirement::Connection,
2896            Self::CreateVm(_)
2897            | Self::CompareVmConfig(_)
2898            | Self::AcquirePackage(_)
2899            | Self::GetPackageCacheStats(_)
2900            | Self::PersistenceLoad(_)
2901            | Self::PersistenceFlush(_) => OwnershipRequirement::Session,
2902            Self::DisposeVm(_)
2903            | Self::BootstrapRootFilesystem(_)
2904            | Self::ConfigureVm(_)
2905            | Self::RegisterHostCallbacks(_)
2906            | Self::CreateLayer(_)
2907            | Self::SealLayer(_)
2908            | Self::ImportSnapshot(_)
2909            | Self::ExportSnapshot(_)
2910            | Self::CreateOverlay(_)
2911            | Self::GuestFilesystemCall(_)
2912            | Self::SnapshotRootFilesystem(_)
2913            | Self::ListMounts(_)
2914            | Self::Execute(_)
2915            | Self::WriteStdin(_)
2916            | Self::CloseStdin(_)
2917            | Self::KillProcess(_)
2918            | Self::GetProcessSnapshot(_)
2919            | Self::GetResourceSnapshot(_)
2920            | Self::FindListener(_)
2921            | Self::FindBoundUdp(_)
2922            | Self::VmFetch(_)
2923            | Self::GetSignalState(_)
2924            | Self::GetZombieTimerCount(_)
2925            | Self::GuestKernelCall(_)
2926            | Self::ResizePty(_)
2927            | Self::LinkPackage(_)
2928            | Self::UnlinkPackage(_)
2929            | Self::InstallPackage(_)
2930            | Self::ProvidedCommands(_)
2931            | Self::ShellExecution(_)
2932            | Self::ArgvExecution(_)
2933            | Self::JavaScriptExecution(_)
2934            | Self::JavaScriptEvaluation(_)
2935            | Self::JavaScriptFileExecution(_)
2936            | Self::TypeScriptExecution(_)
2937            | Self::TypeScriptEvaluation(_)
2938            | Self::TypeScriptFileExecution(_)
2939            | Self::TypeScriptCheck(_)
2940            | Self::TypeScriptProjectCheck(_)
2941            | Self::NpmProjectInstall(_)
2942            | Self::NpmPackageInstall(_)
2943            | Self::NpmScriptExecution(_)
2944            | Self::NpmPackageExecution(_)
2945            | Self::PythonExecution(_)
2946            | Self::PythonEvaluation(_)
2947            | Self::PythonFileExecution(_)
2948            | Self::PythonModuleExecution(_)
2949            | Self::PythonInstall(_)
2950            | Self::CreateContext(_)
2951            | Self::GetExecution(_)
2952            | Self::ListExecutions(_)
2953            | Self::WaitExecution(_)
2954            | Self::CancelExecution(_)
2955            | Self::SignalExecution(_)
2956            | Self::ResetExecution(_)
2957            | Self::DeleteExecution(_)
2958            | Self::WriteExecutionStdin(_)
2959            | Self::CloseExecutionStdin(_)
2960            | Self::ResizeExecutionPty(_)
2961            | Self::ReadExecutionOutput(_)
2962            | Self::ReadProcessOutput(_)
2963            | Self::HostFilesystemCall(_) => OwnershipRequirement::Vm,
2964            Self::Ext(_) => OwnershipRequirement::Any,
2965        }
2966    }
2967
2968    fn expected_response(&self) -> ExpectedResponseKind {
2969        match self {
2970            Self::Authenticate(_) => ExpectedResponseKind::Authenticated,
2971            Self::OpenSession(_) => ExpectedResponseKind::SessionOpened,
2972            Self::CreateVm(_) => ExpectedResponseKind::VmCreated,
2973            Self::CompareVmConfig(_) => ExpectedResponseKind::VmConfigCompared,
2974            Self::DisposeVm(_) => ExpectedResponseKind::VmDisposed,
2975            Self::BootstrapRootFilesystem(_) => ExpectedResponseKind::RootFilesystemBootstrapped,
2976            Self::ConfigureVm(_) => ExpectedResponseKind::VmConfigured,
2977            Self::RegisterHostCallbacks(_) => ExpectedResponseKind::HostCallbacksRegistered,
2978            Self::CreateLayer(_) => ExpectedResponseKind::LayerCreated,
2979            Self::SealLayer(_) => ExpectedResponseKind::LayerSealed,
2980            Self::ImportSnapshot(_) => ExpectedResponseKind::SnapshotImported,
2981            Self::ExportSnapshot(_) => ExpectedResponseKind::SnapshotExported,
2982            Self::CreateOverlay(_) => ExpectedResponseKind::OverlayCreated,
2983            Self::GuestFilesystemCall(_) => ExpectedResponseKind::GuestFilesystemResult,
2984            Self::SnapshotRootFilesystem(_) => ExpectedResponseKind::RootFilesystemSnapshot,
2985            Self::ListMounts(_) => ExpectedResponseKind::MountsListed,
2986            Self::Execute(_) => ExpectedResponseKind::ProcessStarted,
2987            Self::WriteStdin(_) => ExpectedResponseKind::StdinWritten,
2988            Self::CloseStdin(_) => ExpectedResponseKind::StdinClosed,
2989            Self::KillProcess(_) => ExpectedResponseKind::ProcessKilled,
2990            Self::GetProcessSnapshot(_) => ExpectedResponseKind::ProcessSnapshot,
2991            Self::GetResourceSnapshot(_) => ExpectedResponseKind::ResourceSnapshot,
2992            Self::FindListener(_) => ExpectedResponseKind::ListenerSnapshot,
2993            Self::FindBoundUdp(_) => ExpectedResponseKind::BoundUdpSnapshot,
2994            Self::VmFetch(_) => ExpectedResponseKind::VmFetchResult,
2995            Self::GetSignalState(_) => ExpectedResponseKind::SignalState,
2996            Self::GetZombieTimerCount(_) => ExpectedResponseKind::ZombieTimerCount,
2997            Self::HostFilesystemCall(_) => ExpectedResponseKind::FilesystemResult,
2998            Self::PersistenceLoad(_) => ExpectedResponseKind::PersistenceState,
2999            Self::PersistenceFlush(_) => ExpectedResponseKind::PersistenceFlushed,
3000            Self::Ext(_) => ExpectedResponseKind::ExtResult,
3001            Self::GuestKernelCall(_) => ExpectedResponseKind::GuestKernelResult,
3002            Self::ResizePty(_) => ExpectedResponseKind::PtyResized,
3003            Self::LinkPackage(_) => ExpectedResponseKind::PackageLinked,
3004            Self::UnlinkPackage(_) => ExpectedResponseKind::PackageUnlinked,
3005            Self::AcquirePackage(_) => ExpectedResponseKind::PackageAcquired,
3006            Self::InstallPackage(_) => ExpectedResponseKind::PackageInstalled,
3007            Self::GetPackageCacheStats(_) => ExpectedResponseKind::PackageCacheStats,
3008            Self::ProvidedCommands(_) => ExpectedResponseKind::ProvidedCommands,
3009            Self::ShellExecution(_)
3010            | Self::ArgvExecution(_)
3011            | Self::JavaScriptExecution(_)
3012            | Self::JavaScriptFileExecution(_)
3013            | Self::TypeScriptExecution(_)
3014            | Self::TypeScriptFileExecution(_)
3015            | Self::NpmProjectInstall(_)
3016            | Self::NpmPackageInstall(_)
3017            | Self::NpmScriptExecution(_)
3018            | Self::NpmPackageExecution(_)
3019            | Self::PythonExecution(_)
3020            | Self::PythonFileExecution(_)
3021            | Self::PythonModuleExecution(_)
3022            | Self::PythonInstall(_) => ExpectedResponseKind::ExecutionOperation,
3023            Self::JavaScriptEvaluation(_)
3024            | Self::TypeScriptEvaluation(_)
3025            | Self::PythonEvaluation(_) => ExpectedResponseKind::ExecutionEvaluation,
3026            Self::TypeScriptCheck(_) | Self::TypeScriptProjectCheck(_) => {
3027                ExpectedResponseKind::TypeScriptCheck
3028            }
3029            Self::CreateContext(_)
3030            | Self::GetExecution(_)
3031            | Self::CancelExecution(_)
3032            | Self::SignalExecution(_)
3033            | Self::ResetExecution(_) => ExpectedResponseKind::ExecutionDescriptor,
3034            Self::ListExecutions(_) => ExpectedResponseKind::ExecutionList,
3035            Self::WaitExecution(_) => ExpectedResponseKind::ExecutionCompleted,
3036            Self::DeleteExecution(_) => ExpectedResponseKind::ExecutionDeleted,
3037            Self::WriteExecutionStdin(_)
3038            | Self::CloseExecutionStdin(_)
3039            | Self::ResizeExecutionPty(_) => ExpectedResponseKind::ExecutionIo,
3040            Self::ReadExecutionOutput(_) => ExpectedResponseKind::ExecutionOutputPage,
3041            Self::ReadProcessOutput(_) => ExpectedResponseKind::ProcessOutputPage,
3042        }
3043    }
3044}
3045
3046impl SidecarRequestPayload {
3047    fn ownership_requirement(&self) -> OwnershipRequirement {
3048        OwnershipRequirement::Vm
3049    }
3050
3051    fn expected_response(&self) -> ExpectedSidecarResponseKind {
3052        match self {
3053            Self::HostCallback(_) => ExpectedSidecarResponseKind::HostCallback,
3054            Self::JsBridgeCall(_) => ExpectedSidecarResponseKind::JsBridge,
3055            Self::Ext(_) => ExpectedSidecarResponseKind::Ext,
3056        }
3057    }
3058}
3059
3060impl ResponsePayload {
3061    fn ownership_requirement(&self) -> OwnershipRequirement {
3062        match self {
3063            Self::Authenticated(_) | Self::SessionOpened(_) => OwnershipRequirement::Connection,
3064            Self::VmCreated(_)
3065            | Self::VmConfigCompared(_)
3066            | Self::PackageAcquired(_)
3067            | Self::PackageCacheStats(_)
3068            | Self::PersistenceState(_)
3069            | Self::PersistenceFlushed(_) => OwnershipRequirement::Session,
3070            Self::Rejected(_) => OwnershipRequirement::Any,
3071            Self::VmDisposed(_)
3072            | Self::RootFilesystemBootstrapped(_)
3073            | Self::VmConfigured(_)
3074            | Self::HostCallbacksRegistered(_)
3075            | Self::LayerCreated(_)
3076            | Self::LayerSealed(_)
3077            | Self::SnapshotImported(_)
3078            | Self::SnapshotExported(_)
3079            | Self::OverlayCreated(_)
3080            | Self::GuestFilesystemResult(_)
3081            | Self::RootFilesystemSnapshot(_)
3082            | Self::MountsListed(_)
3083            | Self::ProcessStarted(_)
3084            | Self::StdinWritten(_)
3085            | Self::StdinClosed(_)
3086            | Self::ProcessKilled(_)
3087            | Self::ProcessSnapshot(_)
3088            | Self::ResourceSnapshot(_)
3089            | Self::ListenerSnapshot(_)
3090            | Self::BoundUdpSnapshot(_)
3091            | Self::VmFetchResult(_)
3092            | Self::SignalState(_)
3093            | Self::ZombieTimerCount(_)
3094            | Self::FilesystemResult(_)
3095            | Self::PermissionDecision(_)
3096            | Self::GuestKernelResult(_)
3097            | Self::PtyResized(_)
3098            | Self::PackageLinked(_)
3099            | Self::PackageUnlinked(_)
3100            | Self::PackageInstalled(_)
3101            | Self::ProvidedCommands(_)
3102            | Self::ExecutionAccepted(_)
3103            | Self::ExecutionCompleted(_)
3104            | Self::ExecutionEvaluation(_)
3105            | Self::TypeScriptCheck(_)
3106            | Self::ExecutionDescriptor(_)
3107            | Self::ExecutionList(_)
3108            | Self::ExecutionDeleted(_)
3109            | Self::ExecutionIo(_)
3110            | Self::ExecutionOutputPage(_)
3111            | Self::ProcessOutputPage(_) => OwnershipRequirement::Vm,
3112            Self::ExtResult(_) => OwnershipRequirement::Any,
3113        }
3114    }
3115
3116    fn kind_name(&self) -> &'static str {
3117        match self {
3118            Self::Authenticated(_) => "authenticated",
3119            Self::SessionOpened(_) => "session_opened",
3120            Self::VmCreated(_) => "vm_created",
3121            Self::VmConfigCompared(_) => "vm_config_compared",
3122            Self::VmDisposed(_) => "vm_disposed",
3123            Self::RootFilesystemBootstrapped(_) => "root_filesystem_bootstrapped",
3124            Self::VmConfigured(_) => "vm_configured",
3125            Self::HostCallbacksRegistered(_) => "host_callbacks_registered",
3126            Self::LayerCreated(_) => "layer_created",
3127            Self::LayerSealed(_) => "layer_sealed",
3128            Self::SnapshotImported(_) => "snapshot_imported",
3129            Self::SnapshotExported(_) => "snapshot_exported",
3130            Self::OverlayCreated(_) => "overlay_created",
3131            Self::GuestFilesystemResult(_) => "guest_filesystem_result",
3132            Self::RootFilesystemSnapshot(_) => "root_filesystem_snapshot",
3133            Self::MountsListed(_) => "mounts_listed",
3134            Self::ProcessStarted(_) => "process_started",
3135            Self::StdinWritten(_) => "stdin_written",
3136            Self::StdinClosed(_) => "stdin_closed",
3137            Self::ProcessKilled(_) => "process_killed",
3138            Self::ProcessSnapshot(_) => "process_snapshot",
3139            Self::ResourceSnapshot(_) => "resource_snapshot",
3140            Self::ListenerSnapshot(_) => "listener_snapshot",
3141            Self::BoundUdpSnapshot(_) => "bound_udp_snapshot",
3142            Self::VmFetchResult(_) => "vm_fetch_result",
3143            Self::SignalState(_) => "signal_state",
3144            Self::ZombieTimerCount(_) => "zombie_timer_count",
3145            Self::FilesystemResult(_) => "filesystem_result",
3146            Self::PermissionDecision(_) => "permission_decision",
3147            Self::PersistenceState(_) => "persistence_state",
3148            Self::PersistenceFlushed(_) => "persistence_flushed",
3149            Self::Rejected(_) => "rejected",
3150            Self::ExtResult(_) => "ext_result",
3151            Self::GuestKernelResult(_) => "guest_kernel_result",
3152            Self::PtyResized(_) => "pty_resized",
3153            Self::PackageLinked(_) => "package_linked",
3154            Self::PackageUnlinked(_) => "package_unlinked",
3155            Self::PackageAcquired(_) => "package_acquired",
3156            Self::PackageInstalled(_) => "package_installed",
3157            Self::PackageCacheStats(_) => "package_cache_stats",
3158            Self::ProvidedCommands(_) => "provided_commands_response",
3159            Self::ExecutionAccepted(_) => "execution_accepted",
3160            Self::ExecutionCompleted(_) => "execution_completed",
3161            Self::ExecutionEvaluation(_) => "execution_evaluation",
3162            Self::TypeScriptCheck(_) => "type_script_check",
3163            Self::ExecutionDescriptor(_) => "execution_descriptor",
3164            Self::ExecutionList(_) => "execution_list",
3165            Self::ExecutionDeleted(_) => "execution_deleted",
3166            Self::ExecutionIo(_) => "execution_io",
3167            Self::ExecutionOutputPage(_) => "execution_output_page",
3168            Self::ProcessOutputPage(_) => "process_output_page",
3169        }
3170    }
3171}
3172
3173impl SidecarResponsePayload {
3174    fn ownership_requirement(&self) -> OwnershipRequirement {
3175        OwnershipRequirement::Vm
3176    }
3177
3178    fn kind_name(&self) -> &'static str {
3179        match self {
3180            Self::HostCallbackResult(_) => "host_callback_result",
3181            Self::JsBridgeResult(_) => "js_bridge_result",
3182            Self::ExtResult(_) => "ext_result",
3183        }
3184    }
3185}
3186
3187impl EventPayload {
3188    fn ownership_requirement(&self) -> OwnershipRequirement {
3189        match self {
3190            Self::Structured(_) => OwnershipRequirement::SessionOrVm,
3191            Self::VmLifecycle(_)
3192            | Self::ProcessOutput(_)
3193            | Self::ProcessExited(_)
3194            | Self::ExecutionOutput(_)
3195            | Self::ExecutionCompleted(_) => OwnershipRequirement::Vm,
3196            Self::Ext(_) => OwnershipRequirement::Any,
3197        }
3198    }
3199}
3200
3201pub fn validate_frame(frame: &ProtocolFrame) -> Result<(), ProtocolCodecError> {
3202    match frame {
3203        ProtocolFrame::Request(request) => validate_request(request),
3204        ProtocolFrame::Response(response) => validate_response(response),
3205        ProtocolFrame::Event(event) => validate_event(event),
3206        ProtocolFrame::SidecarRequest(request) => validate_sidecar_request(request),
3207        ProtocolFrame::SidecarResponse(response) => validate_sidecar_response(response),
3208        ProtocolFrame::Control(control) => validate_schema(&control.schema),
3209    }
3210}
3211
3212fn validate_request(request: &RequestFrame) -> Result<(), ProtocolCodecError> {
3213    validate_schema(&request.schema)?;
3214    validate_request_id_direction(request.request_id, RequestDirection::Host)?;
3215
3216    validate_ownership(&request.ownership)?;
3217    validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
3218    if let RequestPayload::Authenticate(authenticate) = &request.payload {
3219        if authenticate.auth_token.is_empty() {
3220            return Err(ProtocolCodecError::EmptyAuthToken);
3221        }
3222    }
3223
3224    Ok(())
3225}
3226
3227fn validate_response(response: &ResponseFrame) -> Result<(), ProtocolCodecError> {
3228    validate_schema(&response.schema)?;
3229    validate_request_id_direction(response.request_id, RequestDirection::Host)?;
3230
3231    validate_ownership(&response.ownership)?;
3232    validate_requirement(
3233        response.payload.ownership_requirement(),
3234        &response.ownership,
3235    )?;
3236    Ok(())
3237}
3238
3239fn validate_sidecar_request(request: &SidecarRequestFrame) -> Result<(), ProtocolCodecError> {
3240    validate_schema(&request.schema)?;
3241    validate_request_id_direction(request.request_id, RequestDirection::Sidecar)?;
3242    validate_ownership(&request.ownership)?;
3243    validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
3244    Ok(())
3245}
3246
3247fn validate_sidecar_response(response: &SidecarResponseFrame) -> Result<(), ProtocolCodecError> {
3248    validate_schema(&response.schema)?;
3249    validate_request_id_direction(response.request_id, RequestDirection::Sidecar)?;
3250    validate_ownership(&response.ownership)?;
3251    validate_requirement(
3252        response.payload.ownership_requirement(),
3253        &response.ownership,
3254    )?;
3255    Ok(())
3256}
3257
3258fn validate_event(event: &EventFrame) -> Result<(), ProtocolCodecError> {
3259    validate_schema(&event.schema)?;
3260    validate_ownership(&event.ownership)?;
3261    validate_requirement(event.payload.ownership_requirement(), &event.ownership)?;
3262    Ok(())
3263}
3264
3265fn validate_schema(schema: &ProtocolSchema) -> Result<(), ProtocolCodecError> {
3266    if schema.name != PROTOCOL_NAME || schema.version != PROTOCOL_VERSION {
3267        return Err(ProtocolCodecError::UnsupportedSchema {
3268            name: schema.name.clone(),
3269            version: schema.version,
3270        });
3271    }
3272
3273    Ok(())
3274}
3275
3276fn validate_ownership(ownership: &OwnershipScope) -> Result<(), ProtocolCodecError> {
3277    match ownership {
3278        OwnershipScope::ConnectionOwnership(inner) => {
3279            validate_non_empty("connection_id", &inner.connection_id)
3280        }
3281        OwnershipScope::SessionOwnership(inner) => {
3282            validate_non_empty("connection_id", &inner.connection_id)?;
3283            validate_non_empty("session_id", &inner.session_id)
3284        }
3285        OwnershipScope::VmOwnership(inner) => {
3286            validate_non_empty("connection_id", &inner.connection_id)?;
3287            validate_non_empty("session_id", &inner.session_id)?;
3288            validate_non_empty("vm_id", &inner.vm_id)
3289        }
3290    }
3291}
3292
3293fn validate_non_empty(field: &'static str, value: &str) -> Result<(), ProtocolCodecError> {
3294    if value.is_empty() {
3295        return Err(ProtocolCodecError::EmptyOwnershipField { field });
3296    }
3297
3298    Ok(())
3299}
3300
3301fn validate_request_id_direction(
3302    request_id: RequestId,
3303    direction: RequestDirection,
3304) -> Result<(), ProtocolCodecError> {
3305    if request_id == 0 {
3306        return Err(ProtocolCodecError::InvalidRequestId);
3307    }
3308
3309    let matches_direction = match direction {
3310        RequestDirection::Host => request_id > 0,
3311        RequestDirection::Sidecar => request_id < 0,
3312    };
3313    if matches_direction {
3314        Ok(())
3315    } else {
3316        Err(ProtocolCodecError::InvalidRequestDirection {
3317            request_id,
3318            expected: direction,
3319        })
3320    }
3321}
3322
3323fn validate_requirement(
3324    required: OwnershipRequirement,
3325    ownership: &OwnershipScope,
3326) -> Result<(), ProtocolCodecError> {
3327    let actual = match ownership {
3328        OwnershipScope::ConnectionOwnership(..) => OwnershipRequirement::Connection,
3329        OwnershipScope::SessionOwnership(..) => OwnershipRequirement::Session,
3330        OwnershipScope::VmOwnership(..) => OwnershipRequirement::Vm,
3331    };
3332
3333    let valid = match required {
3334        OwnershipRequirement::Any => true,
3335        OwnershipRequirement::Connection => {
3336            matches!(ownership, OwnershipScope::ConnectionOwnership(..))
3337        }
3338        OwnershipRequirement::Session => matches!(ownership, OwnershipScope::SessionOwnership(..)),
3339        OwnershipRequirement::Vm => matches!(ownership, OwnershipScope::VmOwnership(..)),
3340        OwnershipRequirement::SessionOrVm => {
3341            matches!(
3342                ownership,
3343                OwnershipScope::SessionOwnership(..) | OwnershipScope::VmOwnership(..)
3344            )
3345        }
3346    };
3347
3348    if valid {
3349        Ok(())
3350    } else {
3351        Err(ProtocolCodecError::InvalidOwnershipScope { required, actual })
3352    }
3353}
3354
3355// ---------------------------------------------------------------------------
3356// JavaScript sync-RPC request types (deserialized from guest Node.js processes)
3357// ---------------------------------------------------------------------------
3358
3359#[derive(Debug, Clone, Deserialize)]
3360pub struct JavascriptPosixSpawnFileAction {
3361    pub command: u32,
3362    #[serde(rename = "guestFd", default)]
3363    pub guest_fd: Option<i32>,
3364    pub fd: i32,
3365    #[serde(rename = "sourceFd")]
3366    pub source_fd: i32,
3367    #[serde(rename = "guestSourceFd", default)]
3368    pub guest_source_fd: Option<i32>,
3369    pub oflag: i32,
3370    pub mode: u32,
3371    pub path: String,
3372    /// Runner-local public guest descriptors selected by closefrom. These do
3373    /// not have kernel mappings, but the child bootstrap must still suppress
3374    /// their untagged aliases while retaining private tagged preopens.
3375    #[serde(rename = "closeFromGuestFds", default)]
3376    pub close_from_guest_fds: Vec<u32>,
3377}
3378
3379#[derive(Debug, Clone, Deserialize, Serialize)]
3380#[serde(rename_all = "camelCase")]
3381pub struct JavascriptSpawnHostNetFd {
3382    pub guest_fd: u32,
3383    #[serde(default)]
3384    pub close_on_exec: bool,
3385    #[serde(default)]
3386    pub socket_id: Option<String>,
3387    #[serde(default)]
3388    pub server_id: Option<String>,
3389    #[serde(default)]
3390    pub udp_socket_id: Option<String>,
3391    /// Runner-visible socket metadata needed to reconstruct the libc-facing
3392    /// descriptor in the child. Resource ownership is never trusted from this
3393    /// object: the sidecar resolves and clones the named parent resource.
3394    #[serde(default)]
3395    pub metadata: Value,
3396}
3397
3398#[derive(Debug, Deserialize, Default)]
3399pub struct JavascriptChildProcessPtyOptions {
3400    #[serde(default)]
3401    pub cols: Option<u16>,
3402    #[serde(default)]
3403    pub rows: Option<u16>,
3404}
3405
3406#[derive(Debug, Deserialize, Default)]
3407pub struct JavascriptChildProcessSpawnOptions {
3408    #[serde(default)]
3409    pub argv0: Option<String>,
3410    /// Guest descriptors marked FD_CLOEXEC in libc's runner-local descriptor
3411    /// table. Native exec applies these at the same commit point as the kernel
3412    /// table; runner-local handles are closed by the in-place image swap.
3413    #[serde(rename = "cloexecFds", default)]
3414    pub cloexec_fds: Vec<u32>,
3415    /// The sidecar-managed WASM runner has already validated the replacement
3416    /// module and will swap images in place after the sidecar commits kernel
3417    /// metadata. Other process.exec callers use the separate-execution path.
3418    #[serde(rename = "localReplacement", default)]
3419    pub local_replacement: bool,
3420    /// Runner-private executable descriptor used only by the dedicated
3421    /// process.exec_fd_image_commit route. Generic guest process.exec requests
3422    /// cannot turn this into an FD-backed replacement.
3423    #[serde(rename = "executableFd", default)]
3424    pub executable_fd: Option<u32>,
3425    #[serde(default)]
3426    pub cwd: Option<String>,
3427    #[serde(default)]
3428    pub env: BTreeMap<String, String>,
3429    #[serde(rename = "internalBootstrapEnv", default)]
3430    pub internal_bootstrap_env: BTreeMap<String, String>,
3431    /// POSIX spawn attributes already validated by the WASM host-import
3432    /// boundary. The sidecar validates them again before applying attributes
3433    /// that belong to the kernel process table.
3434    #[serde(rename = "spawnAttrFlags", default)]
3435    pub spawn_attr_flags: u32,
3436    /// Exact `posix_spawn` bypasses PATH lookup, including for bare names.
3437    #[serde(rename = "spawnExactPath", default)]
3438    pub spawn_exact_path: bool,
3439    /// `posix_spawnp` uses the caller's PATH, which can differ from envp.
3440    #[serde(rename = "spawnSearchPath", default)]
3441    pub spawn_search_path: Option<String>,
3442    #[serde(rename = "spawnSchedPolicy", default)]
3443    pub spawn_sched_policy: Option<i32>,
3444    #[serde(rename = "spawnSchedPriority", default)]
3445    pub spawn_sched_priority: Option<i32>,
3446    #[serde(rename = "spawnPgroup", default)]
3447    pub spawn_pgroup: Option<i32>,
3448    #[serde(rename = "spawnSignalDefaults", default)]
3449    pub spawn_signal_defaults: Vec<u32>,
3450    #[serde(rename = "spawnSignalMask", default)]
3451    pub spawn_signal_mask: Vec<u32>,
3452    #[serde(rename = "spawnFileActions", default)]
3453    pub spawn_file_actions: Vec<JavascriptPosixSpawnFileAction>,
3454    /// Guest-to-kernel descriptor namespace captured by the WASM runner at
3455    /// spawn time. WASI preopens occupy guest descriptors that do not exist in
3456    /// the kernel table, so file actions cannot safely assume the two numeric
3457    /// namespaces are identical.
3458    #[serde(rename = "spawnFdMappings", default)]
3459    pub spawn_fd_mappings: Vec<[u32; 2]>,
3460    /// Host-network descriptors occupy the guest fd namespace but are backed
3461    /// by sidecar-owned socket descriptions rather than kernel fd-table slots.
3462    /// They must therefore be inherited explicitly instead of being coerced
3463    /// into the private kernel descriptor namespace.
3464    #[serde(rename = "spawnHostNetFds", default)]
3465    pub spawn_host_net_fds: Vec<JavascriptSpawnHostNetFd>,
3466    #[serde(default)]
3467    pub input: Option<Value>,
3468    #[serde(default)]
3469    pub shell: bool,
3470    #[serde(default)]
3471    pub detached: bool,
3472    #[serde(default)]
3473    pub stdio: Vec<String>,
3474    #[serde(default)]
3475    pub timeout: Option<u64>,
3476    #[serde(rename = "killSignal", default)]
3477    pub kill_signal: Option<String>,
3478    #[serde(default)]
3479    pub pty: Option<JavascriptChildProcessPtyOptions>,
3480}
3481
3482#[derive(Debug, Deserialize)]
3483pub struct JavascriptChildProcessSpawnRequest {
3484    pub command: String,
3485    #[serde(default)]
3486    pub args: Vec<String>,
3487    #[serde(default)]
3488    pub options: JavascriptChildProcessSpawnOptions,
3489}
3490
3491#[derive(Debug, Deserialize)]
3492pub struct JavascriptNetConnectRequest {
3493    #[serde(default)]
3494    pub host: Option<String>,
3495    #[serde(default)]
3496    pub port: Option<u16>,
3497    #[serde(default)]
3498    pub family: Option<u8>,
3499    #[serde(default)]
3500    pub path: Option<String>,
3501    #[serde(rename = "abstractPathHex", default)]
3502    pub abstract_path_hex: Option<String>,
3503    #[serde(rename = "boundServerId", default)]
3504    pub bound_server_id: Option<String>,
3505    #[serde(rename = "localAddress", default)]
3506    pub local_address: Option<String>,
3507    #[serde(rename = "localPort", default)]
3508    pub local_port: Option<u16>,
3509    #[serde(rename = "localReservation", default)]
3510    pub local_reservation: Option<String>,
3511}
3512
3513#[derive(Debug, Deserialize)]
3514pub struct JavascriptNetBindConnectedUnixRequest {
3515    #[serde(rename = "socketId")]
3516    pub socket_id: String,
3517    #[serde(default)]
3518    pub path: Option<String>,
3519    #[serde(rename = "abstractPathHex", default)]
3520    pub abstract_path_hex: Option<String>,
3521    #[serde(default)]
3522    pub autobind: bool,
3523}
3524
3525#[derive(Debug, Deserialize)]
3526pub struct JavascriptNetReserveTcpPortRequest {
3527    #[serde(default)]
3528    pub host: Option<String>,
3529    #[serde(default)]
3530    pub port: Option<u16>,
3531}
3532
3533#[derive(Debug, Deserialize)]
3534pub struct JavascriptNetListenRequest {
3535    #[serde(default)]
3536    pub host: Option<String>,
3537    #[serde(default)]
3538    pub port: Option<u16>,
3539    #[serde(default)]
3540    pub path: Option<String>,
3541    #[serde(rename = "abstractPathHex", default)]
3542    pub abstract_path_hex: Option<String>,
3543    #[serde(rename = "boundServerId", default)]
3544    pub bound_server_id: Option<String>,
3545    #[serde(default)]
3546    pub autobind: bool,
3547    #[serde(default)]
3548    pub backlog: Option<u32>,
3549    #[serde(rename = "localReservation", default)]
3550    pub local_reservation: Option<String>,
3551}
3552
3553#[derive(Debug, Deserialize)]
3554pub struct JavascriptDgramCreateSocketRequest {
3555    #[serde(rename = "type")]
3556    pub socket_type: String,
3557}
3558
3559#[derive(Debug, Deserialize)]
3560pub struct JavascriptDgramBindRequest {
3561    #[serde(default)]
3562    pub address: Option<String>,
3563    #[serde(default)]
3564    pub port: u16,
3565}
3566
3567#[derive(Debug, Deserialize)]
3568pub struct JavascriptDgramSendRequest {
3569    #[serde(default)]
3570    pub address: Option<String>,
3571    #[serde(default)]
3572    pub port: Option<u16>,
3573}
3574
3575#[derive(Debug, Deserialize)]
3576pub struct JavascriptDgramConnectRequest {
3577    #[serde(default)]
3578    pub address: Option<String>,
3579    pub port: u16,
3580}
3581
3582#[derive(Debug, Deserialize)]
3583pub struct JavascriptDnsLookupRequest {
3584    pub hostname: String,
3585    #[serde(default)]
3586    pub family: Option<u8>,
3587}
3588
3589#[derive(Debug, Deserialize)]
3590pub struct JavascriptDnsResolveRequest {
3591    pub hostname: String,
3592    #[serde(default)]
3593    pub rrtype: Option<String>,
3594}