Skip to main content

instrument_core/
enumerator.rs

1use crate::address::ResourceAddress;
2use crate::error::Result;
3use crate::transport::TransportIdentity;
4
5/// Raw resource from an enumerator before classification.
6#[derive(Debug, Clone)]
7pub struct RawResource {
8    pub address: ResourceAddress,
9    pub identity_hint: TransportIdentity,
10}
11
12/// Narrow seam for acquiring resources without coupling to VISA.
13pub trait ResourceEnumerator: Send + Sync {
14    fn list(&self, pattern: &str) -> Result<Vec<RawResource>>;
15}
16
17/// Static resource list for unit tests.
18#[derive(Debug, Default)]
19pub struct StaticEnumerator {
20    resources: Vec<RawResource>,
21}
22
23impl StaticEnumerator {
24    pub fn new(resources: Vec<RawResource>) -> Self {
25        Self { resources }
26    }
27
28    pub fn from_addresses(addresses: impl IntoIterator<Item = String>) -> Result<Self> {
29        let resources = addresses
30            .into_iter()
31            .map(|raw| {
32                Ok(RawResource {
33                    address: ResourceAddress::parse(&raw)?,
34                    identity_hint: TransportIdentity::default(),
35                })
36            })
37            .collect::<Result<Vec<_>>>()?;
38        Ok(Self::new(resources))
39    }
40}
41
42impl ResourceEnumerator for StaticEnumerator {
43    fn list(&self, pattern: &str) -> Result<Vec<RawResource>> {
44        if pattern == "?*INSTR" || pattern == "?*" {
45            return Ok(self.resources.clone());
46        }
47        Ok(self
48            .resources
49            .iter()
50            .filter(|r| r.address.raw.contains(pattern.trim_matches('?')))
51            .cloned()
52            .collect())
53    }
54}