1use alloc::{boxed::Box, string::String, vec::Vec};
51use core::{
52 convert::{TryFrom, TryInto},
53 fmt::{Debug, Display},
54 num::NonZeroU32,
55};
56
57use zenoh_result::{bail, zerror, Error, IError, ZResult};
58
59use super::{keyexpr, OwnedKeyExpr};
60
61mod support;
62pub use support::{IKeFormatStorage, Segment};
63use support::{IterativeConstructor, Spec};
64
65#[derive(Clone, Copy, Hash)]
100pub struct KeFormat<'s, Storage: IKeFormatStorage<'s> + 's = Vec<Segment<'s>>> {
101 storage: Storage,
103 suffix: &'s str,
108}
109impl<'s, Storage: IKeFormatStorage<'s>> Debug for KeFormat<'s, Storage> {
110 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111 write!(f, "{self}")
112 }
113}
114impl<'s> KeFormat<'s, Vec<Segment<'s>>> {
115 pub fn new<S: AsRef<str> + ?Sized>(value: &'s S) -> ZResult<Self> {
117 value.as_ref().try_into()
118 }
119 pub fn noalloc_new<const N: usize>(value: &'s str) -> ZResult<KeFormat<'s, [Segment<'s>; N]>> {
126 value.try_into()
127 }
128}
129
130pub mod macro_support {
131 use super::*;
132 #[doc(hidden)]
136 #[derive(Clone, Copy)]
137 pub struct SegmentBuilder {
138 pub segment_start: usize,
139 pub prefix_end: usize,
140 pub spec_start: usize,
141 pub id_end: u16,
142 pub pattern_end: u16,
143 pub spec_end: usize,
144 pub segment_end: usize,
145 }
146
147 #[doc(hidden)]
152 pub unsafe fn specs<'s>(this: &KeFormat<'s, Vec<Segment<'s>>>) -> Vec<SegmentBuilder> {
153 let segments = this.storage.segments();
154 if segments.is_empty() {
155 return Vec::new();
156 }
157 let source_start = segments[0].prefix.as_ptr() as usize;
158 segments
159 .iter()
160 .map(|segment| {
161 let segment_start = segment.prefix.as_ptr() as usize - source_start;
162 let prefix_end = segment_start + segment.prefix.len();
163 let spec_start = segment.spec.spec.as_ptr() as usize - source_start;
164 let spec_end = spec_start + segment.spec.spec.len();
165 let segment_end = spec_end + spec_start - prefix_end - 1;
166 SegmentBuilder {
167 segment_start,
168 prefix_end,
169 spec_start,
170 id_end: segment.spec.id_end,
171 pattern_end: segment.spec.pattern_end,
172 spec_end,
173 segment_end,
174 }
175 })
176 .collect()
177 }
178 #[doc(hidden)]
183 pub const unsafe fn const_new<const N: usize>(
184 source: &'static str,
185 segments: [SegmentBuilder; N],
186 ) -> KeFormat<'static, [Segment<'static>; N]> {
187 const unsafe fn substr(source: &'static str, start: usize, end: usize) -> &'static str {
188 core::str::from_utf8_unchecked(core::slice::from_raw_parts(
189 source.as_ptr().add(start),
190 end - start,
191 ))
192 }
193 let mut storage = [Segment {
194 prefix: "",
195 spec: Spec {
196 spec: "",
197 id_end: 0,
198 pattern_end: 0,
199 },
200 }; N];
201 let mut suffix_start = 0;
202 let mut i = 0;
203 while i < N {
204 let segment = segments[i];
205 let prefix = substr(source, segment.segment_start, segment.prefix_end);
206 let spec = Spec {
207 spec: substr(source, segment.spec_start, segment.spec_end),
208 id_end: segment.id_end,
209 pattern_end: segment.pattern_end,
210 };
211 storage[i] = Segment { prefix, spec };
212 suffix_start = segment.segment_end;
213 i += 1;
214 }
215 let suffix = substr(source, suffix_start, source.len());
216 KeFormat { storage, suffix }
217 }
218}
219impl<'s, Storage: IKeFormatStorage<'s> + 's> KeFormat<'s, Storage> {
220 pub fn formatter(&'s self) -> KeFormatter<'s, Storage> {
222 KeFormatter {
223 format: self,
224 buffer: String::new(),
225 values: Storage::values_storage(&self.storage, |_| None),
226 }
227 }
228}
229impl<'s, Storage: IKeFormatStorage<'s> + 's> TryFrom<&'s String> for KeFormat<'s, Storage> {
230 type Error = Error;
231 fn try_from(value: &'s String) -> Result<Self, Self::Error> {
232 Self::try_from(value.as_str())
233 }
234}
235impl<'s, Storage: IKeFormatStorage<'s> + 's> TryFrom<&'s str> for KeFormat<'s, Storage> {
236 type Error = Error;
237 fn try_from(value: &'s str) -> Result<Self, Self::Error> {
238 let mut storage = Storage::new_constructor();
239 let mut segment_start = 0;
240 let mut i = 0;
241 let bvalue = value.as_bytes();
242 while i < bvalue.len() {
243 if bvalue[i] == b'$' {
244 let prefix_end = i;
245 i += 1;
246 let (terminator, spec_start) = match bvalue[i] {
247 b'{' => ("}", i+ 1),
248 b'*' => {i+= 1; continue;}
249 b'#' if bvalue[i+1] == b'{' => ("}#", i +2),
250 c => bail!("Invalid KeFormat: {value} contains `${}` which is not legal in KEs or formats", c as char)
251 };
252 let spec = &value[spec_start..];
253 let Some(spec_end) = spec.find(terminator) else {
254 bail!("Invalid KeFormat: {value} contains an unterminated spec")
255 };
256 let spec = &spec[..spec_end];
257 let spec = match Spec::try_from(spec) {
258 Ok(spec) => spec,
259 Err(e) => {
260 bail!(e => "Invalid KeFormat: {value} contains an invalid spec: {spec}")
261 }
262 };
263 let segment_end = spec_end + spec_start + terminator.len();
264 if prefix_end != 0 && bvalue[prefix_end - 1] != b'/' {
265 bail!("Invalid KeFormat: a spec in {value} is preceded a non-`/` character")
266 }
267 if !matches!(bvalue.get(segment_end), None | Some(b'/')) {
268 bail!("Invalid KeFormat: a spec in {value} is followed by a non-`/` character")
269 }
270 keyexpr::new(spec.pattern().as_str())?; let prefix = &value[segment_start..prefix_end];
272 if prefix.contains('*') {
273 bail!("Invalid KeFormat: wildcards are only allowed in specs when writing formats")
274 }
275 let segment = Segment { prefix, spec };
276 storage = match Storage::add_segment(storage, segment) {
277 IterativeConstructor::Error(e) => {
278 bail!("Couldn't construct KeFormat because its Storage's add_segment failed: {e}")
279 }
280 s => s,
281 };
282 segment_start = segment_end;
283 } else {
284 i += 1;
285 }
286 }
287 let IterativeConstructor::Complete(storage) = storage else {
288 bail!("Couldn't construct KeFormat because its Storage construction was only partial after adding the last segment.")
289 };
290 let segments = storage.segments();
291 for i in 0..(segments.len() - 1) {
292 if segments[(i + 1)..]
293 .iter()
294 .any(|s| s.spec.id() == segments[i].spec.id())
295 {
296 bail!("Invalid KeFormat: {value} contains duplicated ids")
297 }
298 }
299 let suffix = &value[segment_start..];
300 if suffix.contains('*') {
301 bail!("Invalid KeFormat: wildcards are only allowed in specs when writing formats")
302 }
303 Ok(KeFormat { storage, suffix })
304 }
305}
306
307impl<'s, Storage: IKeFormatStorage<'s> + 's> core::convert::TryFrom<&KeFormat<'s, Storage>>
308 for String
309{
310 type Error = core::fmt::Error;
311 fn try_from(value: &KeFormat<'s, Storage>) -> Result<Self, Self::Error> {
312 use core::fmt::Write;
313 let mut s = String::new();
314 for segment in value.storage.segments() {
315 s += segment.prefix;
316 write!(&mut s, "{}", segment.spec.pattern())?;
317 }
318 s += value.suffix;
319 Ok(s)
320 }
321}
322impl<'s, Storage: IKeFormatStorage<'s> + 's> core::convert::TryFrom<&KeFormat<'s, Storage>>
323 for OwnedKeyExpr
324{
325 type Error = Error;
326 fn try_from(value: &KeFormat<'s, Storage>) -> Result<Self, Self::Error> {
327 let s: String = value
328 .try_into()
329 .map_err(|e| zerror!("failed to write into String: {e}"))?;
330 OwnedKeyExpr::autocanonize(s)
331 }
332}
333
334impl<'s, Storage: IKeFormatStorage<'s> + 's> core::fmt::Display for KeFormat<'s, Storage> {
335 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
336 for segment in self.storage.segments() {
337 write!(f, "{}{}", segment.prefix, segment.spec)?;
338 }
339 write!(f, "{}", self.suffix)
340 }
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq)]
344struct NonMaxU32(NonZeroU32);
345impl NonMaxU32 {
346 fn new(value: u32) -> Option<Self> {
347 NonZeroU32::new(!value).map(NonMaxU32)
348 }
349 fn get(&self) -> u32 {
350 !self.0.get()
351 }
352}
353
354#[derive(Clone)]
356pub struct KeFormatter<'s, Storage: IKeFormatStorage<'s>> {
357 format: &'s KeFormat<'s, Storage>,
358 buffer: String,
359 values: Storage::ValuesStorage<Option<(u32, NonMaxU32)>>,
360}
361
362impl<'s, Storage: IKeFormatStorage<'s>> core::fmt::Debug for KeFormatter<'s, Storage> {
363 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
364 let values = self.values.as_ref();
365 let segments = self.format.storage.segments();
366 for i in 0..values.len() {
367 let Segment { prefix, spec } = segments[i];
368 let value =
369 values[i].map(|(start, end)| &self.buffer[start as usize..end.get() as usize]);
370 let id = spec.id();
371 let pattern = spec.pattern();
372 let sharp = if id.contains('}')
373 || pattern.contains('}')
374 || value.map_or_else(
375 || spec.default().is_some_and(|v| v.contains('}')),
376 |v| v.contains('}'),
377 ) {
378 "#"
379 } else {
380 ""
381 };
382 write!(f, "{prefix}${sharp}{{{id}:{pattern}")?;
383 if let Some(value) = value {
384 write!(f, "={value}")?
385 } else if let Some(default) = spec.default() {
386 write!(f, "#{default}")?
387 };
388 write!(f, "}}{sharp}")?;
389 }
390 write!(f, "{}", self.format.suffix)
391 }
392}
393
394impl<'s, Storage: IKeFormatStorage<'s>> TryFrom<&KeFormatter<'s, Storage>> for OwnedKeyExpr {
395 type Error = Error;
396
397 fn try_from(value: &KeFormatter<'s, Storage>) -> Result<Self, Self::Error> {
398 let values = value.values.as_ref();
399 let segments = value.format.storage.segments();
400 let mut len = value.format.suffix.len();
401 for i in 0..values.len() {
402 len += segments[i].prefix.len()
403 + if let Some((start, end)) = values[i] {
404 (end.get() - start) as usize
405 } else if let Some(default) = segments[i].spec.default() {
406 default.len()
407 } else {
408 bail!("Missing field `{}` in {value:?}", segments[i].spec.id())
409 };
410 }
411 let mut ans = String::with_capacity(len);
412 let mut concatenate = |s: &str| {
413 let skip_slash = matches!(ans.as_bytes().last(), None | Some(b'/'))
414 && s.as_bytes().first() == Some(&b'/');
415 ans += &s[skip_slash as usize..];
416 };
417 for i in 0..values.len() {
418 concatenate(segments[i].prefix);
419 if let Some((start, end)) = values[i] {
420 let end = end.get();
421 concatenate(&value.buffer[start as usize..end as usize])
422 } else if let Some(default) = segments[i].spec.default() {
423 concatenate(default)
424 } else {
425 unsafe { core::hint::unreachable_unchecked() }
426 };
427 }
428 concatenate(value.format.suffix);
429 if ans.ends_with('/') {
430 ans.pop();
431 }
432 OwnedKeyExpr::autocanonize(ans)
433 }
434}
435impl<'s, Storage: IKeFormatStorage<'s>> TryFrom<&mut KeFormatter<'s, Storage>> for OwnedKeyExpr {
436 type Error = Error;
437
438 fn try_from(value: &mut KeFormatter<'s, Storage>) -> Result<Self, Self::Error> {
439 (&*value).try_into()
440 }
441}
442
443#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
444pub enum FormatSetError {
445 InvalidId,
446 PatternNotMatched,
447}
448impl core::fmt::Display for FormatSetError {
449 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
450 write!(f, "{self:?}")
451 }
452}
453impl IError for FormatSetError {}
454impl<'s, Storage: IKeFormatStorage<'s>> KeFormatter<'s, Storage> {
455 pub fn format(&self) -> &KeFormat<'s, Storage> {
457 self.format
458 }
459
460 pub fn clear(&mut self) -> &mut Self {
462 self.buffer.clear();
463 for value in self.values.as_mut() {
464 *value = None
465 }
466 self
467 }
468
469 pub fn build(&self) -> ZResult<OwnedKeyExpr> {
474 self.try_into()
475 }
476 pub fn get(&self, id: &str) -> Option<&str> {
478 let segments = self.format.storage.segments();
479 segments
480 .iter()
481 .position(|s| s.spec.id() == id)
482 .and_then(|i| {
483 self.values.as_ref()[i]
484 .map(|(start, end)| &self.buffer[start as usize..end.get() as usize])
485 })
486 }
487 pub fn set<S: Display>(&mut self, id: &str, value: S) -> Result<&mut Self, FormatSetError> {
494 use core::fmt::Write;
495 let segments = self.format.storage.segments();
496 let Some(i) = segments.iter().position(|s| s.spec.id() == id) else {
497 return Err(FormatSetError::InvalidId);
498 };
499 let values = self.values.as_mut();
500 if let Some((start, end)) = values[i].take() {
501 let end = end.get();
502 let shift = end - start;
503 self.buffer.replace_range(start as usize..end as usize, "");
504 for (s, e) in values.iter_mut().flatten() {
505 if *s < start {
506 continue;
507 }
508 *s -= shift;
509 *e = NonMaxU32::new(e.get() - shift).unwrap()
510 }
511 }
512 let pattern = segments[i].spec.pattern();
513 let start = self.buffer.len();
514 write!(&mut self.buffer, "{value}").unwrap(); let mut set_value = || {
516 let end = self.buffer.len();
517 if start == end {
518 if !pattern.is_double_wild() {
519 return Err(());
520 }
521 } else {
522 let Ok(ke) = keyexpr::new(&self.buffer[start..end]) else {
523 return Err(());
524 };
525 if !pattern.includes(ke) {
526 return Err(());
527 }
528 }
529
530 values[i] = Some((
531 start as u32,
532 NonMaxU32::new(end.try_into().map_err(|_| ())?).ok_or(())?,
533 ));
534 Ok(())
535 };
536 match set_value() {
537 Ok(()) => Ok(self),
538 Err(()) => {
539 self.buffer.truncate(start);
540 Err(FormatSetError::PatternNotMatched)
541 }
542 }
543 }
544}
545
546pub struct OwnedKeFormat<Storage: IKeFormatStorage<'static> + 'static = Vec<Segment<'static>>> {
548 _owner: Box<str>,
549 format: KeFormat<'static, Storage>,
550}
551impl<Storage: IKeFormatStorage<'static> + 'static> core::ops::Deref for OwnedKeFormat<Storage> {
552 type Target = KeFormat<'static, Storage>;
553 fn deref(&self) -> &Self::Target {
554 &self.format
555 }
556}
557impl<Storage: IKeFormatStorage<'static> + 'static> TryFrom<Box<str>> for OwnedKeFormat<Storage> {
558 type Error = <KeFormat<'static, Storage> as TryFrom<&'static str>>::Error;
559 fn try_from(value: Box<str>) -> Result<Self, Self::Error> {
560 let owner = value;
561 let format: KeFormat<'static, Storage> = unsafe {
562 core::mem::transmute::<&str, &'static str>(&owner)
564 }
565 .try_into()?;
566 Ok(Self {
567 _owner: owner,
568 format,
569 })
570 }
571}
572impl<Storage: IKeFormatStorage<'static> + 'static> TryFrom<String> for OwnedKeFormat<Storage> {
573 type Error = <KeFormat<'static, Storage> as TryFrom<&'static str>>::Error;
574 fn try_from(value: String) -> Result<Self, Self::Error> {
575 value.into_boxed_str().try_into()
576 }
577}
578impl<Storage: IKeFormatStorage<'static> + 'static> core::str::FromStr for OwnedKeFormat<Storage> {
579 type Err = <KeFormat<'static, Storage> as TryFrom<&'static str>>::Error;
580 fn from_str(s: &str) -> Result<Self, Self::Err> {
581 Box::<str>::from(s).try_into()
582 }
583}
584impl<'s, S1: IKeFormatStorage<'s> + 's, S2: IKeFormatStorage<'s> + 's> PartialEq<KeFormat<'s, S2>>
585 for KeFormat<'s, S1>
586{
587 fn eq(&self, other: &KeFormat<'s, S2>) -> bool {
588 self.suffix == other.suffix && self.storage.segments() == other.storage.segments()
589 }
590}
591
592#[test]
593fn formatting() {
594 let format = KeFormat::new("a/${a:*}/b/$#{b:**}#/c").unwrap();
595 assert_eq!(format.storage[0].prefix, "a/");
596 assert_eq!(format.storage[0].spec.id(), "a");
597 assert_eq!(format.storage[0].spec.pattern(), "*");
598 assert_eq!(format.storage[1].prefix, "/b/");
599 assert_eq!(format.storage[1].spec.id(), "b");
600 assert_eq!(format.storage[1].spec.pattern(), "**");
601 assert_eq!(format.suffix, "/c");
602 let ke: OwnedKeyExpr = format
603 .formatter()
604 .set("a", 1)
605 .unwrap()
606 .set("b", "hi/there")
607 .unwrap()
608 .try_into()
609 .unwrap();
610 assert_eq!(ke.as_str(), "a/1/b/hi/there/c");
611 let ke: OwnedKeyExpr = format
612 .formatter()
613 .set("a", 1)
614 .unwrap()
615 .set("b", "")
616 .unwrap()
617 .try_into()
618 .unwrap();
619 assert_eq!(ke.as_str(), "a/1/b/c");
620}
621
622mod parsing;
623pub use parsing::{Iter, Parsed};