1use crate::error::IoError;
2use core::usize;
3
4type Result<T> = core::result::Result<T, IoError>;
5
6#[derive(Clone, Copy)]
7pub enum SeekFrom {
8 Start(usize),
9 End(isize),
10 Current(isize),
11}
12
13pub struct BufferCursor<T: AsRef<[u8]>> {
15 data: T,
16 pos: usize,
17}
18
19impl<T: AsRef<[u8]>> BufferCursor<T> {
20 pub fn into_inner(self) -> T {
21 self.data
22 }
23}
24
25impl<T: AsRef<[u8]>> BufferCursor<T> {
26 pub fn new(data: T) -> Self {
27 Self { data, pos: 0 }
28 }
29}
30
31impl<T: AsRef<[u8]>> SeekableAsset for BufferCursor<T> {
32 fn seek(&mut self, pos: SeekFrom) -> Result<usize> {
33 let new_pos = match pos {
34 SeekFrom::Start(pos) => pos as isize,
35 SeekFrom::End(pos) => self.data.as_ref().len() as isize + pos,
36 SeekFrom::Current(pos) => self.pos as isize + pos,
37 };
38 if new_pos < 0 {
39 return Err(IoError::SeekBeforeStart);
40 }
41 self.pos = new_pos as usize;
42
43 Ok(self.pos)
44 }
45}
46
47impl<T: AsRef<[u8]>> LoadableAsset for BufferCursor<T> {
48 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
49 let data = self.data.as_ref();
50
51 if self.pos >= data.len() {
52 return Err(IoError::UnexpectedEof);
53 }
54 let bytes_to_read = buf.len().min(data.len() - self.pos);
55 buf[0..bytes_to_read].copy_from_slice(&data[self.pos..self.pos + bytes_to_read]);
56 self.pos += bytes_to_read;
57 Ok(bytes_to_read)
58 }
59}
60
61pub trait SeekableAsset {
62 fn seek(&mut self, pos: SeekFrom) -> Result<usize>;
64}
65
66pub trait LoadableAsset {
69 fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
72
73 fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
74 while !buf.is_empty() {
75 match self.read(buf)? {
76 0 => {
77 break;
78 }
79 n => {
80 let tmp = buf;
81 buf = &mut tmp[n..];
82 }
83 }
84 }
85 if !buf.is_empty() {
86 return Err(IoError::UnexpectedEof);
87 }
88
89 Ok(())
90 }
91}
92
93pub trait DataRecorder {
94 fn write(&mut self, buf: &[u8]) -> Result<usize>;
98
99 fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
103 while !buf.is_empty() {
104 match self.write(buf)? {
105 0 => return Err(IoError::WriteZero),
106 n => buf = &buf[n..],
107 }
108 }
109 Ok(())
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn buffer_cursor_seek_works() {
119 const BUFFER: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
120 let mut cursor = BufferCursor::new(BUFFER);
121
122 let mut tmp = [0u8; 1];
123 cursor.read_exact(&mut tmp).unwrap();
124 assert_eq!(tmp[0], 1);
125
126 cursor.seek(SeekFrom::Current(1)).unwrap();
127 cursor.read_exact(&mut tmp).unwrap();
128 assert_eq!(tmp[0], 3);
129
130 cursor.seek(SeekFrom::Start(2)).unwrap();
131 cursor.read_exact(&mut tmp).unwrap();
132 assert_eq!(tmp[0], 3);
133
134 let mut tmp = [0u8; 3];
135 cursor.seek(SeekFrom::End(-2)).unwrap();
136 let read_bytes = cursor.read(&mut tmp).unwrap();
137 assert_eq!(read_bytes, 2);
138 assert_eq!(tmp[0], 9);
139 assert_eq!(tmp[1], 10);
140 }
141}