squib_api/schemas/
vsock.rs1use serde::{Deserialize, Serialize};
12
13use super::common::{UdsPath, VsockId};
14
15pub const MIN_GUEST_CID: u32 = 3;
17
18#[derive(Debug, Clone, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct RawVsockConfig {
22 #[serde(default)]
24 pub vsock_id: Option<String>,
25 pub guest_cid: u32,
27 pub uds_path: String,
29 #[serde(default)]
31 pub tsi: bool,
32}
33
34#[derive(Debug, Clone, Serialize)]
36#[non_exhaustive]
37pub struct VsockConfig {
38 pub vsock_id: Option<VsockId>,
40 pub guest_cid: u32,
42 pub uds_path: UdsPath,
44 pub tsi: bool,
46}
47
48impl TryFrom<RawVsockConfig> for VsockConfig {
49 type Error = String;
50
51 fn try_from(raw: RawVsockConfig) -> Result<Self, Self::Error> {
52 if raw.guest_cid < MIN_GUEST_CID {
53 return Err(format!(
54 "Invalid guest_cid: must be >= {MIN_GUEST_CID}, got {}",
55 raw.guest_cid
56 ));
57 }
58 let vsock_id = match raw.vsock_id {
59 Some(s) => Some(VsockId::new(s)?),
60 None => None,
61 };
62 let uds_path = UdsPath::new(raw.uds_path).map_err(|e| format!("Invalid uds_path: {e}"))?;
63 Ok(Self {
64 vsock_id,
65 guest_cid: raw.guest_cid,
66 uds_path,
67 tsi: raw.tsi,
68 })
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_should_accept_minimal_vsock() {
78 let raw = RawVsockConfig {
79 vsock_id: None,
80 guest_cid: 3,
81 uds_path: "/tmp/vsock.sock".into(),
82 tsi: false,
83 };
84 let cfg = VsockConfig::try_from(raw).unwrap();
85 assert_eq!(cfg.guest_cid, 3);
86 }
87
88 #[test]
89 fn test_should_reject_guest_cid_below_3() {
90 let raw = RawVsockConfig {
91 vsock_id: None,
92 guest_cid: 2,
93 uds_path: "/tmp/vsock.sock".into(),
94 tsi: false,
95 };
96 assert!(VsockConfig::try_from(raw).is_err());
97 }
98
99 #[test]
100 fn test_should_reject_uds_path_above_darwin_cap() {
101 let raw = RawVsockConfig {
102 vsock_id: None,
103 guest_cid: 3,
104 uds_path: format!("/tmp/{}", "a".repeat(110)),
105 tsi: false,
106 };
107 let err = VsockConfig::try_from(raw).unwrap_err();
108 assert!(err.contains("uds_path"));
109 }
110
111 #[test]
112 fn test_should_default_tsi_to_false() {
113 let json = r#"{"guest_cid":3,"uds_path":"/tmp/v"}"#;
114 let raw: RawVsockConfig = serde_json::from_str(json).unwrap();
115 assert!(!raw.tsi);
116 }
117}