grafos_registry/
filter.rs

1//! Registry query filters.
2
3extern crate alloc;
4use alloc::string::String;
5use alloc::vec::Vec;
6
7use crate::registration::{HealthStatus, ServiceRegistration};
8
9/// Filter criteria for registry lookups.
10///
11/// All active criteria are combined with AND semantics: a registration must
12/// match every specified filter to be included in results.
13pub struct RegistryFilter {
14    version_prefix: Option<String>,
15    required_tags: Vec<(String, String)>,
16    health: Option<HealthStatus>,
17}
18
19impl RegistryFilter {
20    /// Create an empty filter (matches everything).
21    pub fn new() -> Self {
22        RegistryFilter {
23            version_prefix: None,
24            required_tags: Vec::new(),
25            health: None,
26        }
27    }
28
29    /// Filter by version prefix (e.g. `"1."` matches `"1.0.0"`, `"1.2.3"`).
30    pub fn version_prefix(mut self, prefix: &str) -> Self {
31        self.version_prefix = Some(String::from(prefix));
32        self
33    }
34
35    /// Require a tag key-value pair (AND with other tags).
36    pub fn tag(mut self, key: &str, value: &str) -> Self {
37        self.required_tags
38            .push((String::from(key), String::from(value)));
39        self
40    }
41
42    /// Filter by health status.
43    pub fn health(mut self, status: HealthStatus) -> Self {
44        self.health = Some(status);
45        self
46    }
47
48    /// Test whether a registration matches all active filter criteria.
49    pub fn matches(&self, reg: &ServiceRegistration) -> bool {
50        if let Some(ref prefix) = self.version_prefix {
51            if !reg.version_matches_prefix(prefix) {
52                return false;
53            }
54        }
55
56        if !self.required_tags.is_empty() && !reg.has_tags(&self.required_tags) {
57            return false;
58        }
59
60        if let Some(ref required_health) = self.health {
61            let health_matches = matches!(
62                (required_health, &reg.health),
63                (HealthStatus::Healthy, HealthStatus::Healthy)
64                    | (HealthStatus::Draining, HealthStatus::Draining)
65                    | (HealthStatus::Degraded { .. }, HealthStatus::Degraded { .. })
66            );
67            if !health_matches {
68                return false;
69            }
70        }
71
72        true
73    }
74}
75
76impl Default for RegistryFilter {
77    fn default() -> Self {
78        Self::new()
79    }
80}