fromsoftware_shared/ext/
read.rs1use std::io;
2
3pub trait LengthDelimitedReadExt {
12 fn read_delimited(&mut self) -> io::Result<Vec<u8>>;
20
21 fn read_str_delimited(&mut self) -> io::Result<String> {
30 String::from_utf8(self.read_delimited()?).map_err(io::Error::other)
31 }
32}
33
34impl<T: ?Sized + io::Read> LengthDelimitedReadExt for T {
35 fn read_delimited(&mut self) -> io::Result<Vec<u8>> {
36 let mut delimiter = [0; std::mem::size_of::<u32>()];
37 if self.read(&mut delimiter)? < delimiter.len() {
38 return Err(io::Error::other("Couldn't read delimiter"));
39 }
40
41 let delimiter: usize = u32::from_le_bytes(delimiter)
42 .try_into()
43 .map_err(io::Error::other)?;
44
45 const CHUNK_SIZE: usize = 0x4000;
49 let mut result = Vec::with_capacity(std::cmp::min(delimiter, CHUNK_SIZE));
50 while result.len() < delimiter {
51 let prev_len = result.len();
52 result.resize(std::cmp::min(delimiter, prev_len + CHUNK_SIZE), 0);
53 let size = self.read(&mut result[prev_len..])?;
54
55 let expected = result.len() - prev_len;
56 if size < expected {
57 return Err(io::Error::other(format!(
58 "Expected {} bytes but only {} were read",
59 expected, size
60 )));
61 }
62 }
63
64 Ok(result)
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use super::LengthDelimitedReadExt;
71 use crate::ext::LengthDelimitedWriteExt;
72
73 #[test]
74 fn write_and_read_small_bytes() {
75 let mut writer = Vec::new();
76 assert_eq!(writer.write_delimited(&[1, 2, 3, 4, 5]).unwrap(), 9);
77
78 let mut reader = &writer[..];
79 assert_eq!(reader.read_delimited().unwrap(), &[1, 2, 3, 4, 5]);
80 }
81
82 #[test]
83 fn write_and_read_small_string() {
84 let mut writer = Vec::new();
85 assert_eq!(writer.write_str_delimited("hello!").unwrap(), 10);
86
87 let mut reader = &writer[..];
88 assert_eq!(reader.read_str_delimited().unwrap(), "hello!");
89 }
90
91 #[test]
92 fn write_and_read_large_bytes() {
93 let mut data = [0; 0x5000];
94 for (i, byte) in data.iter_mut().enumerate() {
95 *byte = (i % 255).try_into().unwrap();
96 }
97
98 let mut writer = Vec::new();
99 assert_eq!(writer.write_delimited(&data[..]).unwrap(), 0x5004);
100
101 let mut reader = &writer[..];
102 assert_eq!(reader.read_delimited().unwrap(), &data);
103 }
104}