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