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]
266 pub fn read_var_string8(&mut self) -> Result<String, SbeDecodeError> {
267 Ok(self.read_var_string8_ref()?.to_owned())
268 }
269
270 #[inline]
276 pub fn read_var_string8_ref(&mut self) -> Result<&'a str, SbeDecodeError> {
277 let len = self.read_u8()? as usize;
278 if len == 0 {
279 return Ok("");
280 }
281 self.require(len)?;
282 let s = str::from_utf8(&self.buf[self.pos..self.pos + len])
283 .map_err(|_| SbeDecodeError::InvalidUtf8)?;
284 self.pos += len;
285 Ok(s)
286 }
287
288 #[inline]
296 pub fn read_var_string16(&mut self) -> Result<String, SbeDecodeError> {
297 Ok(self.read_var_string16_ref()?.to_owned())
298 }
299
300 #[inline]
306 pub fn read_var_string16_ref(&mut self) -> Result<&'a str, SbeDecodeError> {
307 let len = usize::from(self.read_u16_le()?);
308 if len == 0 {
309 return Ok("");
310 }
311 self.require(len)?;
312 let s = str::from_utf8(&self.buf[self.pos..self.pos + len])
313 .map_err(|_| SbeDecodeError::InvalidUtf8)?;
314 self.pos += len;
315 Ok(s)
316 }
317
318 pub fn skip_var_data8(&mut self) -> Result<(), SbeDecodeError> {
326 let len = self.read_u8()? as usize;
327 self.advance(len)
328 }
329
330 pub fn read_var_bytes8(&mut self) -> Result<Vec<u8>, SbeDecodeError> {
338 let len = self.read_u8()? as usize;
339 Ok(self.read_bytes(len)?.to_vec())
340 }
341
342 pub fn skip_var_data16(&mut self) -> Result<(), SbeDecodeError> {
348 let len = usize::from(self.read_u16_le()?);
349 self.advance(len)
350 }
351
352 pub fn read_var_bytes16(&mut self) -> Result<Vec<u8>, SbeDecodeError> {
360 let len = usize::from(self.read_u16_le()?);
361 Ok(self.read_bytes(len)?.to_vec())
362 }
363
364 #[inline]
373 pub fn read_group_header(&mut self) -> Result<(u16, u32), SbeDecodeError> {
374 let block_length = self.read_u16_le()?;
375 let num_in_group = self.read_u32_le()?;
376
377 if num_in_group > MAX_GROUP_SIZE {
378 return Err(SbeDecodeError::GroupSizeTooLarge {
379 count: num_in_group,
380 max: MAX_GROUP_SIZE,
381 });
382 }
383
384 Ok((block_length, num_in_group))
385 }
386
387 #[inline]
396 pub fn read_group_header_16(&mut self) -> Result<(u16, u16), SbeDecodeError> {
397 let block_length = self.read_u16_le()?;
398 let num_in_group = self.read_u16_le()?;
399
400 if u32::from(num_in_group) > MAX_GROUP_SIZE {
401 return Err(SbeDecodeError::GroupSizeTooLarge {
402 count: u32::from(num_in_group),
403 max: MAX_GROUP_SIZE,
404 });
405 }
406
407 Ok((block_length, num_in_group))
408 }
409
410 pub fn read_group<T, F>(
419 &mut self,
420 block_length: u16,
421 num_in_group: u32,
422 mut decode_item: F,
423 ) -> Result<Vec<T>, SbeDecodeError>
424 where
425 F: FnMut(&mut Self) -> Result<T, SbeDecodeError>,
426 {
427 let block_len = block_length as usize;
428 let count = num_in_group as usize;
429
430 self.require(count * block_len)?;
432
433 let mut items = Vec::with_capacity(count);
434 for _ in 0..count {
435 let item_start = self.pos;
436 let item = decode_item(self)?;
437 items.push(item);
438
439 self.pos = item_start + block_len;
441 }
442
443 Ok(items)
444 }
445}
446
447#[cfg(test)]
448mod tests {
449 use rstest::rstest;
450
451 use super::*;
452
453 #[rstest]
454 fn test_new_starts_at_zero() {
455 let buf = [1, 2, 3, 4];
456 let cursor = SbeCursor::new(&buf);
457 assert_eq!(cursor.pos(), 0);
458 assert_eq!(cursor.remaining(), 4);
459 }
460
461 #[rstest]
462 fn test_new_at_starts_at_offset() {
463 let buf = [1, 2, 3, 4];
464 let cursor = SbeCursor::new_at(&buf, 2);
465 assert_eq!(cursor.pos(), 2);
466 assert_eq!(cursor.remaining(), 2);
467 }
468
469 #[rstest]
470 fn test_read_u8() {
471 let buf = [0x42, 0xFF];
472 let mut cursor = SbeCursor::new(&buf);
473
474 assert_eq!(cursor.read_u8().unwrap(), 0x42);
475 assert_eq!(cursor.pos(), 1);
476
477 assert_eq!(cursor.read_u8().unwrap(), 0xFF);
478 assert_eq!(cursor.pos(), 2);
479
480 assert!(cursor.read_u8().is_err());
481 }
482
483 #[rstest]
484 fn test_read_i8() {
485 let buf = [0x7F, 0x80]; let mut cursor = SbeCursor::new(&buf);
487
488 assert_eq!(cursor.read_i8().unwrap(), 127);
489 assert_eq!(cursor.read_i8().unwrap(), -128);
490 }
491
492 #[rstest]
493 fn test_read_u16_le() {
494 let buf = [0x34, 0x12]; let mut cursor = SbeCursor::new(&buf);
496
497 assert_eq!(cursor.read_u16_le().unwrap(), 0x1234);
498 assert_eq!(cursor.pos(), 2);
499 }
500
501 #[rstest]
502 fn test_read_i64_le() {
503 let value: i64 = -1_234_567_890_123_456_789;
504 let buf = value.to_le_bytes();
505 let mut cursor = SbeCursor::new(&buf);
506
507 assert_eq!(cursor.read_i64_le().unwrap(), value);
508 assert_eq!(cursor.pos(), 8);
509 }
510
511 #[rstest]
512 #[case::u16(&[0x34][..], 2)]
513 #[case::u32(&[0x34, 0x12, 0x00][..], 4)]
514 #[case::u64(&[0; 7][..], 8)]
515 #[case::u128(&[0; 15][..], 16)]
516 fn test_multi_byte_reads_buffer_too_short(#[case] buf: &[u8], #[case] needed: usize) {
517 let mut cursor = SbeCursor::new(buf);
518 let err = match needed {
519 2 => cursor.read_u16_le().map(|_| ()).unwrap_err(),
520 4 => cursor.read_u32_le().map(|_| ()).unwrap_err(),
521 8 => cursor.read_u64_le().map(|_| ()).unwrap_err(),
522 16 => cursor.read_u128_le().map(|_| ()).unwrap_err(),
523 _ => unreachable!(),
524 };
525
526 assert_eq!(
527 err,
528 SbeDecodeError::BufferTooShort {
529 expected: needed,
530 actual: buf.len()
531 }
532 );
533 assert_eq!(cursor.pos(), 0, "position must not advance on error");
534 }
535
536 #[rstest]
537 fn test_read_optional_i64_null() {
538 let buf = i64::MIN.to_le_bytes();
539 let mut cursor = SbeCursor::new(&buf);
540
541 assert_eq!(cursor.read_optional_i64_le().unwrap(), None);
542 }
543
544 #[rstest]
545 fn test_read_optional_i64_present() {
546 let value: i64 = 12345;
547 let buf = value.to_le_bytes();
548 let mut cursor = SbeCursor::new(&buf);
549
550 assert_eq!(cursor.read_optional_i64_le().unwrap(), Some(12345));
551 }
552
553 #[rstest]
554 fn test_read_var_string8() {
555 let mut buf = vec![5]; buf.extend_from_slice(b"hello");
557 let mut cursor = SbeCursor::new(&buf);
558
559 assert_eq!(cursor.read_var_string8().unwrap(), "hello");
560 assert_eq!(cursor.pos(), 6); }
562
563 #[rstest]
564 fn test_read_var_string8_empty() {
565 let buf = [0]; let mut cursor = SbeCursor::new(&buf);
567
568 assert_eq!(cursor.read_var_string8().unwrap(), "");
569 assert_eq!(cursor.pos(), 1);
570 }
571
572 #[rstest]
573 fn test_read_var_string8_invalid_utf8() {
574 let buf = [2, 0xFF, 0xFE]; let mut cursor = SbeCursor::new(&buf);
576
577 assert!(matches!(
578 cursor.read_var_string8(),
579 Err(SbeDecodeError::InvalidUtf8)
580 ));
581 }
582
583 #[rstest]
584 fn test_read_group_header() {
585 let buf = [24, 0, 3, 0, 0, 0];
587 let mut cursor = SbeCursor::new(&buf);
588
589 let (block_len, count) = cursor.read_group_header().unwrap();
590 assert_eq!(block_len, 24);
591 assert_eq!(count, 3);
592 assert_eq!(cursor.pos(), 6);
593 }
594
595 #[rstest]
596 fn test_read_group_header_too_large() {
597 let count = MAX_GROUP_SIZE + 1;
599 let mut buf = vec![24, 0]; buf.extend_from_slice(&count.to_le_bytes());
601 let mut cursor = SbeCursor::new(&buf);
602
603 assert!(matches!(
604 cursor.read_group_header(),
605 Err(SbeDecodeError::GroupSizeTooLarge { .. })
606 ));
607 }
608
609 #[rstest]
610 fn test_read_group() {
611 let mut buf = Vec::new();
613 buf.extend_from_slice(&100u32.to_le_bytes()); buf.extend_from_slice(&200u32.to_le_bytes()); let mut cursor = SbeCursor::new(&buf);
617 let items: Vec<u32> = cursor
618 .read_group(4, 2, super::SbeCursor::read_u32_le)
619 .unwrap();
620
621 assert_eq!(items, vec![100, 200]);
622 assert_eq!(cursor.pos(), 8);
623 }
624
625 #[rstest]
626 fn test_read_group_respects_block_length() {
627 let mut buf = Vec::new();
629 buf.extend_from_slice(&100u32.to_le_bytes());
630 buf.extend_from_slice(&[0, 0, 0, 0]); buf.extend_from_slice(&200u32.to_le_bytes());
632 buf.extend_from_slice(&[0, 0, 0, 0]); let mut cursor = SbeCursor::new(&buf);
635 let items: Vec<u32> = cursor
636 .read_group(8, 2, super::SbeCursor::read_u32_le)
637 .unwrap();
638
639 assert_eq!(items, vec![100, 200]);
640 assert_eq!(cursor.pos(), 16); }
642
643 #[rstest]
644 fn test_require_success() {
645 let buf = [1, 2, 3, 4];
646 let cursor = SbeCursor::new(&buf);
647
648 assert!(cursor.require(4).is_ok());
649 assert!(cursor.require(3).is_ok());
650 }
651
652 #[rstest]
653 fn test_require_failure() {
654 let buf = [1, 2];
655 let cursor = SbeCursor::new(&buf);
656
657 let err = cursor.require(3).unwrap_err();
658 assert_eq!(
659 err,
660 SbeDecodeError::BufferTooShort {
661 expected: 3,
662 actual: 2
663 }
664 );
665 }
666
667 #[rstest]
668 fn test_advance() {
669 let buf = [1, 2, 3, 4];
670 let mut cursor = SbeCursor::new(&buf);
671
672 cursor.advance(2).unwrap();
673 assert_eq!(cursor.pos(), 2);
674 assert_eq!(cursor.remaining(), 2);
675
676 assert!(cursor.advance(3).is_err());
677 }
678
679 #[rstest]
680 fn test_peek() {
681 let buf = [1, 2, 3, 4];
682 let mut cursor = SbeCursor::new(&buf);
683
684 assert_eq!(cursor.peek(), &[1, 2, 3, 4]);
685 cursor.advance(2).unwrap();
686 assert_eq!(cursor.peek(), &[3, 4]);
687 }
688
689 #[rstest]
690 fn test_reset() {
691 let buf = [1, 2, 3, 4];
692 let mut cursor = SbeCursor::new(&buf);
693
694 cursor.advance(3).unwrap();
695 assert_eq!(cursor.pos(), 3);
696
697 cursor.reset();
698 assert_eq!(cursor.pos(), 0);
699 assert_eq!(cursor.remaining(), 4);
700 }
701
702 #[rstest]
703 #[case::short(false)]
704 #[case::wide(true)]
705 fn test_var_bytes_preserve_binary_and_position(#[case] wide: bool) {
706 let mut buf = if wide { vec![3, 0] } else { vec![3] };
707 buf.extend_from_slice(&[0xff, 0, 0x80, 0x42]);
708 let mut read = SbeCursor::new(&buf);
709 let mut skip = read.clone();
710
711 let bytes = if wide {
712 skip.skip_var_data16().unwrap();
713 read.read_var_bytes16().unwrap()
714 } else {
715 skip.skip_var_data8().unwrap();
716 read.read_var_bytes8().unwrap()
717 };
718
719 assert_eq!(bytes, [0xff, 0, 0x80]);
720 assert_eq!(read.pos(), buf.len() - 1);
721 assert_eq!(skip.pos(), read.pos());
722 assert_eq!(read.peek(), [0x42]);
723 assert_eq!(skip.peek(), [0x42]);
724 }
725
726 #[rstest]
727 #[case::short(false)]
728 #[case::wide(true)]
729 fn test_var_bytes_reject_truncated_payload(#[case] wide: bool) {
730 let buf = if wide {
731 vec![3, 0, 0xff]
732 } else {
733 vec![3, 0xff]
734 };
735
736 let prefix = if wide { 2 } else { 1 };
737 let mut read = SbeCursor::new(&buf);
738 let mut skip = read.clone();
739
740 let (read_result, skip_result) = if wide {
741 (read.read_var_bytes16(), skip.skip_var_data16())
742 } else {
743 (read.read_var_bytes8(), skip.skip_var_data8())
744 };
745
746 let expected = SbeDecodeError::BufferTooShort {
747 expected: prefix + 3,
748 actual: buf.len(),
749 };
750
751 assert_eq!(read_result, Err(expected.clone()));
752 assert_eq!(skip_result, Err(expected));
753 assert_eq!(read.pos(), prefix);
754 assert_eq!(skip.pos(), prefix);
755 }
756
757 #[rstest]
758 fn test_read_group_propagates_item_error() {
759 let mut cursor = SbeCursor::new(&[1, 2, 3, 4]);
760
761 let result = cursor.read_group(2, 2, |entry| {
762 let value = entry.read_u8()?;
763 if value == 3 {
764 Err(SbeDecodeError::InvalidValue { field: "entry" })
765 } else {
766 Ok(value)
767 }
768 });
769
770 assert_eq!(result, Err(SbeDecodeError::InvalidValue { field: "entry" }));
771 assert_eq!(cursor.pos(), 3);
772 }
773}