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 {
59 keyexpr::from_str_unchecked(if self.pattern_end != u16::MAX {
60 &self.spec[(self.id_end + 1) as usize..self.pattern_end as usize]
61 } else {
62 &self.spec[(self.id_end + 1) as usize..]
63 })
64 }
65 }
66 pub fn default(&self) -> Option<&keyexpr> {
67 let pattern_end = self.pattern_end as usize;
68 (self.spec.len() > pattern_end)
69 .then(|| unsafe { keyexpr::from_str_unchecked(&self.spec[(pattern_end + 1)..]) })
70 }
71}
72impl core::fmt::Debug for Spec<'_> {
73 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
74 core::fmt::Display::fmt(self, f)
75 }
76}
77impl core::fmt::Display for Spec<'_> {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 let spec = self.spec;
80 if spec.contains('}') {
81 write!(f, "$#{{{spec}}}#")
82 } else {
83 write!(f, "${{{spec}}}")
84 }
85 }
86}
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88pub struct Segment<'a> {
89 pub(crate) prefix: &'a str,
95 pub(crate) spec: Spec<'a>,
96}
97impl Segment<'_> {
98 pub fn prefix(&self) -> Option<&keyexpr> {
99 match self.prefix {
100 "" | "/" => None,
101 _ => Some(unsafe {
102 keyexpr::from_str_unchecked(trim_suffix_slash(trim_prefix_slash(self.prefix)))
103 }),
104 }
105 }
106 pub fn id(&self) -> &str {
107 self.spec.id()
108 }
109 pub fn pattern(&self) -> &keyexpr {
110 self.spec.pattern()
111 }
112 pub fn default(&self) -> Option<&keyexpr> {
113 self.spec.default()
114 }
115}
116
117pub enum IterativeConstructor<Complete, Partial, Error> {
118 Complete(Complete),
119 Partial(Partial),
120 Error(Error),
121}
122pub trait IKeFormatStorage<'s>: Sized {
123 type PartialConstruct;
124 type ConstructionError: core::fmt::Display;
125 fn new_constructor(
126 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
127 fn add_segment(
128 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
129 segment: Segment<'s>,
130 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
131 fn segments(&self) -> &[Segment<'s>];
132 fn segments_mut(&mut self) -> &mut [Segment<'s>];
133 fn segment(&self, id: &str) -> Option<&Segment<'s>> {
134 self.segments().iter().find(|s| s.spec.id() == id)
135 }
136 fn segment_mut(&mut self, id: &str) -> Option<&mut Segment<'s>> {
137 self.segments_mut().iter_mut().find(|s| s.spec.id() == id)
138 }
139 type ValuesStorage<T>: AsMut<[T]> + AsRef<[T]>;
140 fn values_storage<T, F: FnMut(usize) -> T>(&self, f: F) -> Self::ValuesStorage<T>;
141}
142
143impl<'s, const N: usize> IKeFormatStorage<'s> for [Segment<'s>; N] {
144 type PartialConstruct = ([core::mem::MaybeUninit<Segment<'s>>; N], u16);
145 type ConstructionError = Error;
146 fn new_constructor(
147 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
148 if N > u16::MAX as usize {
149 IterativeConstructor::Error(
150 zerror!(
151 "[Segments; {N}] unsupported because {N} is too big (max: {}).",
152 u16::MAX
153 )
154 .into(),
155 )
156 } else {
157 IterativeConstructor::Partial(([core::mem::MaybeUninit::uninit(); N], 0))
158 }
159 }
160 fn add_segment(
161 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
162 segment: Segment<'s>,
163 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
164 match constructor {
165 IterativeConstructor::Complete(_) => IterativeConstructor::Error(
166 zerror!("Attempted to add more than {N} segments to [Segment<'s>; {N}]").into(),
167 ),
168 IterativeConstructor::Partial((mut this, n)) => {
169 let mut n = n as usize;
170 this[n] = core::mem::MaybeUninit::new(segment);
171 n += 1;
172 if n == N {
173 IterativeConstructor::Complete(this.map(|e| unsafe { e.assume_init() }))
174 } else {
175 IterativeConstructor::Partial((this, n as u16))
176 }
177 }
178 IterativeConstructor::Error(e) => IterativeConstructor::Error(e),
179 }
180 }
181
182 fn segments(&self) -> &[Segment<'s>] {
183 self
184 }
185 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
186 self
187 }
188
189 type ValuesStorage<T> = [T; N];
190 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
191 let mut values = PartialSlice::new();
192 for i in 0..N {
193 values.push(f(i));
194 }
195 match values.try_into() {
196 Ok(v) => v,
197 Err(_) => unreachable!(),
198 }
199 }
200}
201struct PartialSlice<T, const N: usize> {
202 buffer: [core::mem::MaybeUninit<T>; N],
203 n: u16,
204}
205
206impl<T, const N: usize> PartialSlice<T, N> {
207 fn new() -> Self {
208 Self {
209 buffer: [(); N].map(|_| core::mem::MaybeUninit::uninit()),
210 n: 0,
211 }
212 }
213 fn push(&mut self, value: T) {
214 self.buffer[self.n as usize] = core::mem::MaybeUninit::new(value);
215 self.n += 1;
216 }
217}
218impl<T, const N: usize> TryFrom<PartialSlice<T, N>> for [T; N] {
219 type Error = PartialSlice<T, N>;
220 fn try_from(value: PartialSlice<T, N>) -> Result<Self, Self::Error> {
221 let buffer = unsafe { core::ptr::read(&value.buffer) };
222 if value.n as usize == N {
223 core::mem::forget(value);
224 Ok(buffer.map(|v| unsafe { v.assume_init() }))
225 } else {
226 Err(value)
227 }
228 }
229}
230impl<T, const N: usize> Drop for PartialSlice<T, N> {
231 fn drop(&mut self) {
232 for i in 0..self.n as usize {
233 unsafe { core::mem::MaybeUninit::assume_init_drop(&mut self.buffer[i]) }
234 }
235 }
236}
237
238impl<'s> IKeFormatStorage<'s> for Vec<Segment<'s>> {
239 type PartialConstruct = core::convert::Infallible;
240 type ConstructionError = core::convert::Infallible;
241 fn new_constructor(
242 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
243 IterativeConstructor::Complete(Self::new())
244 }
245 fn add_segment(
246 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
247 segment: Segment<'s>,
248 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
249 #[allow(irrefutable_let_patterns)]
252 let IterativeConstructor::Complete(mut this) = constructor
253 else {
254 unsafe { core::hint::unreachable_unchecked() }
255 };
256 this.push(segment);
257 IterativeConstructor::Complete(this)
258 }
259
260 fn segments(&self) -> &[Segment<'s>] {
261 self
262 }
263 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
264 self
265 }
266
267 type ValuesStorage<T> = Box<[T]>;
268 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
269 let mut ans = Vec::with_capacity(self.len());
270 for i in 0..self.len() {
271 ans.push(f(i))
272 }
273 ans.into()
274 }
275}
276
277pub(crate) fn trim_prefix_slash(target: &str) -> &str {
281 &target[matches!(target.as_bytes().first(), Some(b'/')) as usize..]
282}
283pub(crate) fn trim_suffix_slash(target: &str) -> &str {
284 &target[..(target.len() - matches!(target.as_bytes().last(), Some(b'/')) as usize)]
285}