use serde::{Deserialize, Deserializer};
use serde::ser::{SerializeStruct, Serialize, Serializer};
use crate::wrapper::platformio;
#[derive(Deserialize, Debug)]
pub struct PioDevice {
pub port: String,
#[serde(deserialize_with = "parse_input", default)]
pub description: Option<String>,
#[serde(deserialize_with = "parse_input", default)]
pub hwid: Option<String>,
}
impl Serialize for PioDevice {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let hwid = match &self.hwid {
Some(id) => id.as_str(),
None => "n/a",
};
let description = match &self.description {
Some(d) => d.as_str(),
None => "n/a",
};
let mut state = serializer.serialize_struct("PioDevice", 3)?;
state.serialize_field("port", &self.port)?;
state.serialize_field("hwid", &hwid)?;
state.serialize_field("description", description)?;
state.end()
}
}
pub fn get_connected_device_list() -> Result<Vec<PioDevice>, String> {
let ports = get_port_list()?;
let mut connected: Vec<PioDevice> = Vec::new();
for port in ports {
match port.hwid {
Some(_) => {
connected.push(port);
},
None => (),
};
}
Ok(connected)
}
pub fn get_port_list() -> Result<Vec<PioDevice>, String> {
let output = platformio::get_devices()?;
let json = String::from_utf8_lossy(&output);
let devices: Vec<PioDevice> = match serde_json::from_str(&json) {
Ok(res) => res,
Err(_) => {
return Err(String::from("Failed to parse device list JSON."));
}
};
Ok(devices)
}
fn parse_input<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let opt: Option<String> = Option::deserialize(deserializer)?;
Ok(match opt {
Some(s) if s == "n/a" => None,
other => other,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pio_device_deserialization() {
let json_data = r#"
[
{
"port": "/dev/ttyUSB0",
"description": "USB Serial",
"hwid": "USB VID:PID=1A86:7523"
},
{
"port": "/dev/ttyS0",
"description": "n/a",
"hwid": "n/a"
}
]
"#;
let devices: Vec<PioDevice> = serde_json::from_str(json_data).unwrap();
assert_eq!(devices.len(), 2);
assert_eq!(devices[0].port, "/dev/ttyUSB0");
assert_eq!(devices[0].description, Some("USB Serial".to_string()));
assert_eq!(devices[0].hwid, Some("USB VID:PID=1A86:7523".to_string()));
assert_eq!(devices[1].port, "/dev/ttyS0");
assert_eq!(devices[1].description, None);
assert_eq!(devices[1].hwid, None);
}
}