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
use std::io::{Read, Result, ErrorKind};
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;
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
}
pub fn clean(&mut self) {
if self.start == 0 {
return
}
let n_in_buffer = self.len();
let new_end = (n_in_buffer + 15) & !0x0f;
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);
}
}