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