use crate::{
deserializer::{consumed::Consumed, number::read_unsigned_int},
error::Result,
};
pub fn read_string(data: &[u8]) -> Result<Consumed<&str>> {
let length = read_unsigned_int(data)?;
Ok(Consumed::new(
core::str::from_utf8(
data.get(length.bytes_consumed..(length.bytes_consumed + length.value as usize))
.ok_or({
crate::error::TypedStreamError::OutOfBounds(length.value as usize, data.len())
})?,
)?,
length.bytes_consumed + length.value as usize,
))
}
#[cfg(test)]
mod string_tests {
use alloc::vec::Vec;
use crate::deserializer::{
constants::{I_16, I_32},
string::read_string,
};
#[test]
fn can_read_string() {
let data = [0x05, b'H', b'e', b'l', b'l', b'o'];
let result = read_string(&data).unwrap();
assert_eq!(result.value, "Hello");
assert_eq!(result.bytes_consumed, 6);
}
#[test]
fn can_read_string_extra() {
let data = [
0x05, b'H', b'e', b'l', b'l', b'o', b' ', b'W', b'o', b'r', b'l', b'd',
];
let result = read_string(&data).unwrap();
assert_eq!(result.value, "Hello");
assert_eq!(result.bytes_consumed, 6);
}
#[test]
fn can_read_string_long() {
let start_bytes = [I_16, 0xE8, 0x03]; let long_string: Vec<u8> = (0..1000).map(|_| b'a').collect();
let combined = start_bytes
.iter()
.chain(long_string.iter())
.copied()
.collect::<Vec<u8>>();
let result = read_string(&combined).unwrap();
assert_eq!(result.value.len(), 1000);
assert!(result.value.starts_with('a'));
assert!(result.value.ends_with('a'));
assert_eq!(result.bytes_consumed, 1003);
}
#[test]
fn can_read_string_insanely_long() {
let start_bytes = [I_32, 0x01, 0x01, 0x01, 0x01]; let long_string: Vec<u8> = (0..16843009).map(|_| b'a').collect();
let combined = start_bytes
.iter()
.chain(long_string.iter())
.copied()
.collect::<Vec<u8>>();
let result = read_string(&combined).unwrap();
assert_eq!(result.value.len(), 16843009);
assert!(result.value.starts_with('a'));
assert!(result.value.ends_with('a'));
assert_eq!(result.bytes_consumed, 16843014);
}
#[test]
fn can_read_empty_string() {
let data = [0x00];
let result = read_string(&data).unwrap();
assert_eq!(result.value, "");
assert_eq!(result.bytes_consumed, 1);
}
}