asteroid_mq_model/
interest.rs

1use std::{convert::Infallible, fmt::Display, str::FromStr};
2
3use bytes::Bytes;
4use serde::{Deserialize, Serialize};
5use typeshare::typeshare;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8#[typeshare(serialized_as = "String")]
9pub struct Subject(pub(crate) Bytes);
10
11impl From<&'static str> for Subject {
12    fn from(value: &'static str) -> Self {
13        Subject(Bytes::from_static(value.as_bytes()))
14    }
15}
16
17impl Serialize for Subject {
18    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19    where
20        S: serde::Serializer,
21    {
22        let string = unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) };
23        serializer.serialize_str(string)
24    }
25}
26
27impl<'de> Deserialize<'de> for Subject {
28    fn deserialize<D>(deserializer: D) -> Result<Subject, D::Error>
29    where
30        D: serde::Deserializer<'de>,
31    {
32        let string = String::deserialize(deserializer)?;
33        Ok(Subject(Bytes::from(string)))
34    }
35}
36
37impl FromStr for Subject {
38    type Err = Infallible;
39    fn from_str(s: &str) -> Result<Self, Self::Err> {
40        Ok(Subject(Bytes::from(s.to_owned())))
41    }
42}
43
44impl Display for Subject {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        let string = unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) };
47        write!(f, "{}", string)
48    }
49}
50
51impl AsRef<str> for Subject {
52    fn as_ref(&self) -> &str {
53        self.as_str()
54    }
55}
56
57impl Subject {
58    pub fn as_str(&self) -> &str {
59        unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) }
60    }
61    pub fn as_bytes(&self) -> &[u8] {
62        self.0.as_ref()
63    }
64    pub fn new<B: Into<Bytes>>(bytes: B) -> Self {
65        Self(bytes.into())
66    }
67    pub const fn const_new(bytes: &'static str) -> Self {
68        Self(Bytes::from_static(bytes.as_bytes()))
69    }
70    pub fn segments(&self) -> SubjectSegments<'_> {
71        SubjectSegments {
72            inner: self.0.as_ref(),
73        }
74    }
75}
76#[derive(Debug, Clone)]
77pub struct SubjectSegments<'a> {
78    // stripped slash, always start with a non-slash byte
79    inner: &'a [u8],
80}
81
82impl<'a> Iterator for SubjectSegments<'a> {
83    type Item = &'a [u8];
84
85    fn next(&mut self) -> Option<Self::Item> {
86        if self.inner.is_empty() {
87            return None;
88        }
89        let mut slash_index = None;
90        for index in 0..self.inner.len() {
91            if self.inner[index] == b'/' {
92                slash_index.replace(index);
93                break;
94            }
95        }
96        if let Some(slash_index) = slash_index {
97            let next = &self.inner[0..slash_index];
98            let mut next_start = None;
99            for (bias, b) in self.inner[slash_index..].iter().enumerate() {
100                if *b != b'/' {
101                    next_start = Some(slash_index + bias);
102                    break;
103                }
104            }
105            if let Some(next_start) = next_start {
106                self.inner = &self.inner[next_start..]
107            } else {
108                self.inner = &[];
109            }
110            Some(next)
111        } else {
112            let next = self.inner;
113            self.inner = &[];
114            Some(next)
115        }
116    }
117}
118
119/// # Interest
120/// ## Glob Match Interest
121/// (/)?(<path>|<*>|<**>)/*
122#[derive(Debug, Clone, PartialEq, Eq, Hash)]
123#[typeshare(serialized_as = "String")]
124pub struct Interest(pub(crate) Bytes);
125
126impl Serialize for Interest {
127    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
128    where
129        S: serde::Serializer,
130    {
131        let string = unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) };
132        serializer.serialize_str(string)
133    }
134}
135
136impl<'de> Deserialize<'de> for Interest {
137    fn deserialize<D>(deserializer: D) -> Result<Interest, D::Error>
138    where
139        D: serde::Deserializer<'de>,
140    {
141        let string = String::deserialize(deserializer)?;
142        Ok(Interest(Bytes::from(string)))
143    }
144}
145
146impl Interest {
147    pub fn new<B: Into<Bytes>>(bytes: B) -> Self {
148        Self(bytes.into())
149    }
150    pub fn as_segments(&self) -> impl Iterator<Item = InterestSegment<'_>> + Clone {
151        self.0.split(|c| *c == b'/').filter_map(|seg| {
152            if seg.is_empty() {
153                None
154            } else {
155                Some(match seg.trim_ascii() {
156                    b"*" => InterestSegment::Any,
157                    b"**" => InterestSegment::RecursiveAny,
158                    specific => InterestSegment::Specific(specific),
159                })
160            }
161        })
162    }
163}
164
165pub enum InterestSegment<'a> {
166    Specific(&'a [u8]),
167    Any,
168    RecursiveAny,
169}
170impl InterestSegment<'_> {
171    pub fn to_owned(&self) -> OwnedInterestSegment {
172        match self {
173            InterestSegment::Specific(s) => OwnedInterestSegment::Specific(s.to_vec()),
174            InterestSegment::Any => OwnedInterestSegment::Any,
175            InterestSegment::RecursiveAny => OwnedInterestSegment::RecursiveAny,
176        }
177    }
178}
179pub enum OwnedInterestSegment {
180    Specific(Vec<u8>),
181    Any,
182    RecursiveAny,
183}