1use crate::builtin_interfaces::{Duration, Time};
13use crate::cdr::*;
14use crate::std_msgs::Header;
15
16#[derive(PartialEq, Clone, Copy, Debug)]
19pub struct Date {
20 pub year: u16,
21 pub month: u8,
22 pub day: u8,
23}
24
25impl CdrFixed for Date {
26 const CDR_SIZE: usize = 4; fn read_cdr(cursor: &mut CdrCursor<'_>) -> Result<Self, CdrError> {
28 Ok(Date {
29 year: cursor.read_u16()?,
30 month: cursor.read_u8()?,
31 day: cursor.read_u8()?,
32 })
33 }
34 fn write_cdr(&self, writer: &mut CdrWriter<'_>) {
35 writer.write_u16(self.year);
36 writer.write_u8(self.month);
37 writer.write_u8(self.day);
38 }
39 fn size_cdr(sizer: &mut CdrSizer) {
40 sizer.size_u16();
41 sizer.size_u8();
42 sizer.size_u8();
43 }
44}
45
46pub mod radar_cube_dimension {
49 pub const UNDEFINED: u8 = 0;
50 pub const RANGE: u8 = 1;
51 pub const DOPPLER: u8 = 2;
52 pub const AZIMUTH: u8 = 3;
53 pub const ELEVATION: u8 = 4;
54 pub const RXCHANNEL: u8 = 5;
55 pub const SEQUENCE: u8 = 6;
56}
57
58pub mod model_info {
59 pub const RAW: u8 = 0;
60 pub const INT8: u8 = 1;
61 pub const UINT8: u8 = 2;
62 pub const INT16: u8 = 3;
63 pub const UINT16: u8 = 4;
64 pub const FLOAT16: u8 = 5;
65 pub const INT32: u8 = 6;
66 pub const UINT32: u8 = 7;
67 pub const FLOAT32: u8 = 8;
68 pub const INT64: u8 = 9;
69 pub const UINT64: u8 = 10;
70 pub const FLOAT64: u8 = 11;
71 pub const STRING: u8 = 12;
72}
73
74pub struct Mask<B> {
85 buf: B,
86 offsets: [usize; 2],
87}
88
89impl<B> Mask<B> {
90 #[inline]
92 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Mask<C> {
93 Mask {
94 buf: f(self.buf),
95 offsets: self.offsets,
96 }
97 }
98}
99
100impl<B: AsRef<[u8]>> Mask<B> {
101 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
102 let mut c = CdrCursor::new(buf.as_ref())?;
103 let _ = c.read_u32()?; let _ = c.read_u32()?; let _ = c.read_u32()?; let _ = c.read_string()?; let o0 = c.offset();
108 let _ = c.read_bytes()?; let o1 = c.offset();
110 let _ = c.read_bool()?; Ok(Mask {
112 offsets: [o0, o1],
113 buf,
114 })
115 }
116
117 #[inline]
118 pub fn height(&self) -> u32 {
119 rd_u32(self.buf.as_ref(), CDR_HEADER_SIZE)
120 }
121
122 #[inline]
123 pub fn width(&self) -> u32 {
124 rd_u32(self.buf.as_ref(), CDR_HEADER_SIZE + 4)
125 }
126
127 #[inline]
128 pub fn length(&self) -> u32 {
129 rd_u32(self.buf.as_ref(), CDR_HEADER_SIZE + 8)
130 }
131
132 #[inline]
133 pub fn encoding(&self) -> &str {
134 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 12).0
135 }
136
137 #[inline]
138 pub fn mask_data(&self) -> &[u8] {
139 rd_bytes(self.buf.as_ref(), self.offsets[0]).0
140 }
141
142 #[inline]
143 pub fn boxed(&self) -> bool {
144 rd_bool(self.buf.as_ref(), self.offsets[1])
145 }
146
147 #[inline]
148 pub fn as_cdr(&self) -> &[u8] {
149 self.buf.as_ref()
150 }
151
152 #[inline]
153 pub fn cdr_size(&self) -> usize {
154 self.buf.as_ref().len()
155 }
156
157 pub fn to_cdr(&self) -> Vec<u8> {
158 self.buf.as_ref().to_vec()
159 }
160}
161
162impl Mask<Vec<u8>> {
163 #[deprecated(
164 since = "3.2.0",
165 note = "use Mask::builder() for allocation-free buffer reuse; Mask::new will be removed in 4.0"
166 )]
167 pub fn new(
168 height: u32,
169 width: u32,
170 length: u32,
171 encoding: &str,
172 mask: &[u8],
173 boxed: bool,
174 ) -> Result<Self, CdrError> {
175 let mut sizer = CdrSizer::new();
176 sizer.size_u32(); sizer.size_u32(); sizer.size_u32(); sizer.size_string(encoding);
180 let o0 = sizer.offset();
181 sizer.size_bytes(mask.len());
182 let o1 = sizer.offset();
183 sizer.size_bool();
184
185 let mut buf = vec![0u8; sizer.size()];
186 let mut w = CdrWriter::new(&mut buf)?;
187 w.write_u32(height);
188 w.write_u32(width);
189 w.write_u32(length);
190 w.write_string(encoding);
191 w.write_bytes(mask);
192 w.write_bool(boxed);
193 w.finish()?;
194
195 Ok(Mask {
196 offsets: [o0, o1],
197 buf,
198 })
199 }
200
201 pub fn into_cdr(self) -> Vec<u8> {
202 self.buf
203 }
204
205 pub fn builder<'a>() -> MaskBuilder<'a> {
207 MaskBuilder::new()
208 }
209}
210
211pub struct MaskBuilder<'a> {
219 height: u32,
220 width: u32,
221 length: u32,
222 encoding: std::borrow::Cow<'a, str>,
223 mask: &'a [u8],
224 boxed: bool,
225}
226
227impl<'a> Default for MaskBuilder<'a> {
228 fn default() -> Self {
229 Self {
230 height: 0,
231 width: 0,
232 length: 0,
233 encoding: std::borrow::Cow::Borrowed(""),
234 mask: &[],
235 boxed: false,
236 }
237 }
238}
239
240impl<'a> MaskBuilder<'a> {
241 pub fn new() -> Self {
242 Self::default()
243 }
244
245 pub fn height(&mut self, v: u32) -> &mut Self {
246 self.height = v;
247 self
248 }
249 pub fn width(&mut self, v: u32) -> &mut Self {
250 self.width = v;
251 self
252 }
253 pub fn length(&mut self, v: u32) -> &mut Self {
254 self.length = v;
255 self
256 }
257 pub fn encoding(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
258 self.encoding = s.into();
259 self
260 }
261 pub fn mask(&mut self, m: &'a [u8]) -> &mut Self {
262 self.mask = m;
263 self
264 }
265 pub fn boxed(&mut self, v: bool) -> &mut Self {
266 self.boxed = v;
267 self
268 }
269
270 fn size(&self) -> usize {
271 let mut s = CdrSizer::new();
272 s.size_u32(); s.size_u32(); s.size_u32(); s.size_string(&self.encoding);
276 s.size_bytes(self.mask.len());
277 s.size_bool();
278 s.size()
279 }
280
281 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
282 let mut w = CdrWriter::new(buf)?;
283 w.write_u32(self.height);
284 w.write_u32(self.width);
285 w.write_u32(self.length);
286 w.write_string(&self.encoding);
287 w.write_bytes(self.mask);
288 w.write_bool(self.boxed);
289 w.finish()
290 }
291
292 pub fn build(&self) -> Result<Mask<Vec<u8>>, CdrError> {
293 let mut buf = vec![0u8; self.size()];
294 self.write_into(&mut buf)?;
295 Mask::from_cdr(buf)
296 }
297
298 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
299 buf.resize(self.size(), 0);
300 self.write_into(buf)
301 }
302
303 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
304 let need = self.size();
305 if buf.len() < need {
306 return Err(CdrError::BufferTooShort {
307 need,
308 have: buf.len(),
309 });
310 }
311 self.write_into(&mut buf[..need])?;
312 Ok(need)
313 }
314}
315
316impl Mask<&'static [u8]> {
317 pub(crate) fn from_cdr_as_view(buf: &'static [u8]) -> Result<MaskView<'static>, CdrError> {
329 let mut c = CdrCursor::new(buf)?;
330 scan_mask_element(&mut c)
331 }
332}
333
334impl<B: AsRef<[u8]> + AsMut<[u8]>> Mask<B> {
335 pub fn set_height(&mut self, h: u32) -> Result<(), CdrError> {
336 wr_u32(self.buf.as_mut(), CDR_HEADER_SIZE, h)
337 }
338
339 pub fn set_width(&mut self, w: u32) -> Result<(), CdrError> {
340 wr_u32(self.buf.as_mut(), CDR_HEADER_SIZE + 4, w)
341 }
342
343 pub fn set_length(&mut self, l: u32) -> Result<(), CdrError> {
344 wr_u32(self.buf.as_mut(), CDR_HEADER_SIZE + 8, l)
345 }
346
347 pub fn set_boxed(&mut self, v: bool) -> Result<(), CdrError> {
348 wr_u8(self.buf.as_mut(), self.offsets[1], v as u8)
349 }
350}
351
352#[derive(Copy, Clone, Debug)]
354pub struct MaskView<'a> {
355 pub height: u32,
356 pub width: u32,
357 pub length: u32,
358 pub encoding: &'a str,
359 pub mask: &'a [u8],
360 pub boxed: bool,
361}
362
363pub(crate) fn scan_mask_element<'a>(c: &mut CdrCursor<'a>) -> Result<MaskView<'a>, CdrError> {
364 let height = c.read_u32()?;
365 let width = c.read_u32()?;
366 let length = c.read_u32()?;
367 let encoding = c.read_string()?;
368 let mask = c.read_bytes()?;
369 let boxed = c.read_bool()?;
370 Ok(MaskView {
371 height,
372 width,
373 length,
374 encoding,
375 mask,
376 boxed,
377 })
378}
379
380pub(crate) fn write_mask_element(w: &mut CdrWriter<'_>, m: &MaskView<'_>) {
381 w.write_u32(m.height);
382 w.write_u32(m.width);
383 w.write_u32(m.length);
384 w.write_string(m.encoding);
385 w.write_bytes(m.mask);
386 w.write_bool(m.boxed);
387}
388
389pub(crate) fn size_mask_element(s: &mut CdrSizer, encoding: &str, mask_len: usize) {
390 s.size_u32();
391 s.size_u32();
392 s.size_u32();
393 s.size_string(encoding);
394 s.size_bytes(mask_len);
395 s.size_bool();
396}
397
398#[deprecated(
407 since = "3.1.0",
408 note = "Use CameraFrame / CameraPlane for multi-plane support, colorimetry, \
409 GPU fences, and off-device bridging. DmaBuffer will be removed in 4.0.0."
410)]
411pub struct DmaBuffer<B> {
412 buf: B,
413 offsets: [usize; 1],
414}
415
416#[allow(deprecated)]
417impl<B> DmaBuffer<B> {
418 #[inline]
420 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> DmaBuffer<C> {
421 DmaBuffer {
422 buf: f(self.buf),
423 offsets: self.offsets,
424 }
425 }
426}
427
428#[allow(deprecated)]
432impl<B: AsRef<[u8]>> DmaBuffer<B> {
433 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
434 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
435 let o0 = header.end_offset();
436 let mut c = CdrCursor::resume(buf.as_ref(), o0);
437 for _ in 0..7 {
438 c.read_u32()?;
439 }
440 Ok(DmaBuffer { offsets: [o0], buf })
441 }
442
443 pub fn header(&self) -> Header<&[u8]> {
445 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
446 }
447
448 #[inline]
449 pub fn stamp(&self) -> Time {
450 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
451 }
452
453 #[inline]
454 pub fn frame_id(&self) -> &str {
455 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
456 }
457
458 #[inline]
459 pub fn pid(&self) -> u32 {
460 let p = align(self.offsets[0], 4);
461 rd_u32(self.buf.as_ref(), p)
462 }
463
464 #[inline]
465 pub fn fd(&self) -> i32 {
466 let p = align(self.offsets[0], 4) + 4;
467 rd_i32(self.buf.as_ref(), p)
468 }
469
470 #[inline]
471 pub fn width(&self) -> u32 {
472 let p = align(self.offsets[0], 4) + 8;
473 rd_u32(self.buf.as_ref(), p)
474 }
475
476 #[inline]
477 pub fn height(&self) -> u32 {
478 let p = align(self.offsets[0], 4) + 12;
479 rd_u32(self.buf.as_ref(), p)
480 }
481
482 #[inline]
483 pub fn stride(&self) -> u32 {
484 let p = align(self.offsets[0], 4) + 16;
485 rd_u32(self.buf.as_ref(), p)
486 }
487
488 #[inline]
489 pub fn fourcc(&self) -> u32 {
490 let p = align(self.offsets[0], 4) + 20;
491 rd_u32(self.buf.as_ref(), p)
492 }
493
494 #[inline]
495 pub fn length(&self) -> u32 {
496 let p = align(self.offsets[0], 4) + 24;
497 rd_u32(self.buf.as_ref(), p)
498 }
499
500 #[inline]
501 pub fn as_cdr(&self) -> &[u8] {
502 self.buf.as_ref()
503 }
504
505 pub fn to_cdr(&self) -> Vec<u8> {
506 self.buf.as_ref().to_vec()
507 }
508}
509
510#[allow(deprecated)]
511impl DmaBuffer<Vec<u8>> {
512 pub fn new(
513 stamp: Time,
514 frame_id: &str,
515 pid: u32,
516 fd: i32,
517 width: u32,
518 height: u32,
519 stride: u32,
520 fourcc: u32,
521 length: u32,
522 ) -> Result<Self, CdrError> {
523 let mut sizer = CdrSizer::new();
524 Time::size_cdr(&mut sizer);
525 sizer.size_string(frame_id);
526 let o0 = sizer.offset();
527 for _ in 0..7 {
528 sizer.size_u32();
529 }
530
531 let mut buf = vec![0u8; sizer.size()];
532 let mut w = CdrWriter::new(&mut buf)?;
533 stamp.write_cdr(&mut w);
534 w.write_string(frame_id);
535 w.write_u32(pid);
536 w.write_i32(fd);
537 w.write_u32(width);
538 w.write_u32(height);
539 w.write_u32(stride);
540 w.write_u32(fourcc);
541 w.write_u32(length);
542 w.finish()?;
543
544 Ok(DmaBuffer { offsets: [o0], buf })
545 }
546
547 pub fn into_cdr(self) -> Vec<u8> {
548 self.buf
549 }
550}
551
552pub struct LocalTime<B> {
558 buf: B,
559 offsets: [usize; 1],
560}
561
562impl<B> LocalTime<B> {
563 #[inline]
565 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> LocalTime<C> {
566 LocalTime {
567 buf: f(self.buf),
568 offsets: self.offsets,
569 }
570 }
571}
572
573impl<B: AsRef<[u8]>> LocalTime<B> {
574 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
575 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
576 let o0 = header.end_offset();
577 let mut c = CdrCursor::resume(buf.as_ref(), o0);
578 Date::read_cdr(&mut c)?;
579 Time::read_cdr(&mut c)?;
580 c.read_i16()?; Ok(LocalTime { offsets: [o0], buf })
582 }
583
584 pub fn header(&self) -> Header<&[u8]> {
586 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
587 }
588
589 #[inline]
590 pub fn stamp(&self) -> Time {
591 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
592 }
593
594 #[inline]
595 pub fn frame_id(&self) -> &str {
596 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
597 }
598
599 pub fn date(&self) -> Date {
600 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
601 Date::read_cdr(&mut c).expect("date field validated during from_cdr")
602 }
603
604 pub fn time(&self) -> Time {
605 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
606 Date::read_cdr(&mut c).expect("date field validated during from_cdr");
607 Time::read_cdr(&mut c).expect("time field validated during from_cdr")
608 }
609
610 pub fn timezone(&self) -> i16 {
611 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
612 Date::read_cdr(&mut c).expect("date field validated during from_cdr");
613 Time::read_cdr(&mut c).expect("time field validated during from_cdr");
614 c.read_i16()
615 .expect("timezone field validated during from_cdr")
616 }
617
618 #[inline]
619 pub fn as_cdr(&self) -> &[u8] {
620 self.buf.as_ref()
621 }
622
623 pub fn to_cdr(&self) -> Vec<u8> {
624 self.buf.as_ref().to_vec()
625 }
626}
627
628impl LocalTime<Vec<u8>> {
629 #[deprecated(
630 since = "3.2.0",
631 note = "use LocalTime::builder() for allocation-free buffer reuse; LocalTime::new will be removed in 4.0"
632 )]
633 pub fn new(
634 stamp: Time,
635 frame_id: &str,
636 date: Date,
637 time: Time,
638 timezone: i16,
639 ) -> Result<Self, CdrError> {
640 let mut sizer = CdrSizer::new();
641 Time::size_cdr(&mut sizer);
642 sizer.size_string(frame_id);
643 let o0 = sizer.offset();
644 Date::size_cdr(&mut sizer);
645 Time::size_cdr(&mut sizer);
646 sizer.size_i16();
647
648 let mut buf = vec![0u8; sizer.size()];
649 let mut w = CdrWriter::new(&mut buf)?;
650 stamp.write_cdr(&mut w);
651 w.write_string(frame_id);
652 date.write_cdr(&mut w);
653 time.write_cdr(&mut w);
654 w.write_i16(timezone);
655 w.finish()?;
656
657 Ok(LocalTime { offsets: [o0], buf })
658 }
659
660 pub fn into_cdr(self) -> Vec<u8> {
661 self.buf
662 }
663
664 pub fn builder<'a>() -> LocalTimeBuilder<'a> {
666 LocalTimeBuilder::new()
667 }
668}
669
670pub struct LocalTimeBuilder<'a> {
674 stamp: Time,
675 frame_id: std::borrow::Cow<'a, str>,
676 date: Date,
677 time: Time,
678 timezone: i16,
679}
680
681impl<'a> Default for LocalTimeBuilder<'a> {
682 fn default() -> Self {
683 Self {
684 stamp: Time { sec: 0, nanosec: 0 },
685 frame_id: std::borrow::Cow::Borrowed(""),
686 date: Date {
687 year: 0,
688 month: 0,
689 day: 0,
690 },
691 time: Time { sec: 0, nanosec: 0 },
692 timezone: 0,
693 }
694 }
695}
696
697impl<'a> LocalTimeBuilder<'a> {
698 pub fn new() -> Self {
699 Self::default()
700 }
701
702 pub fn stamp(&mut self, t: Time) -> &mut Self {
703 self.stamp = t;
704 self
705 }
706 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
707 self.frame_id = s.into();
708 self
709 }
710 pub fn date(&mut self, d: Date) -> &mut Self {
711 self.date = d;
712 self
713 }
714 pub fn time(&mut self, t: Time) -> &mut Self {
715 self.time = t;
716 self
717 }
718 pub fn timezone(&mut self, v: i16) -> &mut Self {
719 self.timezone = v;
720 self
721 }
722
723 fn size(&self) -> usize {
724 let mut s = CdrSizer::new();
725 Time::size_cdr(&mut s);
726 s.size_string(&self.frame_id);
727 Date::size_cdr(&mut s);
728 Time::size_cdr(&mut s);
729 s.size_i16();
730 s.size()
731 }
732
733 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
734 let mut w = CdrWriter::new(buf)?;
735 self.stamp.write_cdr(&mut w);
736 w.write_string(&self.frame_id);
737 self.date.write_cdr(&mut w);
738 self.time.write_cdr(&mut w);
739 w.write_i16(self.timezone);
740 w.finish()
741 }
742
743 pub fn build(&self) -> Result<LocalTime<Vec<u8>>, CdrError> {
744 let mut buf = vec![0u8; self.size()];
745 self.write_into(&mut buf)?;
746 LocalTime::from_cdr(buf)
747 }
748
749 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
750 buf.resize(self.size(), 0);
751 self.write_into(buf)
752 }
753
754 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
755 let need = self.size();
756 if buf.len() < need {
757 return Err(CdrError::BufferTooShort {
758 need,
759 have: buf.len(),
760 });
761 }
762 self.write_into(&mut buf[..need])?;
763 Ok(need)
764 }
765}
766
767impl<B: AsRef<[u8]> + AsMut<[u8]>> LocalTime<B> {
768 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
769 let b = self.buf.as_mut();
770 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
771 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
772 }
773
774 pub fn set_date(&mut self, d: Date) -> Result<(), CdrError> {
775 let b = self.buf.as_mut();
776 let p = cdr_align(self.offsets[0], 2);
778 wr_u16(b, p, d.year)?;
779 wr_u8(b, p + 2, d.month)?;
780 wr_u8(b, p + 3, d.day)
781 }
782
783 pub fn set_time(&mut self, t: Time) -> Result<(), CdrError> {
784 let b = self.buf.as_mut();
785 let date_start = cdr_align(self.offsets[0], 2);
788 let time_start = cdr_align(date_start + 4, 4);
789 wr_i32(b, time_start, t.sec)?;
790 wr_u32(b, time_start + 4, t.nanosec)
791 }
792
793 pub fn set_timezone(&mut self, v: i16) -> Result<(), CdrError> {
794 let date_start = cdr_align(self.offsets[0], 2);
796 let time_start = cdr_align(date_start + 4, 4);
797 let tz_pos = cdr_align(time_start + 8, 2);
798 wr_i16(self.buf.as_mut(), tz_pos, v)
799 }
800}
801
802pub struct RadarCube<B> {
810 buf: B,
811 offsets: [usize; 5],
812}
813
814impl<B> RadarCube<B> {
815 #[inline]
817 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> RadarCube<C> {
818 RadarCube {
819 buf: f(self.buf),
820 offsets: self.offsets,
821 }
822 }
823}
824
825impl<B: AsRef<[u8]>> RadarCube<B> {
826 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
827 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
828 let o0 = header.end_offset();
829 let mut c = CdrCursor::resume(buf.as_ref(), o0);
830 c.read_u64()?; let layout_count = c.read_u32()? as usize;
832 c.skip(layout_count)?;
833 let o1 = c.offset();
834 let shape_count = c.read_u32()? as usize;
835 c.skip_seq_2(shape_count)?;
836 let o2 = c.offset();
837 let scales_count = c.read_u32()? as usize;
838 c.skip_seq_4(scales_count)?;
839 let o3 = c.offset();
840 let cube_count = c.read_u32()? as usize;
841 c.skip_seq_2(cube_count)?;
842 let o4 = c.offset();
843 c.read_bool()?;
844 Ok(RadarCube {
845 offsets: [o0, o1, o2, o3, o4],
846 buf,
847 })
848 }
849
850 #[inline]
851 pub fn header(&self) -> Header<&[u8]> {
854 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
855 }
856 #[inline]
857 pub fn stamp(&self) -> Time {
858 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
859 }
860 #[inline]
861 pub fn frame_id(&self) -> &str {
862 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
863 }
864
865 pub fn timestamp(&self) -> u64 {
866 let p = cdr_align(self.offsets[0], 8);
867 rd_u64(self.buf.as_ref(), p)
868 }
869
870 pub fn layout(&self) -> &[u8] {
871 let b = self.buf.as_ref();
872 let p = align(cdr_align(self.offsets[0], 8) + 8, 4);
873 let count = rd_u32(b, p) as usize;
874 &b[p + 4..p + 4 + count]
875 }
876
877 pub fn shape(&self) -> &[u16] {
878 let b = self.buf.as_ref();
879 let p = align(self.offsets[1], 4);
880 let count = rd_u32(b, p) as usize;
881 rd_slice_u16(b, align(p + 4, 2), count)
882 }
883
884 pub fn scales(&self) -> &[f32] {
885 let b = self.buf.as_ref();
886 let p = align(self.offsets[2], 4);
887 let count = rd_u32(b, p) as usize;
888 rd_slice_f32(b, align(p + 4, 4), count)
889 }
890
891 pub fn cube(&self) -> &[i16] {
893 let b = self.buf.as_ref();
894 let p = align(self.offsets[3], 4);
895 let count = rd_u32(b, p) as usize;
896 rd_slice_i16(b, align(p + 4, 2), count)
897 }
898
899 pub fn cube_raw(&self) -> &[u8] {
900 let b = self.buf.as_ref();
901 let p = align(self.offsets[3], 4);
902 let count = rd_u32(b, p) as usize;
903 &b[p + 4..p + 4 + count * 2]
904 }
905
906 pub fn cube_len(&self) -> u32 {
907 rd_u32(self.buf.as_ref(), align(self.offsets[3], 4))
908 }
909
910 pub fn is_complex(&self) -> bool {
911 rd_bool(self.buf.as_ref(), self.offsets[4])
912 }
913
914 #[inline]
915 pub fn as_cdr(&self) -> &[u8] {
916 self.buf.as_ref()
917 }
918 pub fn to_cdr(&self) -> Vec<u8> {
919 self.buf.as_ref().to_vec()
920 }
921}
922
923impl RadarCube<Vec<u8>> {
924 #[deprecated(
925 since = "3.2.0",
926 note = "use RadarCube::builder() for allocation-free buffer reuse; RadarCube::new will be removed in 4.0"
927 )]
928 #[allow(clippy::too_many_arguments)]
929 pub fn new(
930 stamp: Time,
931 frame_id: &str,
932 timestamp: u64,
933 layout: &[u8],
934 shape: &[u16],
935 scales: &[f32],
936 cube: &[i16],
937 is_complex: bool,
938 ) -> Result<Self, CdrError> {
939 let mut sizer = CdrSizer::new();
940 Time::size_cdr(&mut sizer);
941 sizer.size_string(frame_id);
942 let o0 = sizer.offset();
943 sizer.size_u64();
944 sizer.size_bytes(layout.len());
945 let o1 = sizer.offset();
946 sizer.size_u32();
947 sizer.size_seq_2(shape.len());
948 let o2 = sizer.offset();
949 sizer.size_u32();
950 sizer.size_seq_4(scales.len());
951 let o3 = sizer.offset();
952 sizer.size_u32();
953 sizer.size_seq_2(cube.len());
954 let o4 = sizer.offset();
955 sizer.size_bool();
956
957 let mut buf = vec![0u8; sizer.size()];
958 let mut w = CdrWriter::new(&mut buf)?;
959 stamp.write_cdr(&mut w);
960 w.write_string(frame_id);
961 w.write_u64(timestamp);
962 w.write_bytes(layout);
963 w.write_u32(shape.len() as u32);
964 w.write_slice_u16(shape);
965 w.write_u32(scales.len() as u32);
966 w.write_slice_f32(scales);
967 w.write_u32(cube.len() as u32);
968 w.write_slice_i16(cube);
969 w.write_bool(is_complex);
970 w.finish()?;
971
972 Ok(RadarCube {
973 offsets: [o0, o1, o2, o3, o4],
974 buf,
975 })
976 }
977
978 pub fn into_cdr(self) -> Vec<u8> {
979 self.buf
980 }
981
982 pub fn builder<'a>() -> RadarCubeBuilder<'a> {
984 RadarCubeBuilder::new()
985 }
986}
987
988pub struct RadarCubeBuilder<'a> {
996 stamp: Time,
997 frame_id: std::borrow::Cow<'a, str>,
998 timestamp: u64,
999 layout: &'a [u8],
1000 shape: &'a [u16],
1001 scales: &'a [f32],
1002 cube: &'a [i16],
1003 is_complex: bool,
1004}
1005
1006impl<'a> Default for RadarCubeBuilder<'a> {
1007 fn default() -> Self {
1008 Self {
1009 stamp: Time { sec: 0, nanosec: 0 },
1010 frame_id: std::borrow::Cow::Borrowed(""),
1011 timestamp: 0,
1012 layout: &[],
1013 shape: &[],
1014 scales: &[],
1015 cube: &[],
1016 is_complex: false,
1017 }
1018 }
1019}
1020
1021impl<'a> RadarCubeBuilder<'a> {
1022 pub fn new() -> Self {
1023 Self::default()
1024 }
1025
1026 pub fn stamp(&mut self, t: Time) -> &mut Self {
1027 self.stamp = t;
1028 self
1029 }
1030 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1031 self.frame_id = s.into();
1032 self
1033 }
1034 pub fn timestamp(&mut self, v: u64) -> &mut Self {
1035 self.timestamp = v;
1036 self
1037 }
1038 pub fn layout(&mut self, v: &'a [u8]) -> &mut Self {
1039 self.layout = v;
1040 self
1041 }
1042 pub fn shape(&mut self, v: &'a [u16]) -> &mut Self {
1043 self.shape = v;
1044 self
1045 }
1046 pub fn scales(&mut self, v: &'a [f32]) -> &mut Self {
1047 self.scales = v;
1048 self
1049 }
1050 pub fn cube(&mut self, v: &'a [i16]) -> &mut Self {
1051 self.cube = v;
1052 self
1053 }
1054 pub fn is_complex(&mut self, v: bool) -> &mut Self {
1055 self.is_complex = v;
1056 self
1057 }
1058
1059 fn size(&self) -> usize {
1060 let mut s = CdrSizer::new();
1061 Time::size_cdr(&mut s);
1062 s.size_string(&self.frame_id);
1063 s.size_u64();
1064 s.size_bytes(self.layout.len());
1065 s.size_u32();
1066 s.size_seq_2(self.shape.len());
1067 s.size_u32();
1068 s.size_seq_4(self.scales.len());
1069 s.size_u32();
1070 s.size_seq_2(self.cube.len());
1071 s.size_bool();
1072 s.size()
1073 }
1074
1075 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1076 let mut w = CdrWriter::new(buf)?;
1077 self.stamp.write_cdr(&mut w);
1078 w.write_string(&self.frame_id);
1079 w.write_u64(self.timestamp);
1080 w.write_bytes(self.layout);
1081 w.write_u32(self.shape.len() as u32);
1082 w.write_slice_u16(self.shape);
1083 w.write_u32(self.scales.len() as u32);
1084 w.write_slice_f32(self.scales);
1085 w.write_u32(self.cube.len() as u32);
1086 w.write_slice_i16(self.cube);
1087 w.write_bool(self.is_complex);
1088 w.finish()
1089 }
1090
1091 pub fn build(&self) -> Result<RadarCube<Vec<u8>>, CdrError> {
1092 let mut buf = vec![0u8; self.size()];
1093 self.write_into(&mut buf)?;
1094 RadarCube::from_cdr(buf)
1095 }
1096
1097 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1098 buf.resize(self.size(), 0);
1099 self.write_into(buf)
1100 }
1101
1102 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1103 let need = self.size();
1104 if buf.len() < need {
1105 return Err(CdrError::BufferTooShort {
1106 need,
1107 have: buf.len(),
1108 });
1109 }
1110 self.write_into(&mut buf[..need])?;
1111 Ok(need)
1112 }
1113}
1114
1115impl<B: AsRef<[u8]> + AsMut<[u8]>> RadarCube<B> {
1116 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
1117 let b = self.buf.as_mut();
1118 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
1119 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
1120 }
1121
1122 pub fn set_timestamp(&mut self, v: u64) -> Result<(), CdrError> {
1123 let p = cdr_align(self.offsets[0], 8);
1124 wr_u64(self.buf.as_mut(), p, v)
1125 }
1126
1127 pub fn set_is_complex(&mut self, v: bool) -> Result<(), CdrError> {
1128 wr_bool(self.buf.as_mut(), self.offsets[4], v)
1129 }
1130}
1131
1132pub struct RadarInfo<B> {
1140 buf: B,
1141 offsets: [usize; 5],
1142}
1143
1144impl<B> RadarInfo<B> {
1145 #[inline]
1147 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> RadarInfo<C> {
1148 RadarInfo {
1149 buf: f(self.buf),
1150 offsets: self.offsets,
1151 }
1152 }
1153}
1154
1155impl<B: AsRef<[u8]>> RadarInfo<B> {
1156 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1157 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
1158 let o0 = header.end_offset();
1159 let mut c = CdrCursor::resume(buf.as_ref(), o0);
1160 let _ = c.read_string()?;
1161 let o1 = c.offset();
1162 let _ = c.read_string()?;
1163 let o2 = c.offset();
1164 let _ = c.read_string()?;
1165 let o3 = c.offset();
1166 let _ = c.read_string()?;
1167 let o4 = c.offset();
1168 c.read_bool()?;
1169 Ok(RadarInfo {
1170 offsets: [o0, o1, o2, o3, o4],
1171 buf,
1172 })
1173 }
1174
1175 #[inline]
1176 pub fn header(&self) -> Header<&[u8]> {
1179 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
1180 }
1181 #[inline]
1182 pub fn stamp(&self) -> Time {
1183 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
1184 }
1185 #[inline]
1186 pub fn frame_id(&self) -> &str {
1187 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
1188 }
1189 #[inline]
1190 pub fn center_frequency(&self) -> &str {
1191 rd_string(self.buf.as_ref(), self.offsets[0]).0
1192 }
1193 #[inline]
1194 pub fn frequency_sweep(&self) -> &str {
1195 rd_string(self.buf.as_ref(), self.offsets[1]).0
1196 }
1197 #[inline]
1198 pub fn range_toggle(&self) -> &str {
1199 rd_string(self.buf.as_ref(), self.offsets[2]).0
1200 }
1201 #[inline]
1202 pub fn detection_sensitivity(&self) -> &str {
1203 rd_string(self.buf.as_ref(), self.offsets[3]).0
1204 }
1205 #[inline]
1206 pub fn cube(&self) -> bool {
1207 rd_bool(self.buf.as_ref(), self.offsets[4])
1208 }
1209
1210 #[inline]
1211 pub fn as_cdr(&self) -> &[u8] {
1212 self.buf.as_ref()
1213 }
1214 pub fn to_cdr(&self) -> Vec<u8> {
1215 self.buf.as_ref().to_vec()
1216 }
1217}
1218
1219impl RadarInfo<Vec<u8>> {
1220 #[deprecated(
1221 since = "3.2.0",
1222 note = "use RadarInfo::builder() for allocation-free buffer reuse; RadarInfo::new will be removed in 4.0"
1223 )]
1224 pub fn new(
1225 stamp: Time,
1226 frame_id: &str,
1227 center_frequency: &str,
1228 frequency_sweep: &str,
1229 range_toggle: &str,
1230 detection_sensitivity: &str,
1231 cube: bool,
1232 ) -> Result<Self, CdrError> {
1233 let mut sizer = CdrSizer::new();
1234 Time::size_cdr(&mut sizer);
1235 sizer.size_string(frame_id);
1236 let o0 = sizer.offset();
1237 sizer.size_string(center_frequency);
1238 let o1 = sizer.offset();
1239 sizer.size_string(frequency_sweep);
1240 let o2 = sizer.offset();
1241 sizer.size_string(range_toggle);
1242 let o3 = sizer.offset();
1243 sizer.size_string(detection_sensitivity);
1244 let o4 = sizer.offset();
1245 sizer.size_bool();
1246
1247 let mut buf = vec![0u8; sizer.size()];
1248 let mut w = CdrWriter::new(&mut buf)?;
1249 stamp.write_cdr(&mut w);
1250 w.write_string(frame_id);
1251 w.write_string(center_frequency);
1252 w.write_string(frequency_sweep);
1253 w.write_string(range_toggle);
1254 w.write_string(detection_sensitivity);
1255 w.write_bool(cube);
1256 w.finish()?;
1257
1258 Ok(RadarInfo {
1259 offsets: [o0, o1, o2, o3, o4],
1260 buf,
1261 })
1262 }
1263
1264 pub fn into_cdr(self) -> Vec<u8> {
1265 self.buf
1266 }
1267
1268 pub fn builder<'a>() -> RadarInfoBuilder<'a> {
1270 RadarInfoBuilder::new()
1271 }
1272}
1273
1274pub struct RadarInfoBuilder<'a> {
1278 stamp: Time,
1279 frame_id: std::borrow::Cow<'a, str>,
1280 center_frequency: std::borrow::Cow<'a, str>,
1281 frequency_sweep: std::borrow::Cow<'a, str>,
1282 range_toggle: std::borrow::Cow<'a, str>,
1283 detection_sensitivity: std::borrow::Cow<'a, str>,
1284 cube: bool,
1285}
1286
1287impl<'a> Default for RadarInfoBuilder<'a> {
1288 fn default() -> Self {
1289 Self {
1290 stamp: Time { sec: 0, nanosec: 0 },
1291 frame_id: std::borrow::Cow::Borrowed(""),
1292 center_frequency: std::borrow::Cow::Borrowed(""),
1293 frequency_sweep: std::borrow::Cow::Borrowed(""),
1294 range_toggle: std::borrow::Cow::Borrowed(""),
1295 detection_sensitivity: std::borrow::Cow::Borrowed(""),
1296 cube: false,
1297 }
1298 }
1299}
1300
1301impl<'a> RadarInfoBuilder<'a> {
1302 pub fn new() -> Self {
1303 Self::default()
1304 }
1305
1306 pub fn stamp(&mut self, t: Time) -> &mut Self {
1307 self.stamp = t;
1308 self
1309 }
1310 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1311 self.frame_id = s.into();
1312 self
1313 }
1314 pub fn center_frequency(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1315 self.center_frequency = s.into();
1316 self
1317 }
1318 pub fn frequency_sweep(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1319 self.frequency_sweep = s.into();
1320 self
1321 }
1322 pub fn range_toggle(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1323 self.range_toggle = s.into();
1324 self
1325 }
1326 pub fn detection_sensitivity(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1327 self.detection_sensitivity = s.into();
1328 self
1329 }
1330 pub fn cube(&mut self, v: bool) -> &mut Self {
1331 self.cube = v;
1332 self
1333 }
1334
1335 fn size(&self) -> usize {
1336 let mut s = CdrSizer::new();
1337 Time::size_cdr(&mut s);
1338 s.size_string(&self.frame_id);
1339 s.size_string(&self.center_frequency);
1340 s.size_string(&self.frequency_sweep);
1341 s.size_string(&self.range_toggle);
1342 s.size_string(&self.detection_sensitivity);
1343 s.size_bool();
1344 s.size()
1345 }
1346
1347 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1348 let mut w = CdrWriter::new(buf)?;
1349 self.stamp.write_cdr(&mut w);
1350 w.write_string(&self.frame_id);
1351 w.write_string(&self.center_frequency);
1352 w.write_string(&self.frequency_sweep);
1353 w.write_string(&self.range_toggle);
1354 w.write_string(&self.detection_sensitivity);
1355 w.write_bool(self.cube);
1356 w.finish()
1357 }
1358
1359 pub fn build(&self) -> Result<RadarInfo<Vec<u8>>, CdrError> {
1360 let mut buf = vec![0u8; self.size()];
1361 self.write_into(&mut buf)?;
1362 RadarInfo::from_cdr(buf)
1363 }
1364
1365 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1366 buf.resize(self.size(), 0);
1367 self.write_into(buf)
1368 }
1369
1370 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1371 let need = self.size();
1372 if buf.len() < need {
1373 return Err(CdrError::BufferTooShort {
1374 need,
1375 have: buf.len(),
1376 });
1377 }
1378 self.write_into(&mut buf[..need])?;
1379 Ok(need)
1380 }
1381}
1382
1383impl<B: AsRef<[u8]> + AsMut<[u8]>> RadarInfo<B> {
1384 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
1385 let b = self.buf.as_mut();
1386 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
1387 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
1388 }
1389
1390 pub fn set_cube(&mut self, v: bool) -> Result<(), CdrError> {
1391 wr_bool(self.buf.as_mut(), self.offsets[4], v)
1392 }
1393}
1394
1395pub struct Track<B> {
1400 buf: B,
1401 offsets: [usize; 1],
1402}
1403
1404impl<B> Track<B> {
1405 #[inline]
1407 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Track<C> {
1408 Track {
1409 buf: f(self.buf),
1410 offsets: self.offsets,
1411 }
1412 }
1413}
1414
1415impl<B: AsRef<[u8]>> Track<B> {
1416 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1417 let mut c = CdrCursor::new(buf.as_ref())?;
1418 let _ = c.read_string()?;
1419 let o0 = c.offset();
1420 c.read_i32()?;
1421 Time::read_cdr(&mut c)?;
1422 Ok(Track { offsets: [o0], buf })
1423 }
1424
1425 #[inline]
1426 pub fn id(&self) -> &str {
1427 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE).0
1428 }
1429
1430 pub fn lifetime(&self) -> i32 {
1431 rd_i32(self.buf.as_ref(), align(self.offsets[0], 4))
1432 }
1433
1434 pub fn created(&self) -> Time {
1435 rd_time(self.buf.as_ref(), align(self.offsets[0], 4) + 4)
1436 }
1437
1438 #[inline]
1439 pub fn as_cdr(&self) -> &[u8] {
1440 self.buf.as_ref()
1441 }
1442 pub fn to_cdr(&self) -> Vec<u8> {
1443 self.buf.as_ref().to_vec()
1444 }
1445}
1446
1447impl Track<Vec<u8>> {
1448 #[deprecated(
1449 since = "3.2.0",
1450 note = "use Track::builder() for allocation-free buffer reuse; Track::new will be removed in 4.0"
1451 )]
1452 pub fn new(id: &str, lifetime: i32, created: Time) -> Result<Self, CdrError> {
1453 let mut sizer = CdrSizer::new();
1454 sizer.size_string(id);
1455 let o0 = sizer.offset();
1456 sizer.size_i32();
1457 Time::size_cdr(&mut sizer);
1458
1459 let mut buf = vec![0u8; sizer.size()];
1460 let mut w = CdrWriter::new(&mut buf)?;
1461 w.write_string(id);
1462 w.write_i32(lifetime);
1463 created.write_cdr(&mut w);
1464 w.finish()?;
1465
1466 Ok(Track { offsets: [o0], buf })
1467 }
1468
1469 pub fn into_cdr(self) -> Vec<u8> {
1470 self.buf
1471 }
1472
1473 pub fn builder<'a>() -> TrackBuilder<'a> {
1479 TrackBuilder::new()
1480 }
1481}
1482
1483pub struct TrackBuilder<'a> {
1490 id: std::borrow::Cow<'a, str>,
1491 lifetime: i32,
1492 created: Time,
1493}
1494
1495impl<'a> Default for TrackBuilder<'a> {
1496 fn default() -> Self {
1497 Self {
1498 id: std::borrow::Cow::Borrowed(""),
1499 lifetime: 0,
1500 created: Time { sec: 0, nanosec: 0 },
1501 }
1502 }
1503}
1504
1505impl<'a> TrackBuilder<'a> {
1506 pub fn new() -> Self {
1507 Self::default()
1508 }
1509
1510 pub fn id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1511 self.id = s.into();
1512 self
1513 }
1514 pub fn lifetime(&mut self, v: i32) -> &mut Self {
1515 self.lifetime = v;
1516 self
1517 }
1518 pub fn created(&mut self, t: Time) -> &mut Self {
1519 self.created = t;
1520 self
1521 }
1522
1523 fn size(&self) -> usize {
1524 let mut s = CdrSizer::new();
1525 s.size_string(&self.id);
1526 s.size_i32();
1527 Time::size_cdr(&mut s);
1528 s.size()
1529 }
1530
1531 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1532 let mut w = CdrWriter::new(buf)?;
1533 w.write_string(&self.id);
1534 w.write_i32(self.lifetime);
1535 self.created.write_cdr(&mut w);
1536 w.finish()
1537 }
1538
1539 pub fn build(&self) -> Result<Track<Vec<u8>>, CdrError> {
1540 let mut buf = vec![0u8; self.size()];
1541 self.write_into(&mut buf)?;
1542 Track::from_cdr(buf)
1543 }
1544
1545 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1546 buf.resize(self.size(), 0);
1547 self.write_into(buf)
1548 }
1549
1550 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1551 let need = self.size();
1552 if buf.len() < need {
1553 return Err(CdrError::BufferTooShort {
1554 need,
1555 have: buf.len(),
1556 });
1557 }
1558 self.write_into(&mut buf[..need])?;
1559 Ok(need)
1560 }
1561}
1562
1563impl<B: AsRef<[u8]> + AsMut<[u8]>> Track<B> {
1564 pub fn set_lifetime(&mut self, v: i32) -> Result<(), CdrError> {
1565 wr_i32(self.buf.as_mut(), align(self.offsets[0], 4), v)
1566 }
1567
1568 pub fn set_created(&mut self, t: Time) -> Result<(), CdrError> {
1569 let b = self.buf.as_mut();
1570 let p = align(self.offsets[0], 4) + 4;
1571 wr_i32(b, p, t.sec)?;
1572 wr_u32(b, p + 4, t.nanosec)
1573 }
1574}
1575
1576pub struct DetectBox<B> {
1584 buf: B,
1585 offsets: [usize; 2],
1586}
1587
1588impl<B> DetectBox<B> {
1589 #[inline]
1591 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> DetectBox<C> {
1592 DetectBox {
1593 buf: f(self.buf),
1594 offsets: self.offsets,
1595 }
1596 }
1597}
1598
1599#[derive(Copy, Clone, Debug)]
1601pub struct DetectBoxView<'a> {
1602 pub center_x: f32,
1603 pub center_y: f32,
1604 pub width: f32,
1605 pub height: f32,
1606 pub label: &'a str,
1607 pub score: f32,
1608 pub distance: f32,
1609 pub speed: f32,
1610 pub track_id: &'a str,
1611 pub track_lifetime: i32,
1612 pub track_created: Time,
1613}
1614
1615pub(crate) fn scan_box_element<'a>(c: &mut CdrCursor<'a>) -> Result<DetectBoxView<'a>, CdrError> {
1616 let center_x = c.read_f32()?;
1617 let center_y = c.read_f32()?;
1618 let width = c.read_f32()?;
1619 let height = c.read_f32()?;
1620 let label = c.read_string()?;
1621 let score = c.read_f32()?;
1622 let distance = c.read_f32()?;
1623 let speed = c.read_f32()?;
1624 let track_id = c.read_string()?;
1625 let track_lifetime = c.read_i32()?;
1626 let track_created = Time::read_cdr(c)?;
1627 Ok(DetectBoxView {
1628 center_x,
1629 center_y,
1630 width,
1631 height,
1632 label,
1633 score,
1634 distance,
1635 speed,
1636 track_id,
1637 track_lifetime,
1638 track_created,
1639 })
1640}
1641
1642pub(crate) fn write_box_element(w: &mut CdrWriter<'_>, b: &DetectBoxView<'_>) {
1643 w.write_f32(b.center_x);
1644 w.write_f32(b.center_y);
1645 w.write_f32(b.width);
1646 w.write_f32(b.height);
1647 w.write_string(b.label);
1648 w.write_f32(b.score);
1649 w.write_f32(b.distance);
1650 w.write_f32(b.speed);
1651 w.write_string(b.track_id);
1652 w.write_i32(b.track_lifetime);
1653 b.track_created.write_cdr(w);
1654}
1655
1656pub(crate) fn size_box_element(s: &mut CdrSizer, label: &str, track_id: &str) {
1657 s.size_f32();
1658 s.size_f32();
1659 s.size_f32();
1660 s.size_f32(); s.size_string(label);
1662 s.size_f32();
1663 s.size_f32();
1664 s.size_f32(); s.size_string(track_id);
1666 s.size_i32();
1667 Time::size_cdr(s);
1668}
1669
1670impl DetectBox<&'static [u8]> {
1671 pub(crate) fn from_cdr_as_view(buf: &'static [u8]) -> Result<DetectBoxView<'static>, CdrError> {
1684 let mut c = CdrCursor::new(buf)?;
1685 scan_box_element(&mut c)
1686 }
1687}
1688
1689impl<B: AsRef<[u8]>> DetectBox<B> {
1690 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1691 let mut c = CdrCursor::new(buf.as_ref())?;
1692 c.read_f32()?;
1693 c.read_f32()?;
1694 c.read_f32()?;
1695 c.read_f32()?;
1696 let _ = c.read_string()?;
1697 let o0 = c.offset();
1698 c.read_f32()?;
1699 c.read_f32()?;
1700 c.read_f32()?;
1701 let _ = c.read_string()?;
1702 let o1 = c.offset();
1703 c.read_i32()?;
1704 Time::read_cdr(&mut c)?;
1705 Ok(DetectBox {
1706 offsets: [o0, o1],
1707 buf,
1708 })
1709 }
1710
1711 #[inline]
1712 pub fn center_x(&self) -> f32 {
1713 rd_f32(self.buf.as_ref(), CDR_HEADER_SIZE)
1714 }
1715 #[inline]
1716 pub fn center_y(&self) -> f32 {
1717 rd_f32(self.buf.as_ref(), CDR_HEADER_SIZE + 4)
1718 }
1719 #[inline]
1720 pub fn width(&self) -> f32 {
1721 rd_f32(self.buf.as_ref(), CDR_HEADER_SIZE + 8)
1722 }
1723 #[inline]
1724 pub fn height(&self) -> f32 {
1725 rd_f32(self.buf.as_ref(), CDR_HEADER_SIZE + 12)
1726 }
1727
1728 pub fn label(&self) -> &str {
1729 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 16).0
1730 }
1731
1732 pub fn score(&self) -> f32 {
1733 rd_f32(self.buf.as_ref(), align(self.offsets[0], 4))
1734 }
1735 pub fn distance(&self) -> f32 {
1736 rd_f32(self.buf.as_ref(), align(self.offsets[0], 4) + 4)
1737 }
1738 pub fn speed(&self) -> f32 {
1739 rd_f32(self.buf.as_ref(), align(self.offsets[0], 4) + 8)
1740 }
1741
1742 pub fn track_id(&self) -> &str {
1743 rd_string(self.buf.as_ref(), align(self.offsets[0], 4) + 12).0
1744 }
1745
1746 pub fn track_lifetime(&self) -> i32 {
1747 rd_i32(self.buf.as_ref(), align(self.offsets[1], 4))
1748 }
1749
1750 pub fn track_created(&self) -> Time {
1751 rd_time(self.buf.as_ref(), align(self.offsets[1], 4) + 4)
1752 }
1753
1754 #[inline]
1755 pub fn as_cdr(&self) -> &[u8] {
1756 self.buf.as_ref()
1757 }
1758 pub fn to_cdr(&self) -> Vec<u8> {
1759 self.buf.as_ref().to_vec()
1760 }
1761}
1762
1763impl DetectBox<Vec<u8>> {
1764 #[deprecated(
1765 since = "3.2.0",
1766 note = "use DetectBox::builder() for allocation-free buffer reuse; DetectBox::new will be removed in 4.0"
1767 )]
1768 #[allow(clippy::too_many_arguments)]
1769 pub fn new(
1770 center_x: f32,
1771 center_y: f32,
1772 width: f32,
1773 height: f32,
1774 label: &str,
1775 score: f32,
1776 distance: f32,
1777 speed: f32,
1778 track_id: &str,
1779 track_lifetime: i32,
1780 track_created: Time,
1781 ) -> Result<Self, CdrError> {
1782 let mut sizer = CdrSizer::new();
1783 sizer.size_f32();
1784 sizer.size_f32();
1785 sizer.size_f32();
1786 sizer.size_f32();
1787 sizer.size_string(label);
1788 let o0 = sizer.offset();
1789 sizer.size_f32();
1790 sizer.size_f32();
1791 sizer.size_f32();
1792 sizer.size_string(track_id);
1793 let o1 = sizer.offset();
1794 sizer.size_i32();
1795 Time::size_cdr(&mut sizer);
1796
1797 let mut buf = vec![0u8; sizer.size()];
1798 let mut w = CdrWriter::new(&mut buf)?;
1799 w.write_f32(center_x);
1800 w.write_f32(center_y);
1801 w.write_f32(width);
1802 w.write_f32(height);
1803 w.write_string(label);
1804 w.write_f32(score);
1805 w.write_f32(distance);
1806 w.write_f32(speed);
1807 w.write_string(track_id);
1808 w.write_i32(track_lifetime);
1809 track_created.write_cdr(&mut w);
1810 w.finish()?;
1811
1812 Ok(DetectBox {
1813 offsets: [o0, o1],
1814 buf,
1815 })
1816 }
1817
1818 pub fn into_cdr(self) -> Vec<u8> {
1819 self.buf
1820 }
1821
1822 pub fn builder<'a>() -> DetectBoxBuilder<'a> {
1824 DetectBoxBuilder::new()
1825 }
1826}
1827
1828pub struct DetectBoxBuilder<'a> {
1835 center_x: f32,
1836 center_y: f32,
1837 width: f32,
1838 height: f32,
1839 label: std::borrow::Cow<'a, str>,
1840 score: f32,
1841 distance: f32,
1842 speed: f32,
1843 track_id: std::borrow::Cow<'a, str>,
1844 track_lifetime: i32,
1845 track_created: Time,
1846}
1847
1848impl<'a> Default for DetectBoxBuilder<'a> {
1849 fn default() -> Self {
1850 Self {
1851 center_x: 0.0,
1852 center_y: 0.0,
1853 width: 0.0,
1854 height: 0.0,
1855 label: std::borrow::Cow::Borrowed(""),
1856 score: 0.0,
1857 distance: 0.0,
1858 speed: 0.0,
1859 track_id: std::borrow::Cow::Borrowed(""),
1860 track_lifetime: 0,
1861 track_created: Time { sec: 0, nanosec: 0 },
1862 }
1863 }
1864}
1865
1866impl<'a> DetectBoxBuilder<'a> {
1867 pub fn new() -> Self {
1868 Self::default()
1869 }
1870
1871 pub fn center_x(&mut self, v: f32) -> &mut Self {
1872 self.center_x = v;
1873 self
1874 }
1875 pub fn center_y(&mut self, v: f32) -> &mut Self {
1876 self.center_y = v;
1877 self
1878 }
1879 pub fn width(&mut self, v: f32) -> &mut Self {
1880 self.width = v;
1881 self
1882 }
1883 pub fn height(&mut self, v: f32) -> &mut Self {
1884 self.height = v;
1885 self
1886 }
1887 pub fn label(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1888 self.label = s.into();
1889 self
1890 }
1891 pub fn score(&mut self, v: f32) -> &mut Self {
1892 self.score = v;
1893 self
1894 }
1895 pub fn distance(&mut self, v: f32) -> &mut Self {
1896 self.distance = v;
1897 self
1898 }
1899 pub fn speed(&mut self, v: f32) -> &mut Self {
1900 self.speed = v;
1901 self
1902 }
1903 pub fn track_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1904 self.track_id = s.into();
1905 self
1906 }
1907 pub fn track_lifetime(&mut self, v: i32) -> &mut Self {
1908 self.track_lifetime = v;
1909 self
1910 }
1911 pub fn track_created(&mut self, t: Time) -> &mut Self {
1912 self.track_created = t;
1913 self
1914 }
1915
1916 fn size(&self) -> usize {
1917 let mut s = CdrSizer::new();
1918 size_box_element(&mut s, &self.label, &self.track_id);
1919 s.size()
1920 }
1921
1922 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1923 let mut w = CdrWriter::new(buf)?;
1924 let view = DetectBoxView {
1925 center_x: self.center_x,
1926 center_y: self.center_y,
1927 width: self.width,
1928 height: self.height,
1929 label: &self.label,
1930 score: self.score,
1931 distance: self.distance,
1932 speed: self.speed,
1933 track_id: &self.track_id,
1934 track_lifetime: self.track_lifetime,
1935 track_created: self.track_created,
1936 };
1937 write_box_element(&mut w, &view);
1938 w.finish()
1939 }
1940
1941 pub fn build(&self) -> Result<DetectBox<Vec<u8>>, CdrError> {
1942 let mut buf = vec![0u8; self.size()];
1943 self.write_into(&mut buf)?;
1944 DetectBox::from_cdr(buf)
1945 }
1946
1947 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1948 buf.resize(self.size(), 0);
1949 self.write_into(buf)
1950 }
1951
1952 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1953 let need = self.size();
1954 if buf.len() < need {
1955 return Err(CdrError::BufferTooShort {
1956 need,
1957 have: buf.len(),
1958 });
1959 }
1960 self.write_into(&mut buf[..need])?;
1961 Ok(need)
1962 }
1963}
1964
1965impl<B: AsRef<[u8]> + AsMut<[u8]>> DetectBox<B> {
1966 pub fn set_center_x(&mut self, v: f32) -> Result<(), CdrError> {
1967 wr_f32(self.buf.as_mut(), CDR_HEADER_SIZE, v)
1968 }
1969
1970 pub fn set_center_y(&mut self, v: f32) -> Result<(), CdrError> {
1971 wr_f32(self.buf.as_mut(), CDR_HEADER_SIZE + 4, v)
1972 }
1973
1974 pub fn set_width(&mut self, v: f32) -> Result<(), CdrError> {
1975 wr_f32(self.buf.as_mut(), CDR_HEADER_SIZE + 8, v)
1976 }
1977
1978 pub fn set_height(&mut self, v: f32) -> Result<(), CdrError> {
1979 wr_f32(self.buf.as_mut(), CDR_HEADER_SIZE + 12, v)
1980 }
1981
1982 pub fn set_score(&mut self, v: f32) -> Result<(), CdrError> {
1983 wr_f32(self.buf.as_mut(), align(self.offsets[0], 4), v)
1984 }
1985
1986 pub fn set_distance(&mut self, v: f32) -> Result<(), CdrError> {
1987 wr_f32(self.buf.as_mut(), align(self.offsets[0], 4) + 4, v)
1988 }
1989
1990 pub fn set_speed(&mut self, v: f32) -> Result<(), CdrError> {
1991 wr_f32(self.buf.as_mut(), align(self.offsets[0], 4) + 8, v)
1992 }
1993
1994 pub fn set_track_lifetime(&mut self, v: i32) -> Result<(), CdrError> {
1995 wr_i32(self.buf.as_mut(), align(self.offsets[1], 4), v)
1996 }
1997
1998 pub fn set_track_created(&mut self, t: Time) -> Result<(), CdrError> {
1999 let b = self.buf.as_mut();
2000 let p = align(self.offsets[1], 4) + 4;
2001 wr_i32(b, p, t.sec)?;
2002 wr_u32(b, p + 4, t.nanosec)
2003 }
2004}
2005
2006pub struct Detect<B> {
2013 buf: B,
2014 offsets: [usize; 2],
2015}
2016
2017impl<B> Detect<B> {
2018 #[inline]
2020 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Detect<C> {
2021 Detect {
2022 buf: f(self.buf),
2023 offsets: self.offsets,
2024 }
2025 }
2026}
2027
2028impl<B: AsRef<[u8]>> Detect<B> {
2029 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2030 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2031 let o0 = header.end_offset();
2032 let mut c = CdrCursor::resume(buf.as_ref(), o0);
2033 Time::read_cdr(&mut c)?; Time::read_cdr(&mut c)?; Time::read_cdr(&mut c)?; let raw_count = c.read_u32()?;
2037 let count = c.check_seq_count(raw_count, 24)?;
2038 for _ in 0..count {
2039 scan_box_element(&mut c)?;
2040 }
2041 let o1 = c.offset();
2042 Ok(Detect {
2043 offsets: [o0, o1],
2044 buf,
2045 })
2046 }
2047
2048 #[inline]
2049 pub fn header(&self) -> Header<&[u8]> {
2052 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2053 }
2054 #[inline]
2055 pub fn stamp(&self) -> Time {
2056 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2057 }
2058 #[inline]
2059 pub fn frame_id(&self) -> &str {
2060 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2061 }
2062
2063 pub fn input_timestamp(&self) -> Time {
2064 let p = align(self.offsets[0], 4);
2065 rd_time(self.buf.as_ref(), p)
2066 }
2067
2068 pub fn model_time(&self) -> Time {
2069 rd_time(self.buf.as_ref(), align(self.offsets[0], 4) + 8)
2070 }
2071
2072 pub fn output_time(&self) -> Time {
2073 rd_time(self.buf.as_ref(), align(self.offsets[0], 4) + 16)
2074 }
2075
2076 pub fn boxes_len(&self) -> u32 {
2077 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4) + 24)
2078 }
2079
2080 pub fn boxes(&self) -> Vec<DetectBoxView<'_>> {
2081 let b = self.buf.as_ref();
2082 let p = align(self.offsets[0], 4) + 24;
2083 let count = rd_u32(b, p) as usize;
2084 let mut c = CdrCursor::resume(b, p + 4);
2085 (0..count)
2086 .map(|_| scan_box_element(&mut c).expect("box elements validated during from_cdr"))
2087 .collect()
2088 }
2089
2090 #[inline]
2091 pub fn as_cdr(&self) -> &[u8] {
2092 self.buf.as_ref()
2093 }
2094 pub fn to_cdr(&self) -> Vec<u8> {
2095 self.buf.as_ref().to_vec()
2096 }
2097}
2098
2099impl Detect<&'static [u8]> {
2100 pub(crate) fn from_cdr_collect_boxes(
2111 buf: &'static [u8],
2112 ) -> Result<(Self, Vec<DetectBoxView<'static>>), CdrError> {
2113 let header = Header::<&[u8]>::from_cdr(buf)?;
2114 let o0 = header.end_offset();
2115 let mut c = CdrCursor::resume(buf, o0);
2116 Time::read_cdr(&mut c)?; Time::read_cdr(&mut c)?; Time::read_cdr(&mut c)?; let raw_count = c.read_u32()?;
2120 let count = c.check_seq_count(raw_count, 24)?;
2121 let mut box_views = Vec::with_capacity(count);
2122 for _ in 0..count {
2123 box_views.push(scan_box_element(&mut c)?);
2124 }
2125 let o1 = c.offset();
2126 Ok((
2127 Detect {
2128 offsets: [o0, o1],
2129 buf,
2130 },
2131 box_views,
2132 ))
2133 }
2134}
2135
2136impl Detect<Vec<u8>> {
2137 #[deprecated(
2138 since = "3.2.0",
2139 note = "use Detect::builder() for allocation-free buffer reuse; Detect::new will be removed in 4.0"
2140 )]
2141 pub fn new(
2142 stamp: Time,
2143 frame_id: &str,
2144 input_timestamp: Time,
2145 model_time: Time,
2146 output_time: Time,
2147 boxes: &[DetectBoxView<'_>],
2148 ) -> Result<Self, CdrError> {
2149 let mut sizer = CdrSizer::new();
2150 Time::size_cdr(&mut sizer);
2151 sizer.size_string(frame_id);
2152 let o0 = sizer.offset();
2153 Time::size_cdr(&mut sizer);
2154 Time::size_cdr(&mut sizer);
2155 Time::size_cdr(&mut sizer);
2156 sizer.size_u32();
2157 for b in boxes {
2158 size_box_element(&mut sizer, b.label, b.track_id);
2159 }
2160 let o1 = sizer.offset();
2161
2162 let mut buf = vec![0u8; sizer.size()];
2163 let mut w = CdrWriter::new(&mut buf)?;
2164 stamp.write_cdr(&mut w);
2165 w.write_string(frame_id);
2166 input_timestamp.write_cdr(&mut w);
2167 model_time.write_cdr(&mut w);
2168 output_time.write_cdr(&mut w);
2169 w.write_u32(boxes.len() as u32);
2170 for b in boxes {
2171 write_box_element(&mut w, b);
2172 }
2173 w.finish()?;
2174
2175 Ok(Detect {
2176 offsets: [o0, o1],
2177 buf,
2178 })
2179 }
2180
2181 pub fn into_cdr(self) -> Vec<u8> {
2182 self.buf
2183 }
2184
2185 pub fn builder<'a>() -> DetectBuilder<'a> {
2187 DetectBuilder::new()
2188 }
2189}
2190
2191pub struct DetectBuilder<'a> {
2200 stamp: Time,
2201 frame_id: std::borrow::Cow<'a, str>,
2202 input_timestamp: Time,
2203 model_time: Time,
2204 output_time: Time,
2205 boxes: &'a [DetectBoxView<'a>],
2206}
2207
2208impl<'a> Default for DetectBuilder<'a> {
2209 fn default() -> Self {
2210 Self {
2211 stamp: Time { sec: 0, nanosec: 0 },
2212 frame_id: std::borrow::Cow::Borrowed(""),
2213 input_timestamp: Time { sec: 0, nanosec: 0 },
2214 model_time: Time { sec: 0, nanosec: 0 },
2215 output_time: Time { sec: 0, nanosec: 0 },
2216 boxes: &[],
2217 }
2218 }
2219}
2220
2221impl<'a> DetectBuilder<'a> {
2222 pub fn new() -> Self {
2223 Self::default()
2224 }
2225
2226 pub fn stamp(&mut self, t: Time) -> &mut Self {
2227 self.stamp = t;
2228 self
2229 }
2230 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2231 self.frame_id = s.into();
2232 self
2233 }
2234 pub fn input_timestamp(&mut self, t: Time) -> &mut Self {
2235 self.input_timestamp = t;
2236 self
2237 }
2238 pub fn model_time(&mut self, t: Time) -> &mut Self {
2239 self.model_time = t;
2240 self
2241 }
2242 pub fn output_time(&mut self, t: Time) -> &mut Self {
2243 self.output_time = t;
2244 self
2245 }
2246 pub fn boxes(&mut self, b: &'a [DetectBoxView<'a>]) -> &mut Self {
2247 self.boxes = b;
2248 self
2249 }
2250
2251 fn size(&self) -> usize {
2252 let mut s = CdrSizer::new();
2253 Time::size_cdr(&mut s);
2254 s.size_string(&self.frame_id);
2255 Time::size_cdr(&mut s);
2256 Time::size_cdr(&mut s);
2257 Time::size_cdr(&mut s);
2258 s.size_u32();
2259 for b in self.boxes {
2260 size_box_element(&mut s, b.label, b.track_id);
2261 }
2262 s.size()
2263 }
2264
2265 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
2266 let mut w = CdrWriter::new(buf)?;
2267 self.stamp.write_cdr(&mut w);
2268 w.write_string(&self.frame_id);
2269 self.input_timestamp.write_cdr(&mut w);
2270 self.model_time.write_cdr(&mut w);
2271 self.output_time.write_cdr(&mut w);
2272 w.write_u32(self.boxes.len() as u32);
2273 for b in self.boxes {
2274 write_box_element(&mut w, b);
2275 }
2276 w.finish()
2277 }
2278
2279 pub fn build(&self) -> Result<Detect<Vec<u8>>, CdrError> {
2280 let mut buf = vec![0u8; self.size()];
2281 self.write_into(&mut buf)?;
2282 Detect::from_cdr(buf)
2283 }
2284
2285 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
2286 buf.resize(self.size(), 0);
2287 self.write_into(buf)
2288 }
2289
2290 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
2291 let need = self.size();
2292 if buf.len() < need {
2293 return Err(CdrError::BufferTooShort {
2294 need,
2295 have: buf.len(),
2296 });
2297 }
2298 self.write_into(&mut buf[..need])?;
2299 Ok(need)
2300 }
2301}
2302
2303impl<B: AsRef<[u8]> + AsMut<[u8]>> Detect<B> {
2304 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
2305 let b = self.buf.as_mut();
2306 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
2307 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
2308 }
2309
2310 pub fn set_input_timestamp(&mut self, t: Time) -> Result<(), CdrError> {
2311 let b = self.buf.as_mut();
2312 let p = align(self.offsets[0], 4);
2313 wr_i32(b, p, t.sec)?;
2314 wr_u32(b, p + 4, t.nanosec)
2315 }
2316
2317 pub fn set_model_time(&mut self, t: Time) -> Result<(), CdrError> {
2318 let b = self.buf.as_mut();
2319 let p = align(self.offsets[0], 4) + 8;
2320 wr_i32(b, p, t.sec)?;
2321 wr_u32(b, p + 4, t.nanosec)
2322 }
2323
2324 pub fn set_output_time(&mut self, t: Time) -> Result<(), CdrError> {
2325 let b = self.buf.as_mut();
2326 let p = align(self.offsets[0], 4) + 16;
2327 wr_i32(b, p, t.sec)?;
2328 wr_u32(b, p + 4, t.nanosec)
2329 }
2330}
2331
2332#[derive(Copy, Clone, Debug)]
2350pub struct CameraPlaneView<'a> {
2351 pub fd: i32,
2352 pub offset: u32,
2353 pub stride: u32,
2354 pub size: u32,
2355 pub used: u32,
2356 pub data: &'a [u8],
2357}
2358
2359pub(crate) fn scan_plane_element<'a>(
2360 c: &mut CdrCursor<'a>,
2361) -> Result<CameraPlaneView<'a>, CdrError> {
2362 let fd = c.read_i32()?;
2363 let offset = c.read_u32()?;
2364 let stride = c.read_u32()?;
2365 let size = c.read_u32()?;
2366 let used = c.read_u32()?;
2367 let data = c.read_bytes()?;
2368 Ok(CameraPlaneView {
2369 fd,
2370 offset,
2371 stride,
2372 size,
2373 used,
2374 data,
2375 })
2376}
2377
2378pub(crate) fn write_plane_element(w: &mut CdrWriter<'_>, p: &CameraPlaneView<'_>) {
2379 w.write_i32(p.fd);
2380 w.write_u32(p.offset);
2381 w.write_u32(p.stride);
2382 w.write_u32(p.size);
2383 w.write_u32(p.used);
2384 w.write_bytes(p.data);
2385}
2386
2387pub(crate) fn size_plane_element(s: &mut CdrSizer, data_len: usize) {
2388 s.size_i32();
2389 s.size_u32();
2390 s.size_u32();
2391 s.size_u32();
2392 s.size_u32();
2393 s.size_bytes(data_len);
2394}
2395
2396pub(crate) fn validate_plane(
2404 fd: i32,
2405 size: u32,
2406 used: u32,
2407 data_len: usize,
2408) -> Result<(), CdrError> {
2409 if fd < -1
2410 || used > size
2411 || (fd >= 0 && data_len != 0)
2412 || (fd == -1 && size as usize != data_len)
2413 {
2414 return Err(CdrError::InvalidHeader);
2415 }
2416 Ok(())
2417}
2418
2419pub struct CameraFrame<B> {
2451 buf: B,
2452 offsets: [usize; 2],
2458}
2459
2460impl<B> CameraFrame<B> {
2461 #[inline]
2463 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> CameraFrame<C> {
2464 CameraFrame {
2465 buf: f(self.buf),
2466 offsets: self.offsets,
2467 }
2468 }
2469}
2470
2471impl<B: AsRef<[u8]>> CameraFrame<B> {
2472 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2473 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2474 let o0 = header.end_offset();
2475 let mut c = CdrCursor::resume(buf.as_ref(), o0);
2476 c.read_u64()?; c.read_u32()?; let width = c.read_u32()?;
2479 let height = c.read_u32()?;
2480 c.read_string()?; c.read_string()?; c.read_string()?; c.read_string()?; c.read_string()?; c.read_i32()?; let planes_pos = c.offset();
2487 let raw_count = c.read_u32()?;
2488 let count = c.check_seq_count(raw_count, 24)?;
2490 for _ in 0..count {
2491 let plane = scan_plane_element(&mut c)?;
2492 validate_plane(plane.fd, plane.size, plane.used, plane.data.len())?;
2493 }
2494
2495 if width == 0 || height == 0 {
2496 return Err(CdrError::InvalidHeader);
2497 }
2498
2499 Ok(CameraFrame {
2500 offsets: [o0, planes_pos],
2501 buf,
2502 })
2503 }
2504
2505 #[inline]
2506 pub fn header(&self) -> Header<&[u8]> {
2509 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2510 }
2511 #[inline]
2512 pub fn stamp(&self) -> Time {
2513 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2514 }
2515 #[inline]
2516 pub fn frame_id(&self) -> &str {
2517 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2518 }
2519
2520 #[inline]
2521 pub fn seq(&self) -> u64 {
2522 rd_u64(self.buf.as_ref(), cdr_align(self.offsets[0], 8))
2524 }
2525 #[inline]
2526 pub fn pid(&self) -> u32 {
2527 rd_u32(self.buf.as_ref(), cdr_align(self.offsets[0], 8) + 8)
2528 }
2529 #[inline]
2530 pub fn width(&self) -> u32 {
2531 rd_u32(self.buf.as_ref(), cdr_align(self.offsets[0], 8) + 12)
2532 }
2533 #[inline]
2534 pub fn height(&self) -> u32 {
2535 rd_u32(self.buf.as_ref(), cdr_align(self.offsets[0], 8) + 16)
2536 }
2537
2538 fn strings_start(&self) -> usize {
2539 cdr_align(self.offsets[0], 8) + 20
2541 }
2542
2543 fn scan_strings_and_fence(&self) -> (&str, &str, &str, &str, &str, i32) {
2548 let b = self.buf.as_ref();
2549 let (format, p1) = rd_string(b, self.strings_start());
2550 let (cs, p2) = rd_string(b, p1);
2551 let (ct, p3) = rd_string(b, p2);
2552 let (ce, p4) = rd_string(b, p3);
2553 let (cr, p5) = rd_string(b, p4);
2554 let fence_fd = rd_i32(b, align(p5, 4));
2555 (format, cs, ct, ce, cr, fence_fd)
2556 }
2557
2558 #[inline]
2559 pub fn format(&self) -> &str {
2560 self.scan_strings_and_fence().0
2561 }
2562 #[inline]
2563 pub fn color_space(&self) -> &str {
2564 self.scan_strings_and_fence().1
2565 }
2566 #[inline]
2567 pub fn color_transfer(&self) -> &str {
2568 self.scan_strings_and_fence().2
2569 }
2570 #[inline]
2571 pub fn color_encoding(&self) -> &str {
2572 self.scan_strings_and_fence().3
2573 }
2574 #[inline]
2575 pub fn color_range(&self) -> &str {
2576 self.scan_strings_and_fence().4
2577 }
2578 #[inline]
2579 pub fn fence_fd(&self) -> i32 {
2580 self.scan_strings_and_fence().5
2581 }
2582
2583 #[inline]
2585 pub fn num_planes(&self) -> u32 {
2586 rd_u32(self.buf.as_ref(), self.offsets[1])
2587 }
2588
2589 pub fn planes(&self) -> Vec<CameraPlaneView<'_>> {
2592 let b = self.buf.as_ref();
2593 let count = rd_u32(b, self.offsets[1]) as usize;
2594 let mut c = CdrCursor::resume(b, self.offsets[1] + 4);
2595 (0..count)
2596 .map(|_| scan_plane_element(&mut c).expect("planes validated during from_cdr"))
2597 .collect()
2598 }
2599
2600 #[inline]
2601 pub fn as_cdr(&self) -> &[u8] {
2602 self.buf.as_ref()
2603 }
2604 pub fn to_cdr(&self) -> Vec<u8> {
2605 self.buf.as_ref().to_vec()
2606 }
2607}
2608
2609impl CameraFrame<&'static [u8]> {
2610 pub(crate) fn from_cdr_collect_planes(
2613 buf: &'static [u8],
2614 ) -> Result<(Self, Vec<CameraPlaneView<'static>>), CdrError> {
2615 let header = Header::<&[u8]>::from_cdr(buf)?;
2616 let o0 = header.end_offset();
2617 let mut c = CdrCursor::resume(buf, o0);
2618 c.read_u64()?;
2619 c.read_u32()?;
2620 let width = c.read_u32()?;
2621 let height = c.read_u32()?;
2622 c.read_string()?;
2623 c.read_string()?;
2624 c.read_string()?;
2625 c.read_string()?;
2626 c.read_string()?;
2627 c.read_i32()?;
2628 let planes_pos = c.offset();
2629 let raw_count = c.read_u32()?;
2630 let count = c.check_seq_count(raw_count, 24)?;
2631 let mut planes = Vec::with_capacity(count);
2632 for _ in 0..count {
2633 let plane = scan_plane_element(&mut c)?;
2634 validate_plane(plane.fd, plane.size, plane.used, plane.data.len())?;
2635 planes.push(plane);
2636 }
2637
2638 if width == 0 || height == 0 {
2639 return Err(CdrError::InvalidHeader);
2640 }
2641
2642 Ok((
2643 CameraFrame {
2644 offsets: [o0, planes_pos],
2645 buf,
2646 },
2647 planes,
2648 ))
2649 }
2650}
2651
2652impl CameraFrame<Vec<u8>> {
2653 #[deprecated(
2662 since = "3.2.0",
2663 note = "use CameraFrame::builder() for allocation-free buffer reuse; CameraFrame::new will be removed in 4.0"
2664 )]
2665 #[allow(clippy::too_many_arguments)]
2666 pub fn new(
2667 stamp: Time,
2668 frame_id: &str,
2669 seq: u64,
2670 pid: u32,
2671 width: u32,
2672 height: u32,
2673 format: &str,
2674 color_space: &str,
2675 color_transfer: &str,
2676 color_encoding: &str,
2677 color_range: &str,
2678 fence_fd: i32,
2679 planes: &[CameraPlaneView<'_>],
2680 ) -> Result<Self, CdrError> {
2681 if width == 0 || height == 0 {
2682 return Err(CdrError::InvalidHeader);
2683 }
2684 for p in planes {
2685 validate_plane(p.fd, p.size, p.used, p.data.len())?;
2686 }
2687
2688 let mut sizer = CdrSizer::new();
2689 Time::size_cdr(&mut sizer);
2690 sizer.size_string(frame_id);
2691 let o0 = sizer.offset();
2692 sizer.size_u64();
2693 sizer.size_u32();
2694 sizer.size_u32();
2695 sizer.size_u32();
2696 sizer.size_string(format);
2697 sizer.size_string(color_space);
2698 sizer.size_string(color_transfer);
2699 sizer.size_string(color_encoding);
2700 sizer.size_string(color_range);
2701 sizer.size_i32();
2702 let planes_pos = sizer.offset();
2703 sizer.size_u32();
2704 for p in planes {
2705 size_plane_element(&mut sizer, p.data.len());
2706 }
2707
2708 let mut buf = vec![0u8; sizer.size()];
2709 let mut w = CdrWriter::new(&mut buf)?;
2710 stamp.write_cdr(&mut w);
2711 w.write_string(frame_id);
2712 w.write_u64(seq);
2713 w.write_u32(pid);
2714 w.write_u32(width);
2715 w.write_u32(height);
2716 w.write_string(format);
2717 w.write_string(color_space);
2718 w.write_string(color_transfer);
2719 w.write_string(color_encoding);
2720 w.write_string(color_range);
2721 w.write_i32(fence_fd);
2722 w.write_u32(planes.len() as u32);
2723 for p in planes {
2724 write_plane_element(&mut w, p);
2725 }
2726 w.finish()?;
2727
2728 Ok(CameraFrame {
2729 offsets: [o0, planes_pos],
2730 buf,
2731 })
2732 }
2733
2734 pub fn into_cdr(self) -> Vec<u8> {
2735 self.buf
2736 }
2737
2738 pub fn builder<'a>() -> CameraFrameBuilder<'a> {
2744 CameraFrameBuilder::new()
2745 }
2746}
2747
2748pub struct CameraFrameBuilder<'a> {
2757 stamp: Time,
2758 frame_id: std::borrow::Cow<'a, str>,
2759 seq: u64,
2760 pid: u32,
2761 width: u32,
2762 height: u32,
2763 format: std::borrow::Cow<'a, str>,
2764 color_space: std::borrow::Cow<'a, str>,
2765 color_transfer: std::borrow::Cow<'a, str>,
2766 color_encoding: std::borrow::Cow<'a, str>,
2767 color_range: std::borrow::Cow<'a, str>,
2768 fence_fd: i32,
2769 planes: &'a [CameraPlaneView<'a>],
2770}
2771
2772impl<'a> Default for CameraFrameBuilder<'a> {
2773 fn default() -> Self {
2774 Self {
2775 stamp: Time { sec: 0, nanosec: 0 },
2776 frame_id: std::borrow::Cow::Borrowed(""),
2777 seq: 0,
2778 pid: 0,
2779 width: 0,
2780 height: 0,
2781 format: std::borrow::Cow::Borrowed(""),
2782 color_space: std::borrow::Cow::Borrowed(""),
2783 color_transfer: std::borrow::Cow::Borrowed(""),
2784 color_encoding: std::borrow::Cow::Borrowed(""),
2785 color_range: std::borrow::Cow::Borrowed(""),
2786 fence_fd: -1,
2787 planes: &[],
2788 }
2789 }
2790}
2791
2792impl<'a> CameraFrameBuilder<'a> {
2793 pub fn new() -> Self {
2794 Self::default()
2795 }
2796
2797 pub fn stamp(&mut self, t: Time) -> &mut Self {
2798 self.stamp = t;
2799 self
2800 }
2801 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2802 self.frame_id = s.into();
2803 self
2804 }
2805 pub fn seq(&mut self, v: u64) -> &mut Self {
2806 self.seq = v;
2807 self
2808 }
2809 pub fn pid(&mut self, v: u32) -> &mut Self {
2810 self.pid = v;
2811 self
2812 }
2813 pub fn width(&mut self, v: u32) -> &mut Self {
2814 self.width = v;
2815 self
2816 }
2817 pub fn height(&mut self, v: u32) -> &mut Self {
2818 self.height = v;
2819 self
2820 }
2821 pub fn format(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2822 self.format = s.into();
2823 self
2824 }
2825 pub fn color_space(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2826 self.color_space = s.into();
2827 self
2828 }
2829 pub fn color_transfer(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2830 self.color_transfer = s.into();
2831 self
2832 }
2833 pub fn color_encoding(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2834 self.color_encoding = s.into();
2835 self
2836 }
2837 pub fn color_range(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2838 self.color_range = s.into();
2839 self
2840 }
2841 pub fn fence_fd(&mut self, v: i32) -> &mut Self {
2842 self.fence_fd = v;
2843 self
2844 }
2845 pub fn planes(&mut self, p: &'a [CameraPlaneView<'a>]) -> &mut Self {
2846 self.planes = p;
2847 self
2848 }
2849
2850 fn validate(&self) -> Result<(), CdrError> {
2851 if self.width == 0 || self.height == 0 {
2852 return Err(CdrError::InvalidHeader);
2853 }
2854 for p in self.planes {
2855 validate_plane(p.fd, p.size, p.used, p.data.len())?;
2856 }
2857 Ok(())
2858 }
2859
2860 fn size(&self) -> usize {
2861 let mut s = CdrSizer::new();
2862 Time::size_cdr(&mut s);
2863 s.size_string(&self.frame_id);
2864 s.size_u64(); s.size_u32(); s.size_u32(); s.size_u32(); s.size_string(&self.format);
2869 s.size_string(&self.color_space);
2870 s.size_string(&self.color_transfer);
2871 s.size_string(&self.color_encoding);
2872 s.size_string(&self.color_range);
2873 s.size_i32(); s.size_u32(); for p in self.planes {
2876 size_plane_element(&mut s, p.data.len());
2877 }
2878 s.size()
2879 }
2880
2881 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
2882 let mut w = CdrWriter::new(buf)?;
2883 self.stamp.write_cdr(&mut w);
2884 w.write_string(&self.frame_id);
2885 w.write_u64(self.seq);
2886 w.write_u32(self.pid);
2887 w.write_u32(self.width);
2888 w.write_u32(self.height);
2889 w.write_string(&self.format);
2890 w.write_string(&self.color_space);
2891 w.write_string(&self.color_transfer);
2892 w.write_string(&self.color_encoding);
2893 w.write_string(&self.color_range);
2894 w.write_i32(self.fence_fd);
2895 w.write_u32(self.planes.len() as u32);
2896 for p in self.planes {
2897 write_plane_element(&mut w, p);
2898 }
2899 w.finish()
2900 }
2901
2902 pub fn build(&self) -> Result<CameraFrame<Vec<u8>>, CdrError> {
2903 self.validate()?;
2904 let mut buf = vec![0u8; self.size()];
2905 self.write_into(&mut buf)?;
2906 CameraFrame::from_cdr(buf)
2907 }
2908
2909 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
2910 self.validate()?;
2911 buf.resize(self.size(), 0);
2912 self.write_into(buf)
2913 }
2914
2915 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
2916 self.validate()?;
2917 let need = self.size();
2918 if buf.len() < need {
2919 return Err(CdrError::BufferTooShort {
2920 need,
2921 have: buf.len(),
2922 });
2923 }
2924 self.write_into(&mut buf[..need])?;
2925 Ok(need)
2926 }
2927}
2928
2929impl<B: AsRef<[u8]> + AsMut<[u8]>> CameraFrame<B> {
2930 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
2931 let b = self.buf.as_mut();
2932 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
2933 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
2934 }
2935
2936 pub fn set_seq(&mut self, v: u64) -> Result<(), CdrError> {
2937 let p = cdr_align(self.offsets[0], 8);
2938 wr_u64(self.buf.as_mut(), p, v)
2939 }
2940
2941 pub fn set_pid(&mut self, v: u32) -> Result<(), CdrError> {
2942 let p = cdr_align(self.offsets[0], 8) + 8;
2943 wr_u32(self.buf.as_mut(), p, v)
2944 }
2945
2946 pub fn set_width(&mut self, v: u32) -> Result<(), CdrError> {
2947 let p = cdr_align(self.offsets[0], 8) + 12;
2948 wr_u32(self.buf.as_mut(), p, v)
2949 }
2950
2951 pub fn set_height(&mut self, v: u32) -> Result<(), CdrError> {
2952 let p = cdr_align(self.offsets[0], 8) + 16;
2953 wr_u32(self.buf.as_mut(), p, v)
2954 }
2955
2956 pub fn set_fence_fd(&mut self, v: i32) -> Result<(), CdrError> {
2963 let strings_start = cdr_align(self.offsets[0], 8) + 20;
2964 let b = self.buf.as_ref();
2965 let (_, p1) = rd_string(b, strings_start);
2966 let (_, p2) = rd_string(b, p1);
2967 let (_, p3) = rd_string(b, p2);
2968 let (_, p4) = rd_string(b, p3);
2969 let (_, p5) = rd_string(b, p4);
2970 let pos = align(p5, 4);
2971 wr_i32(self.buf.as_mut(), pos, v)
2972 }
2973}
2974
2975pub struct Model<B> {
2983 buf: B,
2984 offsets: [usize; 3],
2985}
2986
2987impl<B> Model<B> {
2988 #[inline]
2990 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Model<C> {
2991 Model {
2992 buf: f(self.buf),
2993 offsets: self.offsets,
2994 }
2995 }
2996}
2997
2998impl<B: AsRef<[u8]>> Model<B> {
2999 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
3000 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
3001 let o0 = header.end_offset();
3002 let mut c = CdrCursor::resume(buf.as_ref(), o0);
3003 Duration::read_cdr(&mut c)?;
3004 Duration::read_cdr(&mut c)?;
3005 Duration::read_cdr(&mut c)?;
3006 Duration::read_cdr(&mut c)?;
3007 let raw_boxes = c.read_u32()?;
3008 let boxes_count = c.check_seq_count(raw_boxes, 24)?;
3009 for _ in 0..boxes_count {
3010 scan_box_element(&mut c)?;
3011 }
3012 let o1 = c.offset();
3013 let raw_masks = c.read_u32()?;
3014 let masks_count = c.check_seq_count(raw_masks, 13)?;
3015 for _ in 0..masks_count {
3016 scan_mask_element(&mut c)?;
3017 }
3018 let o2 = c.offset();
3019 Ok(Model {
3020 offsets: [o0, o1, o2],
3021 buf,
3022 })
3023 }
3024
3025 #[inline]
3026 pub fn header(&self) -> Header<&[u8]> {
3029 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
3030 }
3031 #[inline]
3032 pub fn stamp(&self) -> Time {
3033 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
3034 }
3035 #[inline]
3036 pub fn frame_id(&self) -> &str {
3037 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
3038 }
3039
3040 pub fn input_time(&self) -> Duration {
3041 rd_duration(self.buf.as_ref(), align(self.offsets[0], 4))
3042 }
3043
3044 pub fn model_time(&self) -> Duration {
3045 rd_duration(self.buf.as_ref(), align(self.offsets[0], 4) + 8)
3046 }
3047
3048 pub fn output_time(&self) -> Duration {
3049 rd_duration(self.buf.as_ref(), align(self.offsets[0], 4) + 16)
3050 }
3051
3052 pub fn decode_time(&self) -> Duration {
3053 rd_duration(self.buf.as_ref(), align(self.offsets[0], 4) + 24)
3054 }
3055
3056 pub fn boxes_len(&self) -> u32 {
3057 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4) + 32)
3058 }
3059
3060 pub fn boxes(&self) -> Vec<DetectBoxView<'_>> {
3061 let b = self.buf.as_ref();
3062 let p = align(self.offsets[0], 4) + 32;
3063 let count = rd_u32(b, p) as usize;
3064 let mut c = CdrCursor::resume(b, p + 4);
3065 (0..count)
3066 .map(|_| scan_box_element(&mut c).expect("box elements validated during from_cdr"))
3067 .collect()
3068 }
3069
3070 pub fn masks_len(&self) -> u32 {
3071 rd_u32(self.buf.as_ref(), align(self.offsets[1], 4))
3072 }
3073
3074 pub fn masks(&self) -> Vec<MaskView<'_>> {
3075 let b = self.buf.as_ref();
3076 let p = align(self.offsets[1], 4);
3077 let count = rd_u32(b, p) as usize;
3078 let mut c = CdrCursor::resume(b, p + 4);
3079 (0..count)
3080 .map(|_| scan_mask_element(&mut c).expect("mask elements validated during from_cdr"))
3081 .collect()
3082 }
3083
3084 #[inline]
3085 pub fn as_cdr(&self) -> &[u8] {
3086 self.buf.as_ref()
3087 }
3088 pub fn to_cdr(&self) -> Vec<u8> {
3089 self.buf.as_ref().to_vec()
3090 }
3091}
3092
3093impl Model<&'static [u8]> {
3094 pub(crate) fn from_cdr_collect_children(
3106 buf: &'static [u8],
3107 ) -> Result<(Self, Vec<DetectBoxView<'static>>, Vec<MaskView<'static>>), CdrError> {
3108 let header = Header::<&[u8]>::from_cdr(buf)?;
3109 let o0 = header.end_offset();
3110 let mut c = CdrCursor::resume(buf, o0);
3111 Duration::read_cdr(&mut c)?;
3112 Duration::read_cdr(&mut c)?;
3113 Duration::read_cdr(&mut c)?;
3114 Duration::read_cdr(&mut c)?;
3115 let raw_boxes = c.read_u32()?;
3116 let boxes_count = c.check_seq_count(raw_boxes, 24)?;
3117 let mut box_views = Vec::with_capacity(boxes_count);
3118 for _ in 0..boxes_count {
3119 box_views.push(scan_box_element(&mut c)?);
3120 }
3121 let o1 = c.offset();
3122 let raw_masks = c.read_u32()?;
3123 let masks_count = c.check_seq_count(raw_masks, 13)?;
3124 let mut mask_views = Vec::with_capacity(masks_count);
3125 for _ in 0..masks_count {
3126 mask_views.push(scan_mask_element(&mut c)?);
3127 }
3128 let o2 = c.offset();
3129 Ok((
3130 Model {
3131 offsets: [o0, o1, o2],
3132 buf,
3133 },
3134 box_views,
3135 mask_views,
3136 ))
3137 }
3138}
3139
3140impl Model<Vec<u8>> {
3141 #[deprecated(
3142 since = "3.2.0",
3143 note = "use Model::builder() for allocation-free buffer reuse; Model::new will be removed in 4.0"
3144 )]
3145 #[allow(clippy::too_many_arguments)]
3146 pub fn new(
3147 stamp: Time,
3148 frame_id: &str,
3149 input_time: Duration,
3150 model_time: Duration,
3151 output_time: Duration,
3152 decode_time: Duration,
3153 boxes: &[DetectBoxView<'_>],
3154 masks: &[MaskView<'_>],
3155 ) -> Result<Self, CdrError> {
3156 let mut sizer = CdrSizer::new();
3157 Time::size_cdr(&mut sizer);
3158 sizer.size_string(frame_id);
3159 let o0 = sizer.offset();
3160 Duration::size_cdr(&mut sizer);
3161 Duration::size_cdr(&mut sizer);
3162 Duration::size_cdr(&mut sizer);
3163 Duration::size_cdr(&mut sizer);
3164 sizer.size_u32();
3165 for b in boxes {
3166 size_box_element(&mut sizer, b.label, b.track_id);
3167 }
3168 let o1 = sizer.offset();
3169 sizer.size_u32();
3170 for m in masks {
3171 size_mask_element(&mut sizer, m.encoding, m.mask.len());
3172 }
3173 let o2 = sizer.offset();
3174
3175 let mut buf = vec![0u8; sizer.size()];
3176 let mut w = CdrWriter::new(&mut buf)?;
3177 stamp.write_cdr(&mut w);
3178 w.write_string(frame_id);
3179 input_time.write_cdr(&mut w);
3180 model_time.write_cdr(&mut w);
3181 output_time.write_cdr(&mut w);
3182 decode_time.write_cdr(&mut w);
3183 w.write_u32(boxes.len() as u32);
3184 for b in boxes {
3185 write_box_element(&mut w, b);
3186 }
3187 w.write_u32(masks.len() as u32);
3188 for m in masks {
3189 write_mask_element(&mut w, m);
3190 }
3191 w.finish()?;
3192
3193 Ok(Model {
3194 offsets: [o0, o1, o2],
3195 buf,
3196 })
3197 }
3198
3199 pub fn into_cdr(self) -> Vec<u8> {
3200 self.buf
3201 }
3202
3203 pub fn builder<'a>() -> ModelBuilder<'a> {
3205 ModelBuilder::new()
3206 }
3207}
3208
3209pub struct ModelBuilder<'a> {
3218 stamp: Time,
3219 frame_id: std::borrow::Cow<'a, str>,
3220 input_time: Duration,
3221 model_time: Duration,
3222 output_time: Duration,
3223 decode_time: Duration,
3224 boxes: &'a [DetectBoxView<'a>],
3225 masks: &'a [MaskView<'a>],
3226}
3227
3228impl<'a> Default for ModelBuilder<'a> {
3229 fn default() -> Self {
3230 Self {
3231 stamp: Time { sec: 0, nanosec: 0 },
3232 frame_id: std::borrow::Cow::Borrowed(""),
3233 input_time: Duration { sec: 0, nanosec: 0 },
3234 model_time: Duration { sec: 0, nanosec: 0 },
3235 output_time: Duration { sec: 0, nanosec: 0 },
3236 decode_time: Duration { sec: 0, nanosec: 0 },
3237 boxes: &[],
3238 masks: &[],
3239 }
3240 }
3241}
3242
3243impl<'a> ModelBuilder<'a> {
3244 pub fn new() -> Self {
3245 Self::default()
3246 }
3247
3248 pub fn stamp(&mut self, t: Time) -> &mut Self {
3249 self.stamp = t;
3250 self
3251 }
3252 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3253 self.frame_id = s.into();
3254 self
3255 }
3256 pub fn input_time(&mut self, d: Duration) -> &mut Self {
3257 self.input_time = d;
3258 self
3259 }
3260 pub fn model_time(&mut self, d: Duration) -> &mut Self {
3261 self.model_time = d;
3262 self
3263 }
3264 pub fn output_time(&mut self, d: Duration) -> &mut Self {
3265 self.output_time = d;
3266 self
3267 }
3268 pub fn decode_time(&mut self, d: Duration) -> &mut Self {
3269 self.decode_time = d;
3270 self
3271 }
3272 pub fn boxes(&mut self, b: &'a [DetectBoxView<'a>]) -> &mut Self {
3273 self.boxes = b;
3274 self
3275 }
3276 pub fn masks(&mut self, m: &'a [MaskView<'a>]) -> &mut Self {
3277 self.masks = m;
3278 self
3279 }
3280
3281 fn size(&self) -> usize {
3282 let mut s = CdrSizer::new();
3283 Time::size_cdr(&mut s);
3284 s.size_string(&self.frame_id);
3285 Duration::size_cdr(&mut s);
3286 Duration::size_cdr(&mut s);
3287 Duration::size_cdr(&mut s);
3288 Duration::size_cdr(&mut s);
3289 s.size_u32();
3290 for b in self.boxes {
3291 size_box_element(&mut s, b.label, b.track_id);
3292 }
3293 s.size_u32();
3294 for m in self.masks {
3295 size_mask_element(&mut s, m.encoding, m.mask.len());
3296 }
3297 s.size()
3298 }
3299
3300 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
3301 let mut w = CdrWriter::new(buf)?;
3302 self.stamp.write_cdr(&mut w);
3303 w.write_string(&self.frame_id);
3304 self.input_time.write_cdr(&mut w);
3305 self.model_time.write_cdr(&mut w);
3306 self.output_time.write_cdr(&mut w);
3307 self.decode_time.write_cdr(&mut w);
3308 w.write_u32(self.boxes.len() as u32);
3309 for b in self.boxes {
3310 write_box_element(&mut w, b);
3311 }
3312 w.write_u32(self.masks.len() as u32);
3313 for m in self.masks {
3314 write_mask_element(&mut w, m);
3315 }
3316 w.finish()
3317 }
3318
3319 pub fn build(&self) -> Result<Model<Vec<u8>>, CdrError> {
3320 let mut buf = vec![0u8; self.size()];
3321 self.write_into(&mut buf)?;
3322 Model::from_cdr(buf)
3323 }
3324
3325 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
3326 buf.resize(self.size(), 0);
3327 self.write_into(buf)
3328 }
3329
3330 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
3331 let need = self.size();
3332 if buf.len() < need {
3333 return Err(CdrError::BufferTooShort {
3334 need,
3335 have: buf.len(),
3336 });
3337 }
3338 self.write_into(&mut buf[..need])?;
3339 Ok(need)
3340 }
3341}
3342
3343impl<B: AsRef<[u8]> + AsMut<[u8]>> Model<B> {
3344 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
3345 let b = self.buf.as_mut();
3346 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
3347 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
3348 }
3349
3350 pub fn set_input_time(&mut self, d: Duration) -> Result<(), CdrError> {
3351 let b = self.buf.as_mut();
3352 let p = align(self.offsets[0], 4);
3353 wr_i32(b, p, d.sec)?;
3354 wr_u32(b, p + 4, d.nanosec)
3355 }
3356
3357 pub fn set_model_time(&mut self, d: Duration) -> Result<(), CdrError> {
3358 let b = self.buf.as_mut();
3359 let p = align(self.offsets[0], 4) + 8;
3360 wr_i32(b, p, d.sec)?;
3361 wr_u32(b, p + 4, d.nanosec)
3362 }
3363
3364 pub fn set_output_time(&mut self, d: Duration) -> Result<(), CdrError> {
3365 let b = self.buf.as_mut();
3366 let p = align(self.offsets[0], 4) + 16;
3367 wr_i32(b, p, d.sec)?;
3368 wr_u32(b, p + 4, d.nanosec)
3369 }
3370
3371 pub fn set_decode_time(&mut self, d: Duration) -> Result<(), CdrError> {
3372 let b = self.buf.as_mut();
3373 let p = align(self.offsets[0], 4) + 24;
3374 wr_i32(b, p, d.sec)?;
3375 wr_u32(b, p + 4, d.nanosec)
3376 }
3377}
3378
3379pub struct ModelInfo<B> {
3389 buf: B,
3390 offsets: [usize; 6],
3391}
3392
3393impl<B> ModelInfo<B> {
3394 #[inline]
3396 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> ModelInfo<C> {
3397 ModelInfo {
3398 buf: f(self.buf),
3399 offsets: self.offsets,
3400 }
3401 }
3402}
3403
3404impl<B: AsRef<[u8]>> ModelInfo<B> {
3405 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
3406 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
3407 let o0 = header.end_offset();
3408 let mut c = CdrCursor::resume(buf.as_ref(), o0);
3409 let is_count = c.read_u32()? as usize;
3410 c.skip_seq_4(is_count)?;
3411 let o1 = c.offset();
3412 c.read_u8()?; let os_count = c.read_u32()? as usize;
3414 c.skip_seq_4(os_count)?;
3415 let o2 = c.offset();
3416 c.read_u8()?; let raw_lab = c.read_u32()?;
3418 let lab_count = c.check_seq_count(raw_lab, 5)?;
3419 for _ in 0..lab_count {
3420 c.read_string()?;
3421 }
3422 let o3 = c.offset();
3423 let _ = c.read_string()?;
3424 let o4 = c.offset();
3425 let _ = c.read_string()?;
3426 let o5 = c.offset();
3427 let _ = c.read_string()?;
3428 Ok(ModelInfo {
3429 offsets: [o0, o1, o2, o3, o4, o5],
3430 buf,
3431 })
3432 }
3433
3434 #[inline]
3435 pub fn header(&self) -> Header<&[u8]> {
3438 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
3439 }
3440 #[inline]
3441 pub fn stamp(&self) -> Time {
3442 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
3443 }
3444 #[inline]
3445 pub fn frame_id(&self) -> &str {
3446 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
3447 }
3448
3449 pub fn input_shape(&self) -> &[u32] {
3450 let b = self.buf.as_ref();
3451 let p = align(self.offsets[0], 4);
3452 let count = rd_u32(b, p) as usize;
3453 rd_slice_u32(b, p + 4, count)
3454 }
3455
3456 pub fn input_type(&self) -> u8 {
3457 rd_u8(self.buf.as_ref(), self.offsets[1])
3458 }
3459
3460 pub fn output_shape(&self) -> &[u32] {
3461 let b = self.buf.as_ref();
3462 let p = align(self.offsets[1] + 1, 4);
3463 let count = rd_u32(b, p) as usize;
3464 rd_slice_u32(b, p + 4, count)
3465 }
3466
3467 pub fn output_type(&self) -> u8 {
3468 rd_u8(self.buf.as_ref(), self.offsets[2])
3469 }
3470
3471 pub fn labels(&self) -> Vec<&str> {
3472 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[2] + 1);
3473 let count = c.read_u32().expect("label data validated during from_cdr") as usize;
3474 (0..count)
3475 .map(|_| {
3476 c.read_string()
3477 .expect("label data validated during from_cdr")
3478 })
3479 .collect()
3480 }
3481
3482 pub fn labels_len(&self) -> u32 {
3483 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[2] + 1);
3484 c.read_u32().expect("label data validated during from_cdr")
3485 }
3486
3487 #[inline]
3488 pub fn model_type(&self) -> &str {
3489 rd_string(self.buf.as_ref(), self.offsets[3]).0
3490 }
3491 #[inline]
3492 pub fn model_format(&self) -> &str {
3493 rd_string(self.buf.as_ref(), self.offsets[4]).0
3494 }
3495 #[inline]
3496 pub fn model_name(&self) -> &str {
3497 rd_string(self.buf.as_ref(), self.offsets[5]).0
3498 }
3499
3500 #[inline]
3501 pub fn as_cdr(&self) -> &[u8] {
3502 self.buf.as_ref()
3503 }
3504 pub fn to_cdr(&self) -> Vec<u8> {
3505 self.buf.as_ref().to_vec()
3506 }
3507}
3508
3509impl ModelInfo<Vec<u8>> {
3510 #[deprecated(
3511 since = "3.2.0",
3512 note = "use ModelInfo::builder() for allocation-free buffer reuse; ModelInfo::new will be removed in 4.0"
3513 )]
3514 #[allow(clippy::too_many_arguments)]
3515 pub fn new(
3516 stamp: Time,
3517 frame_id: &str,
3518 input_shape: &[u32],
3519 input_type: u8,
3520 output_shape: &[u32],
3521 output_type: u8,
3522 labels: &[&str],
3523 model_type: &str,
3524 model_format: &str,
3525 model_name: &str,
3526 ) -> Result<Self, CdrError> {
3527 let mut sizer = CdrSizer::new();
3528 Time::size_cdr(&mut sizer);
3529 sizer.size_string(frame_id);
3530 let o0 = sizer.offset();
3531 sizer.size_u32();
3532 sizer.size_seq_4(input_shape.len());
3533 let o1 = sizer.offset();
3534 sizer.size_u8();
3535 sizer.size_u32();
3536 sizer.size_seq_4(output_shape.len());
3537 let o2 = sizer.offset();
3538 sizer.size_u8();
3539 sizer.size_u32();
3540 for l in labels {
3541 sizer.size_string(l);
3542 }
3543 let o3 = sizer.offset();
3544 sizer.size_string(model_type);
3545 let o4 = sizer.offset();
3546 sizer.size_string(model_format);
3547 let o5 = sizer.offset();
3548 sizer.size_string(model_name);
3549
3550 let mut buf = vec![0u8; sizer.size()];
3551 let mut w = CdrWriter::new(&mut buf)?;
3552 stamp.write_cdr(&mut w);
3553 w.write_string(frame_id);
3554 w.write_u32(input_shape.len() as u32);
3555 w.write_slice_u32(input_shape);
3556 w.write_u8(input_type);
3557 w.write_u32(output_shape.len() as u32);
3558 w.write_slice_u32(output_shape);
3559 w.write_u8(output_type);
3560 w.write_u32(labels.len() as u32);
3561 for l in labels {
3562 w.write_string(l);
3563 }
3564 w.write_string(model_type);
3565 w.write_string(model_format);
3566 w.write_string(model_name);
3567 w.finish()?;
3568
3569 Ok(ModelInfo {
3570 offsets: [o0, o1, o2, o3, o4, o5],
3571 buf,
3572 })
3573 }
3574
3575 pub fn into_cdr(self) -> Vec<u8> {
3576 self.buf
3577 }
3578
3579 pub fn builder<'a>() -> ModelInfoBuilder<'a> {
3581 ModelInfoBuilder::new()
3582 }
3583}
3584
3585pub struct ModelInfoBuilder<'a> {
3592 stamp: Time,
3593 frame_id: std::borrow::Cow<'a, str>,
3594 input_shape: &'a [u32],
3595 input_type: u8,
3596 output_shape: &'a [u32],
3597 output_type: u8,
3598 labels: &'a [&'a str],
3599 model_type: std::borrow::Cow<'a, str>,
3600 model_format: std::borrow::Cow<'a, str>,
3601 model_name: std::borrow::Cow<'a, str>,
3602}
3603
3604impl<'a> Default for ModelInfoBuilder<'a> {
3605 fn default() -> Self {
3606 Self {
3607 stamp: Time { sec: 0, nanosec: 0 },
3608 frame_id: std::borrow::Cow::Borrowed(""),
3609 input_shape: &[],
3610 input_type: 0,
3611 output_shape: &[],
3612 output_type: 0,
3613 labels: &[],
3614 model_type: std::borrow::Cow::Borrowed(""),
3615 model_format: std::borrow::Cow::Borrowed(""),
3616 model_name: std::borrow::Cow::Borrowed(""),
3617 }
3618 }
3619}
3620
3621impl<'a> ModelInfoBuilder<'a> {
3622 pub fn new() -> Self {
3623 Self::default()
3624 }
3625
3626 pub fn stamp(&mut self, t: Time) -> &mut Self {
3627 self.stamp = t;
3628 self
3629 }
3630 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3631 self.frame_id = s.into();
3632 self
3633 }
3634 pub fn input_shape(&mut self, v: &'a [u32]) -> &mut Self {
3635 self.input_shape = v;
3636 self
3637 }
3638 pub fn input_type(&mut self, v: u8) -> &mut Self {
3639 self.input_type = v;
3640 self
3641 }
3642 pub fn output_shape(&mut self, v: &'a [u32]) -> &mut Self {
3643 self.output_shape = v;
3644 self
3645 }
3646 pub fn output_type(&mut self, v: u8) -> &mut Self {
3647 self.output_type = v;
3648 self
3649 }
3650 pub fn labels(&mut self, v: &'a [&'a str]) -> &mut Self {
3651 self.labels = v;
3652 self
3653 }
3654 pub fn model_type(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3655 self.model_type = s.into();
3656 self
3657 }
3658 pub fn model_format(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3659 self.model_format = s.into();
3660 self
3661 }
3662 pub fn model_name(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3663 self.model_name = s.into();
3664 self
3665 }
3666
3667 fn size(&self) -> usize {
3668 let mut s = CdrSizer::new();
3669 Time::size_cdr(&mut s);
3670 s.size_string(&self.frame_id);
3671 s.size_u32();
3672 s.size_seq_4(self.input_shape.len());
3673 s.size_u8();
3674 s.size_u32();
3675 s.size_seq_4(self.output_shape.len());
3676 s.size_u8();
3677 s.size_u32();
3678 for l in self.labels {
3679 s.size_string(l);
3680 }
3681 s.size_string(&self.model_type);
3682 s.size_string(&self.model_format);
3683 s.size_string(&self.model_name);
3684 s.size()
3685 }
3686
3687 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
3688 let mut w = CdrWriter::new(buf)?;
3689 self.stamp.write_cdr(&mut w);
3690 w.write_string(&self.frame_id);
3691 w.write_u32(self.input_shape.len() as u32);
3692 w.write_slice_u32(self.input_shape);
3693 w.write_u8(self.input_type);
3694 w.write_u32(self.output_shape.len() as u32);
3695 w.write_slice_u32(self.output_shape);
3696 w.write_u8(self.output_type);
3697 w.write_u32(self.labels.len() as u32);
3698 for l in self.labels {
3699 w.write_string(l);
3700 }
3701 w.write_string(&self.model_type);
3702 w.write_string(&self.model_format);
3703 w.write_string(&self.model_name);
3704 w.finish()
3705 }
3706
3707 pub fn build(&self) -> Result<ModelInfo<Vec<u8>>, CdrError> {
3708 let mut buf = vec![0u8; self.size()];
3709 self.write_into(&mut buf)?;
3710 ModelInfo::from_cdr(buf)
3711 }
3712
3713 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
3714 buf.resize(self.size(), 0);
3715 self.write_into(buf)
3716 }
3717
3718 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
3719 let need = self.size();
3720 if buf.len() < need {
3721 return Err(CdrError::BufferTooShort {
3722 need,
3723 have: buf.len(),
3724 });
3725 }
3726 self.write_into(&mut buf[..need])?;
3727 Ok(need)
3728 }
3729}
3730
3731impl<B: AsRef<[u8]> + AsMut<[u8]>> ModelInfo<B> {
3732 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
3733 let b = self.buf.as_mut();
3734 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
3735 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
3736 }
3737
3738 pub fn set_input_type(&mut self, v: u8) -> Result<(), CdrError> {
3739 wr_u8(self.buf.as_mut(), self.offsets[1], v)
3740 }
3741
3742 pub fn set_output_type(&mut self, v: u8) -> Result<(), CdrError> {
3743 wr_u8(self.buf.as_mut(), self.offsets[2], v)
3744 }
3745}
3746
3747pub mod vibration_measurement {
3765 pub const UNKNOWN: u8 = 0;
3766 pub const RMS: u8 = 1;
3767 pub const PEAK: u8 = 2;
3768 pub const PEAK_TO_PEAK: u8 = 3;
3769}
3770
3771pub mod vibration_unit {
3773 pub const UNKNOWN: u8 = 0;
3774 pub const ACCEL_M_PER_S2: u8 = 1;
3775 pub const ACCEL_G: u8 = 2;
3776 pub const VELOCITY_MM_PER_S: u8 = 3;
3777 pub const DISPLACEMENT_UM: u8 = 4;
3778 pub const VELOCITY_IN_PER_S: u8 = 5;
3779 pub const DISPLACEMENT_MIL: u8 = 6;
3780}
3781
3782pub struct Vibration<B> {
3783 buf: B,
3784 offsets: [usize; 1],
3802}
3803
3804impl<B> Vibration<B> {
3805 #[inline]
3807 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Vibration<C> {
3808 Vibration {
3809 buf: f(self.buf),
3810 offsets: self.offsets,
3811 }
3812 }
3813}
3814
3815impl<B: AsRef<[u8]>> Vibration<B> {
3816 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
3817 use crate::geometry_msgs::Vector3;
3818 let header = crate::std_msgs::Header::<&[u8]>::from_cdr(buf.as_ref())?;
3819 let pre = header.end_offset();
3820 let mut c = CdrCursor::resume(buf.as_ref(), pre);
3821 c.align(8);
3822 let o0 = c.offset();
3823 Vector3::read_cdr(&mut c)?;
3824 c.read_f32()?; c.read_f32()?; c.read_u8()?; c.read_u8()?; c.align(4);
3829 let raw = c.read_u32()?;
3831 let n = c.check_seq_count(raw, 4)?;
3832 for _ in 0..n {
3833 c.read_u32()?;
3834 }
3835 Ok(Vibration { offsets: [o0], buf })
3836 }
3837
3838 pub fn header(&self) -> crate::std_msgs::Header<&[u8]> {
3840 crate::std_msgs::Header::from_cdr(self.buf.as_ref())
3841 .expect("header bytes validated during from_cdr")
3842 }
3843 pub fn stamp(&self) -> crate::builtin_interfaces::Time {
3844 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
3845 }
3846 pub fn frame_id(&self) -> &str {
3847 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
3848 }
3849 pub fn vibration(&self) -> crate::geometry_msgs::Vector3 {
3850 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
3851 crate::geometry_msgs::Vector3::read_cdr(&mut c)
3852 .expect("vibration validated during from_cdr")
3853 }
3854 pub fn band_lower_hz(&self) -> f32 {
3855 rd_f32(self.buf.as_ref(), self.offsets[0] + 24)
3856 }
3857 pub fn band_upper_hz(&self) -> f32 {
3858 rd_f32(self.buf.as_ref(), self.offsets[0] + 28)
3859 }
3860 pub fn measurement_type(&self) -> u8 {
3861 rd_u8(self.buf.as_ref(), self.offsets[0] + 32)
3862 }
3863 pub fn unit(&self) -> u8 {
3864 rd_u8(self.buf.as_ref(), self.offsets[0] + 33)
3865 }
3866 pub fn clipping_len(&self) -> u32 {
3867 rd_u32(self.buf.as_ref(), self.offsets[0] + 36)
3868 }
3869 pub fn clipping_seq_offset(&self) -> usize {
3872 self.offsets[0] + 36
3873 }
3874 pub fn clipping(&self) -> Vec<u32> {
3875 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0] + 36);
3876 let n = c
3877 .read_u32()
3878 .expect("clipping length validated during from_cdr") as usize;
3879 let mut out = Vec::with_capacity(n);
3880 for _ in 0..n {
3881 out.push(
3882 c.read_u32()
3883 .expect("clipping element validated during from_cdr"),
3884 );
3885 }
3886 out
3887 }
3888 pub fn as_cdr(&self) -> &[u8] {
3889 self.buf.as_ref()
3890 }
3891 pub fn to_cdr(&self) -> Vec<u8> {
3892 self.buf.as_ref().to_vec()
3893 }
3894}
3895
3896impl Vibration<Vec<u8>> {
3897 #[deprecated(
3898 since = "3.2.0",
3899 note = "use Vibration::builder() for allocation-free buffer reuse; Vibration::new will be removed in 4.0"
3900 )]
3901 #[allow(clippy::too_many_arguments)]
3902 pub fn new(
3903 stamp: crate::builtin_interfaces::Time,
3904 frame_id: &str,
3905 measurement_type: u8,
3906 unit: u8,
3907 band_lower_hz: f32,
3908 band_upper_hz: f32,
3909 vibration: crate::geometry_msgs::Vector3,
3910 clipping: &[u32],
3911 ) -> Result<Self, CdrError> {
3912 use crate::builtin_interfaces::Time;
3913 use crate::geometry_msgs::Vector3;
3914 let mut sizer = CdrSizer::new();
3915 Time::size_cdr(&mut sizer);
3916 sizer.size_string(frame_id);
3917 sizer.align(8);
3918 let o0 = sizer.offset();
3919 Vector3::size_cdr(&mut sizer);
3920 sizer.size_f32();
3921 sizer.size_f32();
3922 sizer.size_u8();
3923 sizer.size_u8();
3924 sizer.align(4);
3925 sizer.size_u32();
3926 for _ in clipping {
3927 sizer.size_u32();
3928 }
3929
3930 let mut buf = vec![0u8; sizer.size()];
3931 let mut w = CdrWriter::new(&mut buf)?;
3932 stamp.write_cdr(&mut w);
3933 w.write_string(frame_id);
3934 vibration.write_cdr(&mut w);
3935 w.write_f32(band_lower_hz);
3936 w.write_f32(band_upper_hz);
3937 w.write_u8(measurement_type);
3938 w.write_u8(unit);
3939 w.write_u32(clipping.len() as u32);
3940 for v in clipping {
3941 w.write_u32(*v);
3942 }
3943 w.finish()?;
3944
3945 Ok(Vibration { offsets: [o0], buf })
3946 }
3947
3948 pub fn into_cdr(self) -> Vec<u8> {
3949 self.buf
3950 }
3951
3952 pub fn builder<'a>() -> VibrationBuilder<'a> {
3954 VibrationBuilder::new()
3955 }
3956}
3957
3958pub struct VibrationBuilder<'a> {
3966 stamp: crate::builtin_interfaces::Time,
3967 frame_id: std::borrow::Cow<'a, str>,
3968 measurement_type: u8,
3969 unit: u8,
3970 band_lower_hz: f32,
3971 band_upper_hz: f32,
3972 vibration: crate::geometry_msgs::Vector3,
3973 clipping: &'a [u32],
3974}
3975
3976impl<'a> Default for VibrationBuilder<'a> {
3977 fn default() -> Self {
3978 Self {
3979 stamp: crate::builtin_interfaces::Time { sec: 0, nanosec: 0 },
3980 frame_id: std::borrow::Cow::Borrowed(""),
3981 measurement_type: 0,
3982 unit: 0,
3983 band_lower_hz: 0.0,
3984 band_upper_hz: 0.0,
3985 vibration: crate::geometry_msgs::Vector3 {
3986 x: 0.0,
3987 y: 0.0,
3988 z: 0.0,
3989 },
3990 clipping: &[],
3991 }
3992 }
3993}
3994
3995impl<'a> VibrationBuilder<'a> {
3996 pub fn new() -> Self {
3997 Self::default()
3998 }
3999
4000 pub fn stamp(&mut self, t: crate::builtin_interfaces::Time) -> &mut Self {
4001 self.stamp = t;
4002 self
4003 }
4004 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
4005 self.frame_id = s.into();
4006 self
4007 }
4008 pub fn measurement_type(&mut self, v: u8) -> &mut Self {
4009 self.measurement_type = v;
4010 self
4011 }
4012 pub fn unit(&mut self, v: u8) -> &mut Self {
4013 self.unit = v;
4014 self
4015 }
4016 pub fn band_lower_hz(&mut self, v: f32) -> &mut Self {
4017 self.band_lower_hz = v;
4018 self
4019 }
4020 pub fn band_upper_hz(&mut self, v: f32) -> &mut Self {
4021 self.band_upper_hz = v;
4022 self
4023 }
4024 pub fn vibration(&mut self, v: crate::geometry_msgs::Vector3) -> &mut Self {
4025 self.vibration = v;
4026 self
4027 }
4028 pub fn clipping(&mut self, v: &'a [u32]) -> &mut Self {
4029 self.clipping = v;
4030 self
4031 }
4032
4033 fn size(&self) -> usize {
4034 use crate::builtin_interfaces::Time;
4035 use crate::geometry_msgs::Vector3;
4036 let mut s = CdrSizer::new();
4037 Time::size_cdr(&mut s);
4038 s.size_string(&self.frame_id);
4039 s.align(8);
4040 Vector3::size_cdr(&mut s);
4041 s.size_f32();
4042 s.size_f32();
4043 s.size_u8();
4044 s.size_u8();
4045 s.align(4);
4046 s.size_u32();
4047 for _ in self.clipping {
4048 s.size_u32();
4049 }
4050 s.size()
4051 }
4052
4053 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
4054 let mut w = CdrWriter::new(buf)?;
4055 self.stamp.write_cdr(&mut w);
4056 w.write_string(&self.frame_id);
4057 self.vibration.write_cdr(&mut w);
4058 w.write_f32(self.band_lower_hz);
4059 w.write_f32(self.band_upper_hz);
4060 w.write_u8(self.measurement_type);
4061 w.write_u8(self.unit);
4062 w.write_u32(self.clipping.len() as u32);
4063 for v in self.clipping {
4064 w.write_u32(*v);
4065 }
4066 w.finish()
4067 }
4068
4069 pub fn build(&self) -> Result<Vibration<Vec<u8>>, CdrError> {
4070 let mut buf = vec![0u8; self.size()];
4071 self.write_into(&mut buf)?;
4072 Vibration::from_cdr(buf)
4073 }
4074
4075 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
4076 buf.resize(self.size(), 0);
4077 self.write_into(buf)
4078 }
4079
4080 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
4081 let need = self.size();
4082 if buf.len() < need {
4083 return Err(CdrError::BufferTooShort {
4084 need,
4085 have: buf.len(),
4086 });
4087 }
4088 self.write_into(&mut buf[..need])?;
4089 Ok(need)
4090 }
4091}
4092
4093impl<B: AsRef<[u8]> + AsMut<[u8]>> Vibration<B> {
4094 pub fn set_stamp(&mut self, t: crate::builtin_interfaces::Time) -> Result<(), CdrError> {
4095 let b = self.buf.as_mut();
4096 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
4097 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
4098 }
4099
4100 pub fn set_vibration(&mut self, v: crate::geometry_msgs::Vector3) -> Result<(), CdrError> {
4101 let b = self.buf.as_mut();
4102 let p = self.offsets[0];
4103 wr_f64(b, p, v.x)?;
4104 wr_f64(b, p + 8, v.y)?;
4105 wr_f64(b, p + 16, v.z)
4106 }
4107
4108 pub fn set_band_lower_hz(&mut self, v: f32) -> Result<(), CdrError> {
4109 wr_f32(self.buf.as_mut(), self.offsets[0] + 24, v)
4110 }
4111
4112 pub fn set_band_upper_hz(&mut self, v: f32) -> Result<(), CdrError> {
4113 wr_f32(self.buf.as_mut(), self.offsets[0] + 28, v)
4114 }
4115
4116 pub fn set_measurement_type(&mut self, v: u8) -> Result<(), CdrError> {
4117 wr_u8(self.buf.as_mut(), self.offsets[0] + 32, v)
4118 }
4119
4120 pub fn set_unit(&mut self, v: u8) -> Result<(), CdrError> {
4121 wr_u8(self.buf.as_mut(), self.offsets[0] + 33, v)
4122 }
4123}
4124
4125pub fn is_type_supported(type_name: &str) -> bool {
4129 matches!(
4130 type_name,
4131 "Box"
4132 | "CameraFrame"
4133 | "CameraPlane"
4134 | "Date"
4135 | "Detect"
4136 | "DmaBuffer"
4137 | "LocalTime"
4138 | "Mask"
4139 | "Model"
4140 | "ModelInfo"
4141 | "RadarCube"
4142 | "RadarInfo"
4143 | "Track"
4144 | "Vibration"
4145 )
4146}
4147
4148pub fn list_types() -> &'static [&'static str] {
4150 &[
4151 "edgefirst_msgs/msg/Box",
4152 "edgefirst_msgs/msg/CameraFrame",
4153 "edgefirst_msgs/msg/CameraPlane",
4154 "edgefirst_msgs/msg/Date",
4155 "edgefirst_msgs/msg/Detect",
4156 "edgefirst_msgs/msg/DmaBuffer",
4157 "edgefirst_msgs/msg/LocalTime",
4158 "edgefirst_msgs/msg/Mask",
4159 "edgefirst_msgs/msg/Model",
4160 "edgefirst_msgs/msg/ModelInfo",
4161 "edgefirst_msgs/msg/RadarCube",
4162 "edgefirst_msgs/msg/RadarInfo",
4163 "edgefirst_msgs/msg/Track",
4164 "edgefirst_msgs/msg/Vibration",
4165 ]
4166}
4167
4168use crate::schema_registry::SchemaType;
4170
4171impl SchemaType for Date {
4172 const SCHEMA_NAME: &'static str = "edgefirst_msgs/msg/Date";
4173}
4174
4175#[cfg(test)]
4176#[allow(deprecated)] mod tests {
4178 use super::*;
4179 use crate::builtin_interfaces::Time;
4180 use crate::cdr::{decode_fixed, encode_fixed};
4181
4182 #[test]
4183 fn date_roundtrip() {
4184 let cases = [
4185 (2025, 1, 27, "typical"),
4186 (2000, 12, 31, "end of year"),
4187 (1970, 1, 1, "unix epoch"),
4188 ];
4189 for (year, month, day, name) in cases {
4190 let date = Date { year, month, day };
4191 let bytes = encode_fixed(&date).unwrap();
4192 let decoded: Date = decode_fixed(&bytes).unwrap();
4193 assert_eq!(date, decoded, "failed for case: {}", name);
4194 }
4195 }
4196
4197 #[test]
4198 fn mask_roundtrip() {
4199 let mask = Mask::new(480, 640, 0, "", &vec![0u8; 480 * 640], false).unwrap();
4200 assert_eq!(mask.height(), 480);
4201 assert_eq!(mask.width(), 640);
4202 assert_eq!(mask.length(), 0);
4203 assert_eq!(mask.encoding(), "");
4204 assert_eq!(mask.mask_data().len(), 480 * 640);
4205 assert!(!mask.boxed());
4206
4207 let bytes = mask.to_cdr();
4208 let decoded = Mask::from_cdr(bytes).unwrap();
4209 assert_eq!(decoded.height(), 480);
4210 assert_eq!(decoded.width(), 640);
4211
4212 let compressed = Mask::new(1080, 1920, 5, "zstd", &[1, 2, 3, 4, 5], true).unwrap();
4214 assert_eq!(compressed.encoding(), "zstd");
4215 assert_eq!(compressed.mask_data(), &[1, 2, 3, 4, 5]);
4216 assert!(compressed.boxed());
4217
4218 let bytes = compressed.to_cdr();
4219 let decoded = Mask::from_cdr(bytes).unwrap();
4220 assert_eq!(decoded.encoding(), "zstd");
4221 assert!(decoded.boxed());
4222 }
4223
4224 #[test]
4225 #[allow(deprecated)]
4226 fn dmabuf_roundtrip() {
4227 let dmabuf = DmaBuffer::new(
4228 Time::new(100, 0),
4229 "camera",
4230 12345,
4231 42,
4232 1920,
4233 1080,
4234 1920 * 3,
4235 0x34325247,
4236 1920 * 1080 * 3,
4237 )
4238 .unwrap();
4239 assert_eq!(dmabuf.stamp(), Time::new(100, 0));
4240 assert_eq!(dmabuf.frame_id(), "camera");
4241 assert_eq!(dmabuf.pid(), 12345);
4242 assert_eq!(dmabuf.fd(), 42);
4243 assert_eq!(dmabuf.width(), 1920);
4244 assert_eq!(dmabuf.height(), 1080);
4245 assert_eq!(dmabuf.stride(), 1920 * 3);
4246 assert_eq!(dmabuf.fourcc(), 0x34325247);
4247 assert_eq!(dmabuf.length(), 1920 * 1080 * 3);
4248
4249 let bytes = dmabuf.to_cdr();
4250 let decoded = DmaBuffer::from_cdr(bytes).unwrap();
4251 assert_eq!(decoded.pid(), 12345);
4252 assert_eq!(decoded.fd(), 42);
4253 }
4254
4255 #[test]
4256 fn camera_frame_roundtrip_empty() {
4257 let cf = CameraFrame::new(
4258 Time::new(1, 0),
4259 "cam0",
4260 42,
4261 1234,
4262 1920,
4263 1080,
4264 "NV12",
4265 "bt709",
4266 "bt709",
4267 "bt709",
4268 "limited",
4269 -1,
4270 &[],
4271 )
4272 .unwrap();
4273 assert_eq!(cf.seq(), 42);
4274 assert_eq!(cf.pid(), 1234);
4275 assert_eq!(cf.width(), 1920);
4276 assert_eq!(cf.height(), 1080);
4277 assert_eq!(cf.format(), "NV12");
4278 assert_eq!(cf.color_space(), "bt709");
4279 assert_eq!(cf.color_range(), "limited");
4280 assert_eq!(cf.fence_fd(), -1);
4281 assert_eq!(cf.num_planes(), 0);
4282
4283 let bytes = cf.to_cdr();
4284 let decoded = CameraFrame::<&[u8]>::from_cdr(&bytes[..]).unwrap();
4285 assert_eq!(decoded.seq(), 42);
4286 assert_eq!(decoded.format(), "NV12");
4287 assert_eq!(decoded.num_planes(), 0);
4288 }
4289
4290 #[test]
4291 fn camera_frame_roundtrip_two_planes() {
4292 let y = CameraPlaneView {
4293 fd: 42,
4294 offset: 0,
4295 stride: 1920,
4296 size: 2_073_600,
4297 used: 2_073_600,
4298 data: &[],
4299 };
4300 let uv = CameraPlaneView {
4301 fd: 42,
4302 offset: 2_073_600,
4303 stride: 1920,
4304 size: 1_036_800,
4305 used: 1_036_800,
4306 data: &[],
4307 };
4308 let cf = CameraFrame::new(
4309 Time::new(2, 0),
4310 "cam0",
4311 100,
4312 1234,
4313 1920,
4314 1080,
4315 "NV12",
4316 "bt709",
4317 "bt709",
4318 "bt709",
4319 "limited",
4320 77,
4321 &[y, uv],
4322 )
4323 .unwrap();
4324
4325 let bytes = cf.to_cdr();
4326 let decoded = CameraFrame::<&[u8]>::from_cdr(&bytes[..]).unwrap();
4327 assert_eq!(decoded.fence_fd(), 77);
4328 assert_eq!(decoded.num_planes(), 2);
4329 let planes = decoded.planes();
4330 assert_eq!(planes.len(), 2);
4331 assert_eq!(planes[0].fd, 42);
4332 assert_eq!(planes[0].offset, 0);
4333 assert_eq!(planes[1].offset, 2_073_600);
4334 assert_eq!(planes[0].used, planes[0].size);
4335 }
4336
4337 #[test]
4338 fn camera_frame_inlined_data_roundtrip() {
4339 let data: Vec<u8> = (0..32u8).collect();
4340 let plane = CameraPlaneView {
4341 fd: -1,
4342 offset: 0,
4343 stride: 16,
4344 size: 32,
4345 used: 32,
4346 data: &data,
4347 };
4348 let cf = CameraFrame::new(
4349 Time::new(3, 0),
4350 "bridge",
4351 1,
4352 0,
4353 2,
4354 16,
4355 "rgb8",
4356 "srgb",
4357 "srgb",
4358 "",
4359 "full",
4360 -1,
4361 &[plane],
4362 )
4363 .unwrap();
4364 let decoded = CameraFrame::<&[u8]>::from_cdr(cf.as_cdr()).unwrap();
4365 let planes = decoded.planes();
4366 assert_eq!(planes[0].fd, -1);
4367 assert_eq!(planes[0].data.len(), 32);
4368 assert_eq!(planes[0].data[0], 0);
4369 assert_eq!(planes[0].data[31], 31);
4370 }
4371
4372 #[test]
4373 fn camera_frame_contract_rejections() {
4374 let stamp = Time::new(0, 0);
4375 assert!(CameraFrame::new(stamp, "c", 0, 0, 0, 1, "rgb8", "", "", "", "", -1, &[]).is_err());
4377 assert!(CameraFrame::new(stamp, "c", 0, 0, 1, 0, "rgb8", "", "", "", "", -1, &[]).is_err());
4379 let bad_plane = CameraPlaneView {
4381 fd: 1,
4382 offset: 0,
4383 stride: 1,
4384 size: 1,
4385 used: 2,
4386 data: &[],
4387 };
4388 assert!(CameraFrame::new(
4389 stamp,
4390 "c",
4391 0,
4392 0,
4393 1,
4394 1,
4395 "rgb8",
4396 "",
4397 "",
4398 "",
4399 "",
4400 -1,
4401 &[bad_plane]
4402 )
4403 .is_err());
4404 let bad_fd = CameraPlaneView {
4406 fd: -5,
4407 offset: 0,
4408 stride: 1,
4409 size: 1,
4410 used: 1,
4411 data: &[],
4412 };
4413 assert!(CameraFrame::new(
4414 stamp,
4415 "c",
4416 0,
4417 0,
4418 1,
4419 1,
4420 "rgb8",
4421 "",
4422 "",
4423 "",
4424 "",
4425 -1,
4426 &[bad_fd]
4427 )
4428 .is_err());
4429 let data = vec![1u8];
4431 let both = CameraPlaneView {
4432 fd: 5,
4433 offset: 0,
4434 stride: 1,
4435 size: 1,
4436 used: 1,
4437 data: &data,
4438 };
4439 assert!(
4440 CameraFrame::new(stamp, "c", 0, 0, 1, 1, "rgb8", "", "", "", "", -1, &[both]).is_err()
4441 );
4442 }
4443
4444 #[test]
4445 fn camera_frame_rejects_wrong_endianness() {
4446 let stamp = Time::new(1, 0);
4450 let plane = CameraPlaneView {
4451 fd: 1,
4452 offset: 0,
4453 stride: 1,
4454 size: 1,
4455 used: 1,
4456 data: &[],
4457 };
4458 let cf = CameraFrame::new(
4459 stamp,
4460 "cam",
4461 0,
4462 0,
4463 1,
4464 1,
4465 "rgb8",
4466 "",
4467 "",
4468 "",
4469 "",
4470 -1,
4471 &[plane],
4472 )
4473 .unwrap();
4474 let mut bytes = cf.to_cdr();
4475 bytes[1] = 0x00;
4478 assert!(CameraFrame::<&[u8]>::from_cdr(&bytes).is_err());
4479 }
4480
4481 #[test]
4482 fn camera_frame_decoder_rejects_fd_below_minus_one() {
4483 let stamp = Time::new(1, 0);
4487 let plane = CameraPlaneView {
4488 fd: 1,
4489 offset: 0,
4490 stride: 1,
4491 size: 1,
4492 used: 1,
4493 data: &[],
4494 };
4495 let cf =
4496 CameraFrame::new(stamp, "c", 0, 0, 1, 1, "rgb8", "", "", "", "", -1, &[plane]).unwrap();
4497 let mut bytes = cf.to_cdr();
4498 let fd_off = bytes.len() - 24;
4499 bytes[fd_off..fd_off + 4].copy_from_slice(&(-5i32).to_le_bytes());
4500 assert!(CameraFrame::<&[u8]>::from_cdr(&bytes).is_err());
4501 }
4502
4503 #[test]
4504 fn camera_frame_decoder_rejects_used_greater_than_size() {
4505 let stamp = Time::new(1, 0);
4508 let plane = CameraPlaneView {
4509 fd: 1,
4510 offset: 0,
4511 stride: 1,
4512 size: 1,
4513 used: 1,
4514 data: &[],
4515 };
4516 let cf =
4517 CameraFrame::new(stamp, "c", 0, 0, 1, 1, "rgb8", "", "", "", "", -1, &[plane]).unwrap();
4518 let mut bytes = cf.to_cdr();
4519 let used_off = bytes.len() - 8;
4520 bytes[used_off..used_off + 4].copy_from_slice(&99u32.to_le_bytes());
4521 assert!(CameraFrame::<&[u8]>::from_cdr(&bytes).is_err());
4522 }
4523
4524 #[test]
4525 fn camera_frame_rejects_inlined_size_mismatch() {
4526 let data = [0x42u8, 0x43, 0x44, 0x45];
4529 let plane = CameraPlaneView {
4530 fd: -1,
4531 offset: 0,
4532 stride: 0,
4533 size: 99, used: 4,
4535 data: &data,
4536 };
4537 assert!(CameraFrame::new(
4538 Time::new(0, 0),
4539 "c",
4540 0,
4541 0,
4542 1,
4543 1,
4544 "rgb8",
4545 "",
4546 "",
4547 "",
4548 "",
4549 -1,
4550 &[plane]
4551 )
4552 .is_err());
4553 }
4554
4555 #[test]
4556 fn camera_frame_decoder_rejects_inlined_size_mismatch() {
4557 let data = [0x42u8, 0x43, 0x44, 0x45];
4561 let plane = CameraPlaneView {
4562 fd: -1,
4563 offset: 0,
4564 stride: 0xDEADBEEF,
4565 size: 4,
4566 used: 4,
4567 data: &data,
4568 };
4569 let cf = CameraFrame::new(
4570 Time::new(1, 0),
4571 "c",
4572 0,
4573 0,
4574 1,
4575 1,
4576 "rgb8",
4577 "",
4578 "",
4579 "",
4580 "",
4581 -1,
4582 &[plane],
4583 )
4584 .unwrap();
4585 let mut bytes = cf.to_cdr();
4586 let needle = 0xDEADBEEFu32.to_le_bytes();
4587 let stride_off = bytes
4588 .windows(4)
4589 .position(|w| w == needle)
4590 .expect("stride sentinel");
4591 let size_off = stride_off + 4;
4593 bytes[size_off..size_off + 4].copy_from_slice(&99u32.to_le_bytes());
4594 assert!(CameraFrame::<&[u8]>::from_cdr(&bytes).is_err());
4595 }
4596
4597 #[test]
4598 fn camera_frame_decoder_rejects_positive_fd_with_inline_data() {
4599 let stamp = Time::new(1, 0);
4604 let data = [0x42u8, 0x43, 0x44, 0x45];
4605 let plane = CameraPlaneView {
4606 fd: -1,
4607 offset: 0,
4608 stride: 0xDEADBEEF,
4609 size: 4,
4610 used: 4,
4611 data: &data,
4612 };
4613 let cf =
4614 CameraFrame::new(stamp, "c", 0, 0, 1, 1, "rgb8", "", "", "", "", -1, &[plane]).unwrap();
4615 let mut bytes = cf.to_cdr();
4616 let needle = 0xDEADBEEFu32.to_le_bytes();
4617 let stride_off = bytes
4618 .windows(4)
4619 .position(|w| w == needle)
4620 .expect("stride sentinel");
4621 let fd_off = stride_off - 8;
4622 bytes[fd_off..fd_off + 4].copy_from_slice(&5i32.to_le_bytes());
4623 assert!(CameraFrame::<&[u8]>::from_cdr(&bytes).is_err());
4624 }
4625
4626 #[test]
4627 fn camera_frame_registered_in_type_list() {
4628 assert!(is_type_supported("CameraFrame"));
4629 assert!(is_type_supported("CameraPlane"));
4630 assert!(list_types().contains(&"edgefirst_msgs/msg/CameraFrame"));
4631 assert!(list_types().contains(&"edgefirst_msgs/msg/CameraPlane"));
4632 }
4633
4634 #[test]
4635 fn local_time_roundtrip() {
4636 let lt = LocalTime::new(
4637 Time::new(0, 0),
4638 "clock",
4639 Date {
4640 year: 2025,
4641 month: 1,
4642 day: 27,
4643 },
4644 Time::new(43200, 0),
4645 -300,
4646 )
4647 .unwrap();
4648 assert_eq!(lt.frame_id(), "clock");
4649 assert_eq!(
4650 lt.date(),
4651 Date {
4652 year: 2025,
4653 month: 1,
4654 day: 27
4655 }
4656 );
4657 assert_eq!(lt.time(), Time::new(43200, 0));
4658 assert_eq!(lt.timezone(), -300);
4659
4660 let bytes = lt.to_cdr();
4661 let decoded = LocalTime::from_cdr(bytes).unwrap();
4662 assert_eq!(
4663 decoded.date(),
4664 Date {
4665 year: 2025,
4666 month: 1,
4667 day: 27
4668 }
4669 );
4670 assert_eq!(decoded.timezone(), -300);
4671 }
4672
4673 #[test]
4674 fn radar_cube_roundtrip() {
4675 let cube = RadarCube::new(
4676 Time::new(1234567890, 123456789),
4677 "radar",
4678 1234567890123456,
4679 &[6, 1, 5, 2],
4680 &[16, 256, 4, 64],
4681 &[1.0, 2.5, 1.0, 0.5],
4682 &[100, 200, -100, -200],
4683 true,
4684 )
4685 .unwrap();
4686 assert_eq!(cube.stamp(), Time::new(1234567890, 123456789));
4687 assert_eq!(cube.frame_id(), "radar");
4688 assert_eq!(cube.timestamp(), 1234567890123456);
4689 assert_eq!(cube.layout(), &[6, 1, 5, 2]);
4690 assert_eq!(cube.shape(), vec![16, 256, 4, 64]);
4691 assert_eq!(cube.scales(), vec![1.0, 2.5, 1.0, 0.5]);
4692 assert!(cube.is_complex());
4693
4694 let bytes = cube.to_cdr();
4695 let decoded = RadarCube::from_cdr(bytes).unwrap();
4696 assert_eq!(decoded.timestamp(), 1234567890123456);
4697 assert_eq!(decoded.layout(), &[6, 1, 5, 2]);
4698 assert!(decoded.is_complex());
4699 }
4700
4701 #[test]
4702 fn radar_info_roundtrip() {
4703 let info = RadarInfo::new(
4704 Time::new(0, 0),
4705 "radar",
4706 "77GHz",
4707 "short",
4708 "off",
4709 "high",
4710 true,
4711 )
4712 .unwrap();
4713 assert_eq!(info.center_frequency(), "77GHz");
4714 assert_eq!(info.frequency_sweep(), "short");
4715 assert_eq!(info.range_toggle(), "off");
4716 assert_eq!(info.detection_sensitivity(), "high");
4717 assert!(info.cube());
4718
4719 let bytes = info.to_cdr();
4720 let decoded = RadarInfo::from_cdr(bytes).unwrap();
4721 assert_eq!(decoded.center_frequency(), "77GHz");
4722 assert!(decoded.cube());
4723 }
4724
4725 #[test]
4726 fn detect_roundtrip() {
4727 let empty = Detect::new(
4729 Time::new(0, 0),
4730 "",
4731 Time::new(0, 0),
4732 Time::new(0, 0),
4733 Time::new(0, 0),
4734 &[],
4735 )
4736 .unwrap();
4737 assert_eq!(empty.boxes_len(), 0);
4738
4739 let bytes = empty.to_cdr();
4740 let decoded = Detect::from_cdr(bytes).unwrap();
4741 assert_eq!(decoded.boxes_len(), 0);
4742
4743 let boxes = [DetectBoxView {
4745 center_x: 0.5,
4746 center_y: 0.5,
4747 width: 0.1,
4748 height: 0.2,
4749 label: "car",
4750 score: 0.98,
4751 distance: 10.0,
4752 speed: 5.0,
4753 track_id: "t1",
4754 track_lifetime: 5,
4755 track_created: Time::new(95, 0),
4756 }];
4757 let detect = Detect::new(
4758 Time::new(100, 500_000_000),
4759 "camera",
4760 Time::new(100, 400_000_000),
4761 Time::new(0, 50_000_000),
4762 Time::new(100, 500_000_000),
4763 &boxes,
4764 )
4765 .unwrap();
4766 assert_eq!(detect.boxes_len(), 1);
4767 let b = detect.boxes();
4768 assert_eq!(b[0].label, "car");
4769 assert_eq!(b[0].score, 0.98);
4770
4771 let bytes = detect.to_cdr();
4772 let decoded = Detect::from_cdr(bytes).unwrap();
4773 assert_eq!(decoded.boxes_len(), 1);
4774 let b = decoded.boxes();
4775 assert_eq!(b[0].label, "car");
4776 }
4777
4778 #[test]
4779 fn detect_multi_box_varying_strings() {
4780 let boxes = [
4781 DetectBoxView {
4782 center_x: 0.1,
4783 center_y: 0.2,
4784 width: 0.5,
4785 height: 0.6,
4786 label: "a",
4787 score: 0.95,
4788 distance: 5.0,
4789 speed: 1.0,
4790 track_id: "t",
4791 track_lifetime: 1,
4792 track_created: Time::new(1, 0),
4793 },
4794 DetectBoxView {
4795 center_x: 0.3,
4796 center_y: 0.4,
4797 width: 0.2,
4798 height: 0.3,
4799 label: "person",
4800 score: 0.87,
4801 distance: 12.0,
4802 speed: 3.0,
4803 track_id: "track_long_id",
4804 track_lifetime: 10,
4805 track_created: Time::new(2, 0),
4806 },
4807 DetectBoxView {
4808 center_x: 0.7,
4809 center_y: 0.8,
4810 width: 0.1,
4811 height: 0.1,
4812 label: "ab",
4813 score: 0.50,
4814 distance: 0.0,
4815 speed: 0.0,
4816 track_id: "abc",
4817 track_lifetime: 0,
4818 track_created: Time::new(0, 0),
4819 },
4820 ];
4821 let detect = Detect::new(
4822 Time::new(100, 0),
4823 "camera",
4824 Time::new(99, 0),
4825 Time::new(0, 50_000_000),
4826 Time::new(100, 0),
4827 &boxes,
4828 )
4829 .unwrap();
4830 assert_eq!(detect.boxes_len(), 3);
4831 let decoded_boxes = detect.boxes();
4832 assert_eq!(decoded_boxes[0].label, "a");
4833 assert_eq!(decoded_boxes[0].track_id, "t");
4834 assert_eq!(decoded_boxes[1].label, "person");
4835 assert_eq!(decoded_boxes[1].track_id, "track_long_id");
4836 assert_eq!(decoded_boxes[2].label, "ab");
4837 assert_eq!(decoded_boxes[2].track_id, "abc");
4838
4839 let bytes = detect.to_cdr();
4840 let decoded = Detect::from_cdr(bytes).unwrap();
4841 assert_eq!(decoded.boxes_len(), 3);
4842 let b = decoded.boxes();
4843 assert_eq!(b[0].label, "a");
4844 assert_eq!(b[0].track_id, "t");
4845 assert_eq!(b[0].score, 0.95);
4846 assert_eq!(b[1].label, "person");
4847 assert_eq!(b[1].track_id, "track_long_id");
4848 assert_eq!(b[1].track_lifetime, 10);
4849 assert_eq!(b[2].label, "ab");
4850 assert_eq!(b[2].track_id, "abc");
4851 }
4852
4853 #[test]
4854 fn model_roundtrip() {
4855 let model = Model::new(
4856 Time::new(0, 0),
4857 "model",
4858 Duration::new(0, 1_000_000),
4859 Duration::new(0, 5_000_000),
4860 Duration::new(0, 500_000),
4861 Duration::new(0, 2_000_000),
4862 &[],
4863 &[],
4864 )
4865 .unwrap();
4866 assert_eq!(model.input_time(), Duration::new(0, 1_000_000));
4867 assert_eq!(model.boxes_len(), 0);
4868 assert_eq!(model.masks_len(), 0);
4869
4870 let bytes = model.to_cdr();
4871 let decoded = Model::from_cdr(bytes).unwrap();
4872 assert_eq!(decoded.input_time(), Duration::new(0, 1_000_000));
4873 }
4874
4875 #[test]
4876 fn model_info_roundtrip() {
4877 let info = ModelInfo::new(
4878 Time::new(0, 0),
4879 "",
4880 &[1, 3, 640, 640],
4881 8,
4882 &[1, 25200, 85],
4883 8,
4884 &["person", "car"],
4885 "yolov8",
4886 "onnx",
4887 "yolov8n",
4888 )
4889 .unwrap();
4890 assert_eq!(info.input_shape(), vec![1, 3, 640, 640]);
4891 assert_eq!(info.input_type(), 8);
4892 assert_eq!(info.output_shape(), vec![1, 25200, 85]);
4893 assert_eq!(info.output_type(), 8);
4894 assert_eq!(info.labels(), vec!["person", "car"]);
4895 assert_eq!(info.model_type(), "yolov8");
4896 assert_eq!(info.model_format(), "onnx");
4897 assert_eq!(info.model_name(), "yolov8n");
4898
4899 let bytes = info.to_cdr();
4900 let decoded = ModelInfo::from_cdr(bytes).unwrap();
4901 assert_eq!(decoded.input_shape(), vec![1, 3, 640, 640]);
4902 assert_eq!(decoded.labels(), vec!["person", "car"]);
4903 assert_eq!(decoded.model_name(), "yolov8n");
4904 }
4905
4906 #[test]
4907 fn model_info_empty_labels() {
4908 let info = ModelInfo::new(
4909 Time::new(1, 0),
4910 "cam",
4911 &[1, 3, 224, 224],
4912 8,
4913 &[1, 10],
4914 8,
4915 &[],
4916 "classifier",
4917 "onnx",
4918 "mobilenet",
4919 )
4920 .unwrap();
4921 assert_eq!(info.labels(), Vec::<&str>::new());
4922 assert_eq!(info.input_shape(), &[1, 3, 224, 224]);
4923 assert_eq!(info.output_shape(), &[1, 10]);
4924 assert_eq!(info.model_type(), "classifier");
4925 assert_eq!(info.model_format(), "onnx");
4926 assert_eq!(info.model_name(), "mobilenet");
4927
4928 let bytes = info.to_cdr();
4929 let decoded = ModelInfo::from_cdr(bytes).unwrap();
4930 assert_eq!(decoded.labels(), Vec::<&str>::new());
4931 assert_eq!(decoded.model_type(), "classifier");
4932 assert_eq!(decoded.model_name(), "mobilenet");
4933 }
4934
4935 #[test]
4936 fn model_info_single_empty_label() {
4937 let info = ModelInfo::new(
4938 Time::new(0, 0),
4939 "",
4940 &[1],
4941 0,
4942 &[1],
4943 0,
4944 &[""],
4945 "det",
4946 "tflite",
4947 "m",
4948 )
4949 .unwrap();
4950 assert_eq!(info.labels(), vec![""]);
4951
4952 let bytes = info.to_cdr();
4953 let decoded = ModelInfo::from_cdr(bytes).unwrap();
4954 assert_eq!(decoded.labels(), vec![""]);
4955 assert_eq!(decoded.model_type(), "det");
4956 }
4957
4958 #[test]
4959 fn model_info_alignment_stressing_labels() {
4960 let info = ModelInfo::new(
4961 Time::new(0, 0),
4962 "f",
4963 &[1, 3, 320, 320],
4964 8,
4965 &[1, 100, 6],
4966 8,
4967 &["a", "ab", "abc", "abcd", "abcde"],
4968 "object_detection",
4969 "DeepViewRT",
4970 "yolov8n",
4971 )
4972 .unwrap();
4973 assert_eq!(info.labels(), vec!["a", "ab", "abc", "abcd", "abcde"]);
4974 assert_eq!(info.input_shape(), &[1, 3, 320, 320]);
4975 assert_eq!(info.model_type(), "object_detection");
4976
4977 let bytes = info.to_cdr();
4978 let decoded = ModelInfo::from_cdr(bytes).unwrap();
4979 assert_eq!(decoded.labels(), vec!["a", "ab", "abc", "abcd", "abcde"]);
4980 assert_eq!(decoded.input_shape(), &[1, 3, 320, 320]);
4981 assert_eq!(decoded.model_type(), "object_detection");
4982 assert_eq!(decoded.model_name(), "yolov8n");
4983 }
4984
4985 #[test]
4986 fn model_info_many_labels() {
4987 let label_strs: Vec<String> = (0..80).map(|i| format!("class_{i}")).collect();
4988 let labels: Vec<&str> = label_strs.iter().map(|s| s.as_str()).collect();
4989 let info = ModelInfo::new(
4990 Time::new(0, 0),
4991 "cam0",
4992 &[1, 3, 640, 640],
4993 8,
4994 &[1, 84, 8400],
4995 8,
4996 &labels,
4997 "object_detection",
4998 "DeepViewRT",
4999 "yolov8n",
5000 )
5001 .unwrap();
5002 assert_eq!(info.labels().len(), 80);
5003 assert_eq!(info.labels()[0], "class_0");
5004 assert_eq!(info.labels()[79], "class_79");
5005
5006 let bytes = info.to_cdr();
5007 let decoded = ModelInfo::from_cdr(bytes).unwrap();
5008 assert_eq!(decoded.labels().len(), 80);
5009 assert_eq!(decoded.labels()[0], "class_0");
5010 assert_eq!(decoded.labels()[79], "class_79");
5011 assert_eq!(decoded.model_name(), "yolov8n");
5012 }
5013
5014 #[test]
5015 fn model_info_empty_shapes() {
5016 let info = ModelInfo::new(
5017 Time::new(0, 0),
5018 "",
5019 &[],
5020 0,
5021 &[],
5022 0,
5023 &["label"],
5024 "type",
5025 "format",
5026 "name",
5027 )
5028 .unwrap();
5029 assert_eq!(info.input_shape(), &[] as &[u32]);
5030 assert_eq!(info.output_shape(), &[] as &[u32]);
5031 assert_eq!(info.labels(), vec!["label"]);
5032
5033 let bytes = info.to_cdr();
5034 let decoded = ModelInfo::from_cdr(bytes).unwrap();
5035 assert_eq!(decoded.input_shape(), &[] as &[u32]);
5036 assert_eq!(decoded.output_shape(), &[] as &[u32]);
5037 assert_eq!(decoded.labels(), vec!["label"]);
5038 }
5039
5040 #[test]
5041 fn track_roundtrip() {
5042 let track = Track::new("t1", 5, Time::new(95, 0)).unwrap();
5043 assert_eq!(track.id(), "t1");
5044 assert_eq!(track.lifetime(), 5);
5045 assert_eq!(track.created(), Time::new(95, 0));
5046
5047 let bytes = track.to_cdr();
5048 let decoded = Track::from_cdr(bytes).unwrap();
5049 assert_eq!(decoded.id(), "t1");
5050 assert_eq!(decoded.lifetime(), 5);
5051 }
5052
5053 #[test]
5054 fn detect_box_roundtrip() {
5055 let b = DetectBox::new(
5056 0.5,
5057 0.5,
5058 0.1,
5059 0.2,
5060 "car",
5061 0.98,
5062 10.0,
5063 5.0,
5064 "t1",
5065 5,
5066 Time::new(95, 0),
5067 )
5068 .unwrap();
5069 assert_eq!(b.center_x(), 0.5);
5070 assert_eq!(b.label(), "car");
5071 assert_eq!(b.score(), 0.98);
5072 assert_eq!(b.track_id(), "t1");
5073
5074 let bytes = b.to_cdr();
5075 let decoded = DetectBox::from_cdr(bytes).unwrap();
5076 assert_eq!(decoded.label(), "car");
5077 assert_eq!(decoded.track_id(), "t1");
5078 }
5079
5080 #[test]
5081 fn detect_box_empty_strings() {
5082 let b = DetectBox::new(
5083 0.5,
5084 0.5,
5085 0.1,
5086 0.2,
5087 "",
5088 0.0,
5089 0.0,
5090 0.0,
5091 "",
5092 0,
5093 Time::new(0, 0),
5094 )
5095 .unwrap();
5096 assert_eq!(b.label(), "");
5097 assert_eq!(b.track_id(), "");
5098 assert_eq!(b.center_x(), 0.5);
5099
5100 let bytes = b.to_cdr();
5101 let decoded = DetectBox::from_cdr(bytes).unwrap();
5102 assert_eq!(decoded.label(), "");
5103 assert_eq!(decoded.track_id(), "");
5104 assert_eq!(decoded.score(), 0.0);
5105 }
5106
5107 #[test]
5111 fn detect_from_cdr_collect_boxes_matches_boxes() {
5112 static BYTES: &[u8] = include_bytes!("../testdata/cdr/edgefirst_msgs/Detect_multi.cdr");
5113
5114 let detect_ref = Detect::from_cdr(BYTES).expect("reference decode");
5116 let boxes_ref = detect_ref.boxes();
5117
5118 let (detect_new, boxes_new) =
5120 Detect::from_cdr_collect_boxes(BYTES).expect("collect decode");
5121
5122 assert_eq!(detect_ref.stamp().sec, detect_new.stamp().sec);
5124 assert_eq!(detect_ref.stamp().nanosec, detect_new.stamp().nanosec);
5125 assert_eq!(detect_ref.frame_id(), detect_new.frame_id());
5126 assert_eq!(detect_ref.boxes_len(), detect_new.boxes_len());
5127
5128 assert_eq!(boxes_ref.len(), boxes_new.len());
5130
5131 for (i, (a, b)) in boxes_ref.iter().zip(boxes_new.iter()).enumerate() {
5133 assert_eq!(a.center_x, b.center_x, "box[{i}].center_x");
5134 assert_eq!(a.center_y, b.center_y, "box[{i}].center_y");
5135 assert_eq!(a.width, b.width, "box[{i}].width");
5136 assert_eq!(a.height, b.height, "box[{i}].height");
5137 assert_eq!(a.label, b.label, "box[{i}].label");
5138 assert_eq!(a.score, b.score, "box[{i}].score");
5139 assert_eq!(a.distance, b.distance, "box[{i}].distance");
5140 assert_eq!(a.speed, b.speed, "box[{i}].speed");
5141 assert_eq!(a.track_id, b.track_id, "box[{i}].track_id");
5142 assert_eq!(
5143 a.track_lifetime, b.track_lifetime,
5144 "box[{i}].track_lifetime"
5145 );
5146 assert_eq!(
5147 a.track_created.sec, b.track_created.sec,
5148 "box[{i}].track_created.sec"
5149 );
5150 assert_eq!(
5151 a.track_created.nanosec, b.track_created.nanosec,
5152 "box[{i}].track_created.nanosec"
5153 );
5154 }
5155 }
5156
5157 #[test]
5161 fn model_from_cdr_collect_children_matches_boxes_and_masks() {
5162 static BYTES: &[u8] = include_bytes!("../testdata/cdr/edgefirst_msgs/Model.cdr");
5163
5164 let model_ref = Model::from_cdr(BYTES).expect("reference decode");
5166 let boxes_ref = model_ref.boxes();
5167 let masks_ref = model_ref.masks();
5168
5169 let (model_new, boxes_new, masks_new) =
5171 Model::from_cdr_collect_children(BYTES).expect("collect decode");
5172
5173 assert_eq!(model_ref.stamp().sec, model_new.stamp().sec);
5175 assert_eq!(model_ref.stamp().nanosec, model_new.stamp().nanosec);
5176 assert_eq!(model_ref.frame_id(), model_new.frame_id());
5177 assert_eq!(model_ref.boxes_len(), model_new.boxes_len());
5178 assert_eq!(model_ref.masks_len(), model_new.masks_len());
5179
5180 assert_eq!(boxes_ref.len(), boxes_new.len());
5182 for (i, (a, b)) in boxes_ref.iter().zip(boxes_new.iter()).enumerate() {
5183 assert_eq!(a.center_x, b.center_x, "box[{i}].center_x");
5184 assert_eq!(a.center_y, b.center_y, "box[{i}].center_y");
5185 assert_eq!(a.width, b.width, "box[{i}].width");
5186 assert_eq!(a.height, b.height, "box[{i}].height");
5187 assert_eq!(a.label, b.label, "box[{i}].label");
5188 assert_eq!(a.score, b.score, "box[{i}].score");
5189 assert_eq!(a.distance, b.distance, "box[{i}].distance");
5190 assert_eq!(a.speed, b.speed, "box[{i}].speed");
5191 assert_eq!(a.track_id, b.track_id, "box[{i}].track_id");
5192 assert_eq!(
5193 a.track_lifetime, b.track_lifetime,
5194 "box[{i}].track_lifetime"
5195 );
5196 assert_eq!(
5197 a.track_created.sec, b.track_created.sec,
5198 "box[{i}].track_created.sec"
5199 );
5200 assert_eq!(
5201 a.track_created.nanosec, b.track_created.nanosec,
5202 "box[{i}].track_created.nanosec"
5203 );
5204 }
5205
5206 assert_eq!(masks_ref.len(), masks_new.len());
5208 for (i, (a, b)) in masks_ref.iter().zip(masks_new.iter()).enumerate() {
5209 assert_eq!(a.height, b.height, "mask[{i}].height");
5210 assert_eq!(a.width, b.width, "mask[{i}].width");
5211 assert_eq!(a.length, b.length, "mask[{i}].length");
5212 assert_eq!(a.encoding, b.encoding, "mask[{i}].encoding");
5213 assert_eq!(a.mask, b.mask, "mask[{i}].mask");
5214 assert_eq!(a.boxed, b.boxed, "mask[{i}].boxed");
5215 }
5216 }
5217}