use crate::{
deserializer::{constants::REFERENCE_TAG, consumed::Consumed},
error::{Result, TypedStreamError},
};
#[inline(always)]
pub fn read_exact_bytes(data: &[u8], n: usize) -> Result<&[u8]> {
let range = data
.get(0..n)
.ok_or(TypedStreamError::OutOfBounds(n, data.len()))?;
Ok(range)
}
#[inline(always)]
pub fn read_byte_at(data: &[u8], idx: usize) -> Result<&u8> {
data.get(idx)
.ok_or(TypedStreamError::OutOfBounds(idx, data.len()))
}
#[inline(always)]
pub fn read_pointer(pointer: &u8) -> Result<Consumed<u64>> {
let result = u64::from(*pointer)
.checked_sub(REFERENCE_TAG)
.ok_or(TypedStreamError::InvalidPointer(*pointer))?;
Ok(Consumed::new(result, 1))
}
#[cfg(test)]
mod read_tests {
use crate::deserializer::read::{read_exact_bytes, read_pointer};
use crate::error::TypedStreamError;
#[test]
fn can_read_exact_bytes() {
let data = [0x01, 0x02, 0x03, 0x04];
let result = read_exact_bytes(&data, 4).unwrap();
assert_eq!(result, &data);
}
#[test]
fn can_read_exact_bytes_partial() {
let data = [0x01, 0x02, 0x03];
let result = read_exact_bytes(&data, 2).unwrap();
assert_eq!(result, &data[..2]);
}
#[test]
fn cannot_read_exact_bytes_out_of_bounds() {
let data = [0x01, 0x02];
let result = read_exact_bytes(&data, 3);
assert!(matches!(result, Err(TypedStreamError::OutOfBounds(3, 2))));
}
#[test]
fn can_read_pointer() {
let result = read_pointer(&0x95).unwrap();
assert_eq!(result.value, 3);
assert_eq!(result.bytes_consumed, 1);
}
#[test]
fn can_read_pointer_zero() {
let result = read_pointer(&0x92).unwrap();
assert_eq!(result.value, 0);
assert_eq!(result.bytes_consumed, 1);
}
#[test]
fn cant_read_invalid_pointer() {
let result = read_pointer(&0x10);
assert!(matches!(result, Err(TypedStreamError::InvalidPointer(16))));
}
}