diff --git a/src/agent/src/pci.rs b/src/agent/src/pci.rs index 7f85e53949..176d90c678 100644 --- a/src/agent/src/pci.rs +++ b/src/agent/src/pci.rs @@ -4,6 +4,7 @@ // use std::convert::TryInto; use std::fmt; +use std::ops::Deref; use std::str::FromStr; use anyhow::anyhow; @@ -48,9 +49,50 @@ impl fmt::Display for Slot { } } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Path(Vec); + +impl Path { + pub fn new(slots: Vec) -> anyhow::Result { + if slots.is_empty() { + return Err(anyhow!("PCI path must have at least one element")); + } + Ok(Path(slots)) + } +} + +// Let Path be treated as a slice of Slots +impl Deref for Path { + type Target = [Slot]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl fmt::Display for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let sslots: Vec = self + .0 + .iter() + .map(std::string::ToString::to_string) + .collect(); + write!(f, "{}", sslots.join("/")) + } +} + +impl FromStr for Path { + type Err = anyhow::Error; + + fn from_str(s: &str) -> anyhow::Result { + let rslots: anyhow::Result> = s.split('/').map(Slot::from_str).collect(); + Path::new(rslots?) + } +} + #[cfg(test)] mod tests { - use crate::pci::Slot; + use crate::pci::{Path, Slot}; use std::str::FromStr; #[test] @@ -85,4 +127,42 @@ mod tests { let slot = Slot::from_str(""); assert!(slot.is_err()); } + + #[test] + fn test_path() { + let slot3 = Slot::new(0x03).unwrap(); + let slot4 = Slot::new(0x04).unwrap(); + let slot5 = Slot::new(0x05).unwrap(); + + // Valid paths + let pcipath = Path::new(vec![slot3]).unwrap(); + assert_eq!(format!("{}", pcipath), "03"); + let pcipath2 = Path::from_str("03").unwrap(); + assert_eq!(pcipath, pcipath2); + assert_eq!(pcipath.len(), 1); + assert_eq!(pcipath[0], slot3); + + let pcipath = Path::new(vec![slot3, slot4]).unwrap(); + assert_eq!(format!("{}", pcipath), "03/04"); + let pcipath2 = Path::from_str("03/04").unwrap(); + assert_eq!(pcipath, pcipath2); + assert_eq!(pcipath.len(), 2); + assert_eq!(pcipath[0], slot3); + assert_eq!(pcipath[1], slot4); + + let pcipath = Path::new(vec![slot3, slot4, slot5]).unwrap(); + assert_eq!(format!("{}", pcipath), "03/04/05"); + let pcipath2 = Path::from_str("03/04/05").unwrap(); + assert_eq!(pcipath, pcipath2); + assert_eq!(pcipath.len(), 3); + assert_eq!(pcipath[0], slot3); + assert_eq!(pcipath[1], slot4); + assert_eq!(pcipath[2], slot5); + + // Bad paths + assert!(Path::new(vec!()).is_err()); + assert!(Path::from_str("20").is_err()); + assert!(Path::from_str("//").is_err()); + assert!(Path::from_str("xyz").is_err()); + } }