librespot_core/dealer/
maps.rs

1use std::collections::HashMap;
2
3use crate::Error;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum HandlerMapError {
8    #[error("request was already handled")]
9    AlreadyHandled,
10}
11
12impl From<HandlerMapError> for Error {
13    fn from(err: HandlerMapError) -> Self {
14        Error::aborted(err)
15    }
16}
17
18pub enum HandlerMap<T> {
19    Leaf(T),
20    Branch(HashMap<String, HandlerMap<T>>),
21}
22
23impl<T> Default for HandlerMap<T> {
24    fn default() -> Self {
25        Self::Branch(HashMap::new())
26    }
27}
28
29impl<T> HandlerMap<T> {
30    pub fn contains(&self, path: &str) -> bool {
31        matches!(self, HandlerMap::Branch(map) if map.contains_key(path))
32    }
33
34    pub fn insert<'a>(
35        &mut self,
36        mut path: impl Iterator<Item = &'a str>,
37        handler: T,
38    ) -> Result<(), Error> {
39        match self {
40            Self::Leaf(_) => Err(HandlerMapError::AlreadyHandled.into()),
41            Self::Branch(children) => {
42                if let Some(component) = path.next() {
43                    let node = children.entry(component.to_owned()).or_default();
44                    node.insert(path, handler)
45                } else if children.is_empty() {
46                    *self = Self::Leaf(handler);
47                    Ok(())
48                } else {
49                    Err(HandlerMapError::AlreadyHandled.into())
50                }
51            }
52        }
53    }
54
55    pub fn get<'a>(&self, mut path: impl Iterator<Item = &'a str>) -> Option<&T> {
56        match self {
57            Self::Leaf(t) => Some(t),
58            Self::Branch(m) => {
59                let component = path.next()?;
60                m.get(component)?.get(path)
61            }
62        }
63    }
64
65    pub fn remove<'a>(&mut self, mut path: impl Iterator<Item = &'a str>) -> Option<T> {
66        match self {
67            Self::Leaf(_) => match std::mem::take(self) {
68                Self::Leaf(t) => Some(t),
69                _ => unreachable!(),
70            },
71            Self::Branch(map) => {
72                let component = path.next()?;
73                let next = map.get_mut(component)?;
74                let result = next.remove(path);
75                match &*next {
76                    Self::Branch(b) if b.is_empty() => {
77                        map.remove(component);
78                    }
79                    _ => (),
80                }
81                result
82            }
83        }
84    }
85}
86
87pub struct SubscriberMap<T> {
88    subscribed: Vec<T>,
89    children: HashMap<String, SubscriberMap<T>>,
90}
91
92impl<T> Default for SubscriberMap<T> {
93    fn default() -> Self {
94        Self {
95            subscribed: Vec::new(),
96            children: HashMap::new(),
97        }
98    }
99}
100
101impl<T> SubscriberMap<T> {
102    pub fn insert<'a>(&mut self, mut path: impl Iterator<Item = &'a str>, handler: T) {
103        if let Some(component) = path.next() {
104            self.children
105                .entry(component.to_owned())
106                .or_default()
107                .insert(path, handler);
108        } else {
109            self.subscribed.push(handler);
110        }
111    }
112
113    pub fn contains<'a>(&self, mut path: impl Iterator<Item = &'a str>) -> bool {
114        if !self.subscribed.is_empty() {
115            return true;
116        }
117
118        if let Some(next) = path.next() {
119            if let Some(next_map) = self.children.get(next) {
120                return next_map.contains(path);
121            }
122        } else {
123            return !self.is_empty();
124        }
125
126        false
127    }
128
129    pub fn is_empty(&self) -> bool {
130        self.children.is_empty() && self.subscribed.is_empty()
131    }
132
133    pub fn retain<'a>(
134        &mut self,
135        mut path: impl Iterator<Item = &'a str>,
136        fun: &mut impl FnMut(&T) -> bool,
137    ) -> bool {
138        let mut handled_by_any = false;
139        self.subscribed.retain(|x| {
140            handled_by_any = true;
141            fun(x)
142        });
143
144        if let Some(next) = path.next() {
145            if let Some(y) = self.children.get_mut(next) {
146                handled_by_any = handled_by_any || y.retain(path, fun);
147                if y.is_empty() {
148                    self.children.remove(next);
149                }
150            }
151        }
152
153        handled_by_any
154    }
155}