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
120pub enum IterativeConstructor<Complete, Partial, Error> {
121 Complete(Complete),
122 Partial(Partial),
123 Error(Error),
124}
125pub trait IKeFormatStorage<'s>: Sized {
126 type PartialConstruct;
127 type ConstructionError: core::fmt::Display;
128 fn new_constructor(
129 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
130 fn add_segment(
131 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
132 segment: Segment<'s>,
133 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>;
134 fn segments(&self) -> &[Segment<'s>];
135 fn segments_mut(&mut self) -> &mut [Segment<'s>];
136 fn segment(&self, id: &str) -> Option<&Segment<'s>> {
137 self.segments().iter().find(|s| s.spec.id() == id)
138 }
139 fn segment_mut(&mut self, id: &str) -> Option<&mut Segment<'s>> {
140 self.segments_mut().iter_mut().find(|s| s.spec.id() == id)
141 }
142 type ValuesStorage<T>: AsMut<[T]> + AsRef<[T]>;
143 fn values_storage<T, F: FnMut(usize) -> T>(&self, f: F) -> Self::ValuesStorage<T>;
144}
145
146impl<'s, const N: usize> IKeFormatStorage<'s> for [Segment<'s>; N] {
147 type PartialConstruct = ([core::mem::MaybeUninit<Segment<'s>>; N], u16);
148 type ConstructionError = Error;
149 fn new_constructor(
150 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
151 if N > u16::MAX as usize {
152 IterativeConstructor::Error(
153 zerror!(
154 "[Segments; {N}] unsupported because {N} is too big (max: {}).",
155 u16::MAX
156 )
157 .into(),
158 )
159 } else {
160 IterativeConstructor::Partial(([core::mem::MaybeUninit::uninit(); N], 0))
161 }
162 }
163 fn add_segment(
164 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
165 segment: Segment<'s>,
166 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
167 match constructor {
168 IterativeConstructor::Complete(_) => IterativeConstructor::Error(
169 zerror!("Attempted to add more than {N} segments to [Segment<'s>; {N}]").into(),
170 ),
171 IterativeConstructor::Partial((mut this, n)) => {
172 let mut n = n as usize;
173 this[n] = core::mem::MaybeUninit::new(segment);
174 n += 1;
175 if n == N {
176 IterativeConstructor::Complete(this.map(|e| unsafe { e.assume_init() }))
178 } else {
179 IterativeConstructor::Partial((this, n as u16))
180 }
181 }
182 IterativeConstructor::Error(e) => IterativeConstructor::Error(e),
183 }
184 }
185
186 fn segments(&self) -> &[Segment<'s>] {
187 self
188 }
189 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
190 self
191 }
192
193 type ValuesStorage<T> = [T; N];
194 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
195 let mut values = PartialSlice::new();
196 for i in 0..N {
197 values.push(f(i));
198 }
199 match values.try_into() {
200 Ok(v) => v,
201 Err(_) => unreachable!(),
202 }
203 }
204}
205struct PartialSlice<T, const N: usize> {
206 buffer: [core::mem::MaybeUninit<T>; N],
207 n: u16,
208}
209
210impl<T, const N: usize> PartialSlice<T, N> {
211 fn new() -> Self {
212 Self {
213 buffer: [(); N].map(|_| core::mem::MaybeUninit::uninit()),
214 n: 0,
215 }
216 }
217 fn push(&mut self, value: T) {
218 self.buffer[self.n as usize] = core::mem::MaybeUninit::new(value);
219 self.n += 1;
220 }
221}
222impl<T, const N: usize> TryFrom<PartialSlice<T, N>> for [T; N] {
223 type Error = PartialSlice<T, N>;
224 fn try_from(value: PartialSlice<T, N>) -> Result<Self, Self::Error> {
225 let buffer = unsafe { core::ptr::read(&value.buffer) };
227 if value.n as usize == N {
228 core::mem::forget(value);
229 Ok(buffer.map(|v| unsafe { v.assume_init() }))
231 } else {
232 Err(value)
233 }
234 }
235}
236impl<T, const N: usize> Drop for PartialSlice<T, N> {
237 fn drop(&mut self) {
238 for i in 0..self.n as usize {
239 unsafe { core::mem::MaybeUninit::assume_init_drop(&mut self.buffer[i]) }
241 }
242 }
243}
244
245impl<'s> IKeFormatStorage<'s> for Vec<Segment<'s>> {
246 type PartialConstruct = core::convert::Infallible;
247 type ConstructionError = core::convert::Infallible;
248 fn new_constructor(
249 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
250 IterativeConstructor::Complete(Self::new())
251 }
252 fn add_segment(
253 constructor: IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError>,
254 segment: Segment<'s>,
255 ) -> IterativeConstructor<Self, Self::PartialConstruct, Self::ConstructionError> {
256 #[allow(irrefutable_let_patterns)]
259 let IterativeConstructor::Complete(mut this) = constructor
260 else {
261 unsafe { core::hint::unreachable_unchecked() }
263 };
264 this.push(segment);
265 IterativeConstructor::Complete(this)
266 }
267
268 fn segments(&self) -> &[Segment<'s>] {
269 self
270 }
271 fn segments_mut(&mut self) -> &mut [Segment<'s>] {
272 self
273 }
274
275 type ValuesStorage<T> = Box<[T]>;
276 fn values_storage<T, F: FnMut(usize) -> T>(&self, mut f: F) -> Self::ValuesStorage<T> {
277 let mut ans = Vec::with_capacity(self.len());
278 for i in 0..self.len() {
279 ans.push(f(i))
280 }
281 ans.into()
282 }
283}
284
285pub(crate) fn trim_prefix_slash(target: &str) -> &str {
289 &target[matches!(target.as_bytes().first(), Some(b'/')) as usize..]
290}
291pub(crate) fn trim_suffix_slash(target: &str) -> &str {
292 &target[..(target.len() - matches!(target.as_bytes().last(), Some(b'/')) as usize)]
293}