Skip to main content

isaac_sim_bridge/
source.rs

1// SPDX-License-Identifier: MPL-2.0
2/// Filter for the per-source routing key adapters use to demultiplex
3/// dispatches from multiple sensors of the same type.
4///
5/// Centralised so all adapters share one definition of "matches" — if
6/// glob/regex/prefix matching ever lands, it lands in one place.
7///
8/// # Example
9///
10/// ```
11/// use isaac_sim_bridge::SourceFilter;
12/// let f = SourceFilter::exact("/World/Carter/lidar_2d");
13/// assert!(f.matches("/World/Carter/lidar_2d"));
14/// assert!(!f.matches("/World/Carter/lidar_3d"));
15/// ```
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct SourceFilter(String);
18
19impl SourceFilter {
20    /// Construct a filter that matches exactly `source` (no wildcards).
21    ///
22    /// # Example
23    ///
24    /// ```
25    /// use isaac_sim_bridge::SourceFilter;
26    /// let f = SourceFilter::exact("/World/lidar");
27    /// assert!(f.matches("/World/lidar"));
28    /// ```
29    pub fn exact(source: impl Into<String>) -> Self {
30        Self(source.into())
31    }
32
33    /// Returns `true` if `src` matches this filter exactly.
34    ///
35    /// # Example
36    ///
37    /// ```
38    /// use isaac_sim_bridge::SourceFilter;
39    /// let f = SourceFilter::exact("/sensor/a");
40    /// assert!(f.matches("/sensor/a"));
41    /// assert!(!f.matches("/sensor/b"));
42    /// ```
43    pub fn matches(&self, src: &str) -> bool {
44        self.0 == src
45    }
46
47    /// The raw filter string, e.g. a prim path like `/World/Carter/lidar_2d`.
48    pub fn as_str(&self) -> &str {
49        &self.0
50    }
51}
52
53impl From<String> for SourceFilter {
54    fn from(s: String) -> Self {
55        Self::exact(s)
56    }
57}
58
59impl From<&str> for SourceFilter {
60    fn from(s: &str) -> Self {
61        Self::exact(s)
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn matches_exact_path() {
71        let f = SourceFilter::exact("/Root/World/Carter/lidar_2d");
72        assert!(f.matches("/Root/World/Carter/lidar_2d"));
73        assert!(!f.matches("/Root/World/Carter/lidar_3d"));
74        assert!(!f.matches(""));
75    }
76
77    #[test]
78    fn empty_filter_does_not_match_unset_source() {
79        let f = SourceFilter::exact("");
80        assert!(f.matches(""));
81        assert!(!f.matches("/anything"));
82    }
83}