use std::path::Path;
use std::path::PathBuf;
use serde::Deserialize;
use serde::Serialize;
use serde_keyvalue::FromKeyValues;
static VHOST_VSOCK_DEFAULT_PATH: &str = "/dev/vhost-vsock";
fn default_vsock_path() -> PathBuf {
PathBuf::from(VHOST_VSOCK_DEFAULT_PATH)
}
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, FromKeyValues)]
#[serde(deny_unknown_fields)]
pub struct VsockConfig {
pub cid: u64,
#[serde(default = "default_vsock_path", rename = "device")]
pub vhost_device: PathBuf,
}
impl VsockConfig {
pub fn new<P: AsRef<Path>>(cid: u64, vhost_device: Option<P>) -> Self {
Self {
cid,
#[cfg(any(target_os = "android", target_os = "linux"))]
vhost_device: vhost_device
.map(|p| PathBuf::from(p.as_ref()))
.unwrap_or_else(|| PathBuf::from(VHOST_VSOCK_DEFAULT_PATH)),
}
}
}
#[cfg(test)]
mod tests {
use serde_keyvalue::from_key_values;
use serde_keyvalue::ErrorKind;
use serde_keyvalue::ParseError;
use super::*;
fn from_vsock_arg(options: &str) -> Result<VsockConfig, ParseError> {
from_key_values(options)
}
#[test]
fn params_from_key_values() {
assert_eq!(
from_vsock_arg("cid=56").unwrap(),
VsockConfig {
vhost_device: VHOST_VSOCK_DEFAULT_PATH.into(),
cid: 56,
}
);
assert_eq!(
from_vsock_arg("").unwrap_err(),
ParseError {
kind: ErrorKind::SerdeError("missing field `cid`".into()),
pos: 0
}
);
assert_eq!(
from_vsock_arg("78").unwrap(),
VsockConfig {
#[cfg(any(target_os = "android", target_os = "linux"))]
vhost_device: VHOST_VSOCK_DEFAULT_PATH.into(),
cid: 78,
}
);
assert_eq!(
from_vsock_arg("cid=42,cid=56").unwrap_err(),
ParseError {
kind: ErrorKind::SerdeError("duplicate field `cid`".into()),
pos: 0,
}
);
assert_eq!(
from_vsock_arg("invalid=foo").unwrap_err(),
ParseError {
kind: ErrorKind::SerdeError(
"unknown field `invalid`, expected `cid` or `device`".into()
),
pos: 0,
}
);
assert_eq!(
from_vsock_arg("device=/some/path,cid=56").unwrap(),
VsockConfig {
vhost_device: "/some/path".into(),
cid: 56,
}
);
assert_eq!(
from_vsock_arg("56,device=/some/path").unwrap(),
VsockConfig {
vhost_device: "/some/path".into(),
cid: 56,
}
);
assert_eq!(
from_vsock_arg("device=42").unwrap_err(),
ParseError {
kind: ErrorKind::SerdeError("missing field `cid`".into()),
pos: 0,
}
);
assert_eq!(
from_vsock_arg("cid=56,device=42,device=/some/path").unwrap_err(),
ParseError {
kind: ErrorKind::SerdeError("duplicate field `device`".into()),
pos: 0,
}
);
}
}