-
Notifications
You must be signed in to change notification settings - Fork 13
/
buffer.rs
112 lines (92 loc) · 2.78 KB
/
buffer.rs
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
use std::io::{ErrorKind, Read, Result};
pub struct Buffer {
data: Box<[u8]>,
start: usize,
end: usize,
}
impl Buffer {
pub fn new(size: usize) -> Buffer {
Buffer {
data: vec![0u8; size].into_boxed_slice(),
start: 0,
end: 0,
}
}
pub fn len(&self) -> usize {
self.end.checked_sub(self.start).unwrap()
}
pub fn n_free(&self) -> usize {
self.data.len().checked_sub(self.end).unwrap()
}
pub fn pos(&self) -> usize {
self.start
}
pub fn replace_buffer(&mut self, mut buffer: Box<[u8]>) -> Box<[u8]> {
let n_in_buffer = self.len();
let new_end = (n_in_buffer + 15) & !0x0f; // make sure next read is aligned
let new_start = new_end.checked_sub(n_in_buffer).unwrap();
assert!(buffer.len() >= new_end);
{
let dest = &mut buffer[new_start..new_end];
let src = &self.data[self.start..self.end];
dest.copy_from_slice(src);
}
::std::mem::swap(&mut self.data, &mut buffer);
self.start = new_start;
self.end = new_end;
buffer
}
/// Move data to the start of the buffer, freeing space at the end.
pub fn clean(&mut self) {
if self.start == 0 {
return;
}
let n_in_buffer = self.len();
let new_end = (n_in_buffer + 15) & !0x0f; // make sure next read is aligned
let new_start = new_end.checked_sub(n_in_buffer).unwrap();
if new_start >= self.start {
return;
}
let dest = self.data[new_start..].as_mut_ptr();
let src = self.data[self.start..].as_ptr();
unsafe {
::std::ptr::copy(src, dest, n_in_buffer);
}
self.start = new_start;
self.end = new_end;
}
pub fn read_into<R: Read>(&mut self, reader: &mut R) -> Result<usize> {
let n_free = self.n_free();
let num_read = if n_free < 4096 {
n_free
} else {
n_free - n_free % 4096
};
let dest = &mut self.data[self.end..self.end + num_read];
let n_read;
loop {
match reader.read(dest) {
Err(e) => {
if e.kind() != ErrorKind::Interrupted {
return Err(e);
}
}
Ok(val) => {
n_read = val;
break;
}
}
}
self.end += n_read;
Ok(n_read)
}
#[inline]
pub fn data(&self) -> &[u8] {
&self.data[self.start..self.end]
}
#[inline]
pub fn consume(&mut self, count: usize) {
self.start = self.start.checked_add(count).unwrap();
debug_assert!(self.start <= self.end);
}
}