1use std::str;
19
20use super::error::{MAX_GROUP_SIZE, SbeDecodeError};
21
22#[derive(Debug, Clone)]
27pub struct SbeCursor<'a> {
28 buf: &'a [u8],
29 pos: usize,
30}
31
32impl<'a> SbeCursor<'a> {
33 #[must_use]
35 pub const fn new(buf: &'a [u8]) -> Self {
36 Self { buf, pos: 0 }
37 }
38
39 #[must_use]
41 pub const fn new_at(buf: &'a [u8], pos: usize) -> Self {
42 Self { buf, pos }
43 }
44
45 #[must_use]
47 pub const fn pos(&self) -> usize {
48 self.pos
49 }
50
51 #[must_use]
53 pub const fn remaining(&self) -> usize {
54 self.buf.len().saturating_sub(self.pos)
55 }
56
57 #[must_use]
59 pub const fn buffer(&self) -> &'a [u8] {
60 self.buf
61 }
62
63 #[must_use]
65 pub fn peek(&self) -> &'a [u8] {
66 &self.buf[self.pos..]
67 }
68
69 #[inline]
75 pub fn require(&self, n: usize) -> Result<(), SbeDecodeError> {
76 if self.remaining() < n {
77 return Err(SbeDecodeError::BufferTooShort {
78 expected: self.pos + n,
79 actual: self.buf.len(),
80 });
81 }
82 Ok(())
83 }
84
85 #[inline]
91 pub fn advance(&mut self, n: usize) -> Result<(), SbeDecodeError> {
92 self.require(n)?;
93 self.pos += n;
94 Ok(())
95 }
96
97 #[inline]
101 pub fn skip(&mut self, n: usize) {
102 self.pos += n;
103 }
104
105 pub fn reset(&mut self) {
107 self.pos = 0;
108 }
109
110 pub fn set_pos(&mut self, pos: usize) {
112 self.pos = pos;
113 }
114
115 #[inline]
121 pub fn read_u8(&mut self) -> Result<u8, SbeDecodeError> {
122 self.require(1)?;
123 let value = self.buf[self.pos];
124 self.pos += 1;
125 Ok(value)
126 }
127
128 #[inline]
134 pub fn read_i8(&mut self) -> Result<i8, SbeDecodeError> {
135 self.require(1)?;
136 let value = self.buf[self.pos] as i8;
137 self.pos += 1;
138 Ok(value)
139 }
140
141 #[inline]
147 pub fn read_u16_le(&mut self) -> Result<u16, SbeDecodeError> {
148 Ok(u16::from_le_bytes(self.read_array::<2>()?))
149 }
150
151 #[inline]
157 pub fn read_i16_le(&mut self) -> Result<i16, SbeDecodeError> {
158 Ok(i16::from_le_bytes(self.read_array::<2>()?))
159 }
160
161 #[inline]
167 pub fn read_u32_le(&mut self) -> Result<u32, SbeDecodeError> {
168 Ok(u32::from_le_bytes(self.read_array::<4>()?))
169 }
170
171 #[inline]
177 pub fn read_i32_le(&mut self) -> Result<i32, SbeDecodeError> {
178 Ok(i32::from_le_bytes(self.read_array::<4>()?))
179 }
180
181 #[inline]
187 pub fn read_u64_le(&mut self) -> Result<u64, SbeDecodeError> {
188 Ok(u64::from_le_bytes(self.read_array::<8>()?))
189 }
190
191 #[inline]
197 pub fn read_i64_le(&mut self) -> Result<i64, SbeDecodeError> {
198 Ok(i64::from_le_bytes(self.read_array::<8>()?))
199 }
200
201 #[inline]
207 pub fn read_u128_le(&mut self) -> Result<u128, SbeDecodeError> {
208 Ok(u128::from_le_bytes(self.read_array::<16>()?))
209 }
210
211 #[inline]
217 pub fn read_i128_le(&mut self) -> Result<i128, SbeDecodeError> {
218 Ok(i128::from_le_bytes(self.read_array::<16>()?))
219 }
220
221 #[inline]
227 pub fn read_optional_i64_le(&mut self) -> Result<Option<i64>, SbeDecodeError> {
228 let value = self.read_i64_le()?;
229 Ok(if value == i64::MIN { None } else { Some(value) })
230 }
231
232 #[inline]
238 pub fn read_bytes(&mut self, n: usize) -> Result<&'a [u8], SbeDecodeError> {
239 self.require(n)?;
240 let slice = &self.buf[self.pos..self.pos + n];
241 self.pos += n;
242 Ok(slice)
243 }
244
245 #[inline]
249 fn read_array<const N: usize>(&mut self) -> Result<[u8; N], SbeDecodeError> {
250 self.require(N)?;
251 let bytes: [u8; N] = self.buf[self.pos..self.pos + N]
252 .try_into()
253 .expect("slice length matches N");
254 self.pos += N;
255 Ok(bytes)
256 }
257
258 #[inline]
267 pub fn read_var_string8(&mut self) -> Result<String, SbeDecodeError> {
268 Ok(self.read_var_string8_ref()?.to_owned())
269 }
270
271 #[inline]
278 pub fn read_var_string8_ref(&mut self) -> Result<&'a str, SbeDecodeError> {
279 let len = self.read_u8()? as usize;
280 if len == 0 {
281 return Ok("");
282 }
283 self.require(len)?;
284 let s = str::from_utf8(&self.buf[self.pos..self.pos + len])
285 .map_err(|_| SbeDecodeError::InvalidUtf8)?;
286 self.pos += len;
287 Ok(s)
288 }
289
290 #[inline]
299 pub fn read_var_string16(&mut self) -> Result<String, SbeDecodeError> {
300 Ok(self.read_var_string16_ref()?.to_owned())
301 }
302
303 #[inline]
310 pub fn read_var_string16_ref(&mut self) -> Result<&'a str, SbeDecodeError> {
311 let len = usize::from(self.read_u16_le()?);
312 if len == 0 {
313 return Ok("");
314 }
315 self.require(len)?;
316 let s = str::from_utf8(&self.buf[self.pos..self.pos + len])
317 .map_err(|_| SbeDecodeError::InvalidUtf8)?;
318 self.pos += len;
319 Ok(s)
320 }
321
322 pub fn skip_var_data8(&mut self) -> Result<(), SbeDecodeError> {
330 let len = self.read_u8()? as usize;
331 self.advance(len)
332 }
333
334 pub fn read_var_bytes8(&mut self) -> Result<Vec<u8>, SbeDecodeError> {
342 let len = self.read_u8()? as usize;
343 Ok(self.read_bytes(len)?.to_vec())
344 }
345
346 pub fn skip_var_data16(&mut self) -> Result<(), SbeDecodeError> {
352 let len = usize::from(self.read_u16_le()?);
353 self.advance(len)
354 }
355
356 pub fn read_var_bytes16(&mut self) -> Result<Vec<u8>, SbeDecodeError> {
364 let len = usize::from(self.read_u16_le()?);
365 Ok(self.read_bytes(len)?.to_vec())
366 }
367
368 #[inline]
377 pub fn read_group_header(&mut self) -> Result<(u16, u32), SbeDecodeError> {
378 let block_length = self.read_u16_le()?;
379 let num_in_group = self.read_u32_le()?;
380
381 if num_in_group > MAX_GROUP_SIZE {
382 return Err(SbeDecodeError::GroupSizeTooLarge {
383 count: num_in_group,
384 max: MAX_GROUP_SIZE,
385 });
386 }
387
388 Ok((block_length, num_in_group))
389 }
390
391 #[inline]
400 pub fn read_group_header_16(&mut self) -> Result<(u16, u16), SbeDecodeError> {
401 let block_length = self.read_u16_le()?;
402 let num_in_group = self.read_u16_le()?;
403
404 if u32::from(num_in_group) > MAX_GROUP_SIZE {
405 return Err(SbeDecodeError::GroupSizeTooLarge {
406 count: u32::from(num_in_group),
407 max: MAX_GROUP_SIZE,
408 });
409 }
410
411 Ok((block_length, num_in_group))
412 }
413
414 pub fn read_group<T, F>(
424 &mut self,
425 block_length: u16,
426 num_in_group: u32,
427 mut decode_item: F,
428 ) -> Result<Vec<T>, SbeDecodeError>
429 where
430 F: FnMut(&mut Self) -> Result<T, SbeDecodeError>,
431 {
432 let block_len = block_length as usize;
433 let count = num_in_group as usize;
434
435 self.require(count * block_len)?;
437
438 let mut items = Vec::with_capacity(count);
439 for _ in 0..count {
440 let item_start = self.pos;
441 let item = decode_item(self)?;
442 items.push(item);
443
444 self.pos = item_start + block_len;
446 }
447
448 Ok(items)
449 }
450}
451
452#[cfg(test)]
453mod tests {
454 use rstest::rstest;
455
456 use super::*;
457
458 #[rstest]
459 fn test_new_starts_at_zero() {
460 let buf = [1, 2, 3, 4];
461 let cursor = SbeCursor::new(&buf);
462 assert_eq!(cursor.pos(), 0);
463 assert_eq!(cursor.remaining(), 4);
464 }
465
466 #[rstest]
467 fn test_new_at_starts_at_offset() {
468 let buf = [1, 2, 3, 4];
469 let cursor = SbeCursor::new_at(&buf, 2);
470 assert_eq!(cursor.pos(), 2);
471 assert_eq!(cursor.remaining(), 2);
472 }
473
474 #[rstest]
475 fn test_read_u8() {
476 let buf = [0x42, 0xFF];
477 let mut cursor = SbeCursor::new(&buf);
478
479 assert_eq!(cursor.read_u8().unwrap(), 0x42);
480 assert_eq!(cursor.pos(), 1);
481
482 assert_eq!(cursor.read_u8().unwrap(), 0xFF);
483 assert_eq!(cursor.pos(), 2);
484
485 assert!(cursor.read_u8().is_err());
486 }
487
488 #[rstest]
489 fn test_read_i8() {
490 let buf = [0x7F, 0x80]; let mut cursor = SbeCursor::new(&buf);
492
493 assert_eq!(cursor.read_i8().unwrap(), 127);
494 assert_eq!(cursor.read_i8().unwrap(), -128);
495 }
496
497 #[rstest]
498 fn test_read_u16_le() {
499 let buf = [0x34, 0x12]; let mut cursor = SbeCursor::new(&buf);
501
502 assert_eq!(cursor.read_u16_le().unwrap(), 0x1234);
503 assert_eq!(cursor.pos(), 2);
504 }
505
506 #[rstest]
507 fn test_read_i64_le() {
508 let value: i64 = -1_234_567_890_123_456_789;
509 let buf = value.to_le_bytes();
510 let mut cursor = SbeCursor::new(&buf);
511
512 assert_eq!(cursor.read_i64_le().unwrap(), value);
513 assert_eq!(cursor.pos(), 8);
514 }
515
516 #[rstest]
517 #[case::u16(&[0x34][..], 2)]
518 #[case::u32(&[0x34, 0x12, 0x00][..], 4)]
519 #[case::u64(&[0; 7][..], 8)]
520 #[case::u128(&[0; 15][..], 16)]
521 fn test_multi_byte_reads_buffer_too_short(#[case] buf: &[u8], #[case] needed: usize) {
522 let mut cursor = SbeCursor::new(buf);
523 let err = match needed {
524 2 => cursor.read_u16_le().map(|_| ()).unwrap_err(),
525 4 => cursor.read_u32_le().map(|_| ()).unwrap_err(),
526 8 => cursor.read_u64_le().map(|_| ()).unwrap_err(),
527 16 => cursor.read_u128_le().map(|_| ()).unwrap_err(),
528 _ => unreachable!(),
529 };
530
531 assert_eq!(
532 err,
533 SbeDecodeError::BufferTooShort {
534 expected: needed,
535 actual: buf.len()
536 }
537 );
538 assert_eq!(cursor.pos(), 0, "position must not advance on error");
539 }
540
541 #[rstest]
542 fn test_read_optional_i64_null() {
543 let buf = i64::MIN.to_le_bytes();
544 let mut cursor = SbeCursor::new(&buf);
545
546 assert_eq!(cursor.read_optional_i64_le().unwrap(), None);
547 }
548
549 #[rstest]
550 fn test_read_optional_i64_present() {
551 let value: i64 = 12345;
552 let buf = value.to_le_bytes();
553 let mut cursor = SbeCursor::new(&buf);
554
555 assert_eq!(cursor.read_optional_i64_le().unwrap(), Some(12345));
556 }
557
558 #[rstest]
559 fn test_read_var_string8() {
560 let mut buf = vec![5]; buf.extend_from_slice(b"hello");
562 let mut cursor = SbeCursor::new(&buf);
563
564 assert_eq!(cursor.read_var_string8().unwrap(), "hello");
565 assert_eq!(cursor.pos(), 6); }
567
568 #[rstest]
569 fn test_read_var_string8_empty() {
570 let buf = [0]; let mut cursor = SbeCursor::new(&buf);
572
573 assert_eq!(cursor.read_var_string8().unwrap(), "");
574 assert_eq!(cursor.pos(), 1);
575 }
576
577 #[rstest]
578 fn test_read_var_string8_invalid_utf8() {
579 let buf = [2, 0xFF, 0xFE]; let mut cursor = SbeCursor::new(&buf);
581
582 assert!(matches!(
583 cursor.read_var_string8(),
584 Err(SbeDecodeError::InvalidUtf8)
585 ));
586 }
587
588 #[rstest]
589 fn test_read_group_header() {
590 let buf = [24, 0, 3, 0, 0, 0];
592 let mut cursor = SbeCursor::new(&buf);
593
594 let (block_len, count) = cursor.read_group_header().unwrap();
595 assert_eq!(block_len, 24);
596 assert_eq!(count, 3);
597 assert_eq!(cursor.pos(), 6);
598 }
599
600 #[rstest]
601 fn test_read_group_header_too_large() {
602 let count = MAX_GROUP_SIZE + 1;
604 let mut buf = vec![24, 0]; buf.extend_from_slice(&count.to_le_bytes());
606 let mut cursor = SbeCursor::new(&buf);
607
608 assert!(matches!(
609 cursor.read_group_header(),
610 Err(SbeDecodeError::GroupSizeTooLarge { .. })
611 ));
612 }
613
614 #[rstest]
615 fn test_read_group() {
616 let mut buf = Vec::new();
618 buf.extend_from_slice(&100u32.to_le_bytes()); buf.extend_from_slice(&200u32.to_le_bytes()); let mut cursor = SbeCursor::new(&buf);
622 let items: Vec<u32> = cursor
623 .read_group(4, 2, super::SbeCursor::read_u32_le)
624 .unwrap();
625
626 assert_eq!(items, vec![100, 200]);
627 assert_eq!(cursor.pos(), 8);
628 }
629
630 #[rstest]
631 fn test_read_group_respects_block_length() {
632 let mut buf = Vec::new();
634 buf.extend_from_slice(&100u32.to_le_bytes());
635 buf.extend_from_slice(&[0, 0, 0, 0]); buf.extend_from_slice(&200u32.to_le_bytes());
637 buf.extend_from_slice(&[0, 0, 0, 0]); let mut cursor = SbeCursor::new(&buf);
640 let items: Vec<u32> = cursor
641 .read_group(8, 2, super::SbeCursor::read_u32_le)
642 .unwrap();
643
644 assert_eq!(items, vec![100, 200]);
645 assert_eq!(cursor.pos(), 16); }
647
648 #[rstest]
649 fn test_require_success() {
650 let buf = [1, 2, 3, 4];
651 let cursor = SbeCursor::new(&buf);
652
653 assert!(cursor.require(4).is_ok());
654 assert!(cursor.require(3).is_ok());
655 }
656
657 #[rstest]
658 fn test_require_failure() {
659 let buf = [1, 2];
660 let cursor = SbeCursor::new(&buf);
661
662 let err = cursor.require(3).unwrap_err();
663 assert_eq!(
664 err,
665 SbeDecodeError::BufferTooShort {
666 expected: 3,
667 actual: 2
668 }
669 );
670 }
671
672 #[rstest]
673 fn test_advance() {
674 let buf = [1, 2, 3, 4];
675 let mut cursor = SbeCursor::new(&buf);
676
677 cursor.advance(2).unwrap();
678 assert_eq!(cursor.pos(), 2);
679 assert_eq!(cursor.remaining(), 2);
680
681 assert!(cursor.advance(3).is_err());
682 }
683
684 #[rstest]
685 fn test_peek() {
686 let buf = [1, 2, 3, 4];
687 let mut cursor = SbeCursor::new(&buf);
688
689 assert_eq!(cursor.peek(), &[1, 2, 3, 4]);
690 cursor.advance(2).unwrap();
691 assert_eq!(cursor.peek(), &[3, 4]);
692 }
693
694 #[rstest]
695 fn test_reset() {
696 let buf = [1, 2, 3, 4];
697 let mut cursor = SbeCursor::new(&buf);
698
699 cursor.advance(3).unwrap();
700 assert_eq!(cursor.pos(), 3);
701
702 cursor.reset();
703 assert_eq!(cursor.pos(), 0);
704 assert_eq!(cursor.remaining(), 4);
705 }
706
707 #[rstest]
708 #[case::short(false)]
709 #[case::wide(true)]
710 fn test_var_bytes_preserve_binary_and_position(#[case] wide: bool) {
711 let mut buf = if wide { vec![3, 0] } else { vec![3] };
712 buf.extend_from_slice(&[0xff, 0, 0x80, 0x42]);
713 let mut read = SbeCursor::new(&buf);
714 let mut skip = read.clone();
715
716 let bytes = if wide {
717 skip.skip_var_data16().unwrap();
718 read.read_var_bytes16().unwrap()
719 } else {
720 skip.skip_var_data8().unwrap();
721 read.read_var_bytes8().unwrap()
722 };
723
724 assert_eq!(bytes, [0xff, 0, 0x80]);
725 assert_eq!(read.pos(), buf.len() - 1);
726 assert_eq!(skip.pos(), read.pos());
727 assert_eq!(read.peek(), [0x42]);
728 assert_eq!(skip.peek(), [0x42]);
729 }
730
731 #[rstest]
732 #[case::short(false)]
733 #[case::wide(true)]
734 fn test_var_bytes_reject_truncated_payload(#[case] wide: bool) {
735 let buf = if wide {
736 vec![3, 0, 0xff]
737 } else {
738 vec![3, 0xff]
739 };
740
741 let prefix = if wide { 2 } else { 1 };
742 let mut read = SbeCursor::new(&buf);
743 let mut skip = read.clone();
744
745 let (read_result, skip_result) = if wide {
746 (read.read_var_bytes16(), skip.skip_var_data16())
747 } else {
748 (read.read_var_bytes8(), skip.skip_var_data8())
749 };
750
751 let expected = SbeDecodeError::BufferTooShort {
752 expected: prefix + 3,
753 actual: buf.len(),
754 };
755
756 assert_eq!(read_result, Err(expected.clone()));
757 assert_eq!(skip_result, Err(expected));
758 assert_eq!(read.pos(), prefix);
759 assert_eq!(skip.pos(), prefix);
760 }
761
762 #[rstest]
763 fn test_read_group_propagates_item_error() {
764 let mut cursor = SbeCursor::new(&[1, 2, 3, 4]);
765
766 let result = cursor.read_group(2, 2, |entry| {
767 let value = entry.read_u8()?;
768 if value == 3 {
769 Err(SbeDecodeError::InvalidValue { field: "entry" })
770 } else {
771 Ok(value)
772 }
773 });
774
775 assert_eq!(result, Err(SbeDecodeError::InvalidValue { field: "entry" }));
776 assert_eq!(cursor.pos(), 3);
777 }
778}