Skip to main content

unifly_api/stream/
filter.rs

1// ── Filter predicates for entity streams ──
2//
3// Used by the TUI to filter snapshots without re-querying the API.
4
5use crate::model::{Client, ClientType, Device, DeviceState, DeviceType, EntityId, MacAddress};
6
7/// Filter predicate for device collections.
8pub enum DeviceFilter {
9    All,
10    ByType(DeviceType),
11    ByState(DeviceState),
12    BySite(EntityId),
13    Online,
14    Offline,
15    Custom(Box<dyn Fn(&Device) -> bool + Send + Sync>),
16}
17
18impl DeviceFilter {
19    pub fn matches(&self, device: &Device) -> bool {
20        match self {
21            Self::All => true,
22            Self::ByType(dt) => device.device_type == *dt,
23            Self::ByState(ds) => device.state == *ds,
24            // All devices in the DataStore belong to the configured site,
25            // so BySite is effectively a no-op in single-site mode.
26            // Multi-site support would require adding site_id to Device.
27            Self::BySite(_sid) => true,
28            Self::Online => device.state.is_online(),
29            Self::Offline => matches!(device.state, DeviceState::Offline),
30            Self::Custom(f) => f(device),
31        }
32    }
33}
34
35/// Filter predicate for client collections.
36pub enum ClientFilter {
37    All,
38    ByType(ClientType),
39    ByNetwork(EntityId),
40    ByDevice(MacAddress),
41    Guests,
42    Blocked,
43    Custom(Box<dyn Fn(&Client) -> bool + Send + Sync>),
44}
45
46impl ClientFilter {
47    pub fn matches(&self, client: &Client) -> bool {
48        match self {
49            Self::All => true,
50            Self::ByType(ct) => client.client_type == *ct,
51            Self::ByNetwork(nid) => client.network_id.as_ref() == Some(nid),
52            Self::ByDevice(mac) => client.uplink_device_mac.as_ref() == Some(mac),
53            Self::Guests => client.is_guest,
54            Self::Blocked => client.blocked,
55            Self::Custom(f) => f(client),
56        }
57    }
58}