zenoh_keyexpr/key_expr/format/
support.rs1use alloc::{boxed::Box, vec::Vec};
16use core::convert::{TryFrom, TryInto};
17
18use zenoh_result::{bail, zerror, Error};
19
20use crate::key_expr::keyexpr;
21
22#[derive(Clone, Copy, PartialEq, Eq, Hash)]
23pub(crate) struct Spec<'a> {
24 pub(crate) spec: &'a str,
25 pub(crate) id_end: u16,
26 pub(crate) pattern_end: u16,
27}
28impl<'a> TryFrom<&'a str> for Spec<'a> {
29 type Error = Error;
30 fn try_from(spec: &'a str) -> Result<Self, Self::Error> {
31 let Some(id_end) = spec.find(':') else {
32 bail!("Spec {spec} didn't contain `:`")
33 };
34 let pattern_start = id_end + 1;
35 let pattern_end = spec[pattern_start..].find('#').unwrap_or(u16::MAX as usize);
36 if pattern_start < spec.len() {
37 let Ok(id_end) = id_end.try_into() else {
38 bail!("Spec {spec} contains an id longer than {}", u16::MAX)
39 };
40 if pattern_end > u16::MAX as usize {
41 bail!("Spec {spec} contains a pattern longer than {}", u16::MAX)
42 }
43 Ok(Self {
44 spec,
45 id_end,
46 pattern_end: pattern_end as u16,
47 })
48 } else {
49 bail!("Spec {spec} has an empty pattern")
50 }
51 }
52}
53impl Spec<'_> {
54 pub fn id(&self) -> &str {
55 &self.spec[..self.id_end as usize]
56 }
57 pub fn pattern(&self) -> &keyexpr {
58 unsafe {
60 keyexpr::from_str_unchecked(if self.pattern_end != u16::MAX {
61 &self.spec[(self.id_end + 1) as usize..self.pattern_end as usize]
62 } else {
63 &self.spec[(self.id_end + 1) as usize..]
64 })
65 }
66 }
67 pub fn default(&self) -> Option<&keyexpr> {
68 let pattern_end = self.pattern_end as usize;
69 (self.spec.len() > pattern_end)
70 .then(|| unsafe { keyexpr::from_str_unchecked(&self.spec[(pattern_end + 1)..]) })
72 }
73}
74impl core::fmt::Debug for Spec<'_> {
75 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76 core::fmt::Display::fmt(self, f)
77 }
78}
79impl core::fmt::Display for Spec<'_> {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 let spec = self.spec;
82 if spec.contains('}') {
83 write!(f, "$#{{{spec}}}#")
84 } else {
85 write!(f, "${{{spec}}}")
86 }
87 }
88}
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
90pub struct Segment<'a> {
91 pub(crate) prefix: &'a str,
97 pub(crate) spec: Spec<'a>,
98}
99impl Segment<'_> {
100 pub fn prefix(&self) -> Option<&keyexpr> {
101 match self.prefix {
102 "" | "/" => None,
103 _ => Some(unsafe {
105 keyexpr::from_str_unchecked(trim_suffix_slash(trim_prefix_slash(self.prefix)))
106 }),
107 }
108 }
109 pub fn id(&self) -> &str {
110 self.spec.id()
111 }
112 pub fn pattern(&self) -> &keyexpr {
113 self.spec.pattern()
114 }
115 pub fn default(&self) -> Option<&keyexpr> {
116 self.spec.default()
117 }
118}
119
120#[derive(Debug)]
121pub enum IterativeConstructor<Complete, Partial, Error> {
122 Complete(Complete),
123 Partial(Partial),
124 Error(Error),
125}
126pub trait IKeFormatStorage<'s>: Sized {
127 type PartialConstruct;
128 type ConstructionError: core::fmt::Display;
129 fn new_constructor(
130 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
131 fn add_segment(
132 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
133 segment: Segment<'s>,
134 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
135 fn segments(&self) -> &[Segment<'s>];
136 fn segments_mut(&mut self) -> &mut [Segment<'s>];
137 fn segment(&self, id: &str) -> Option<&Segment<'s>> {
138 self.segments().iter().find(|s| s.spec.id() == id)
139 }
140 fn segment_mut(&mut self, id: &str) -> Option<&mut Segment<'s>> {
141 self.segments_mut().iter_mut().find(|s| s.spec.id() == id)
142 }
143 type ValuesStorage<T>: AsMut<[T]> + AsRef<[T]>;
144 fn values_storage<T, F: FnMut(usize) -> T>(&self, f: F) -> Self::ValuesStorage<T>;
145}
146
147impl<'s, const N: usize> IKeFormatStorage<'s> for [Segment<'s>; N] {
148 type PartialConstruct = ([core::mem::MaybeUninit<Segment<'s>>; N], u16);
149 type ConstructionError = Error;
150 fn new_constructor(
151 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
152 if N > u16::MAX as usize {
153 IterativeConstructor::Error(
154 zerror!(
155 "[Segments; {N}] unsupported because {N} is too big (max: {}).",
156 u16::MAX
157 )
158 .into(),
159 )
160 } else {
161 IterativeConstructor::Partial(([core::mem::MaybeUninit::uninit(); N], 0))
162 }
163 }
164 fn add_segment(
165 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
166 segment: Segment<'s>,
167 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
168 match constructor {
169 IterativeConstructor::Complete(_) => IterativeConstructor::Error(
170 zerror!("Attempted to add more than {N} segments to [Segment<'s>; {N}]").into(),
171 ),
172 IterativeConstructor::Partial((mut this, n)) => {
173 let mut n = n as usize;
174 this[n] = core::mem::MaybeUninit::new(segment);
175 n += 1;
176 if n == N {
177 IterativeConstructor::Complete(this.map(|e| unsafe { e.assume_init() }))
179 } else {
180 IterativeConstructor::Partial((this, n as u16))
181 }
182 }
183 IterativeConstructor::Error(e) => IterativeConstructor::Error(e),
184 }
185 }
186
187 fn segments(&self) -> &[Segment<'s>] {
188 self
189 }
190 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
191 self
192 }
193
194 type ValuesStorage<T> = [T; N];
195 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
196 let mut values = PartialSlice::new();
197 for i in 0..N {
198 values.push(f(i));
199 }
200 match values.try_into() {
201 Ok(v) => v,
202 Err(_) => unreachable!(),
203 }
204 }
205}
206struct PartialSlice<T, const N: usize> {
207 buffer: [core::mem::MaybeUninit<T>; N],
208 n: u16,
209}
210
211impl<T, const N: usize> PartialSlice<T, N> {
212 fn new() -> Self {
213 Self {
214 buffer: [(); N].map(|_| core::mem::MaybeUninit::uninit()),
215 n: 0,
216 }
217 }
218 fn push(&mut self, value: T) {
219 self.buffer[self.n as usize] = core::mem::MaybeUninit::new(value);
220 self.n += 1;
221 }
222}
223impl<T, const N: usize> TryFrom<PartialSlice<T, N>> for [T; N] {
224 type Error = PartialSlice<T, N>;
225 fn try_from(value: PartialSlice<T, N>) -> Result<Self, Self::Error> {
226 let buffer = unsafe { core::ptr::read(&value.buffer) };
228 if value.n as usize == N {
229 core::mem::forget(value);
230 Ok(buffer.map(|v| unsafe { v.assume_init() }))
232 } else {
233 Err(value)
234 }
235 }
236}
237impl<T, const N: usize> Drop for PartialSlice<T, N> {
238 fn drop(&mut self) {
239 for i in 0..self.n as usize {
240 unsafe { core::mem::MaybeUninit::assume_init_drop(&mut self.buffer[i]) }
242 }
243 }
244}
245
246impl<'s> IKeFormatStorage<'s> for Vec<Segment<'s>> {
247 type PartialConstruct = core::convert::Infallible;
248 type ConstructionError = core::convert::Infallible;
249 fn new_constructor(
250 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
251 IterativeConstructor::Complete(Self::new())
252 }
253 fn add_segment(
254 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
255 segment: Segment<'s>,
256 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
257 #[allow(irrefutable_let_patterns)]
260 let IterativeConstructor::Complete(mut this) = constructor
261 else {
262 unsafe { core::hint::unreachable_unchecked() }
264 };
265 this.push(segment);
266 IterativeConstructor::Complete(this)
267 }
268
269 fn segments(&self) -> &[Segment<'s>] {
270 self
271 }
272 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
273 self
274 }
275
276 type ValuesStorage<T> = Box<[T]>;
277 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
278 let mut ans = Vec::with_capacity(self.len());
279 for i in 0..self.len() {
280 ans.push(f(i))
281 }
282 ans.into()
283 }
284}
285
286pub(crate) fn trim_prefix_slash(target: &str) -> &str {
290 &target[matches!(target.as_bytes().first(), Some(b'/')) as usize..]
291}
292pub(crate) fn trim_suffix_slash(target: &str) -> &str {
293 &target[..(target.len() - matches!(target.as_bytes().last(), Some(b'/')) as usize)]
294}