buf_redux/buffer/
std_buf.rs

1// Copyright 2016-2018 Austin Bonander <austin.bonander@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use safemem;
10
11use std::cmp;
12
13use self::impl_::RawBuf;
14
15pub struct StdBuf {
16    buf: RawBuf,
17    pos: usize,
18    end: usize,
19}
20
21impl StdBuf {
22    pub fn with_capacity(cap: usize) -> Self {
23        StdBuf {
24            buf: RawBuf::with_capacity(cap),
25            pos: 0,
26            end: 0,
27        }
28    }
29
30    pub fn capacity(&self) -> usize {
31        self.buf.capacity()
32    }
33
34    pub fn len(&self) -> usize {
35        self.end - self.pos
36    }
37
38    pub fn usable_space(&self) -> usize {
39        self.capacity() - self.end
40    }
41
42    pub fn reserve(&mut self, additional: usize) -> bool {
43        self.check_cursors();
44        let usable_space = self.usable_space();
45
46        // there's already enough space
47        if usable_space >= additional { return false }
48
49        // attempt to reserve additional capacity in-place
50        if self.buf.reserve_in_place(additional - usable_space) {
51            return false;
52        }
53
54        // don't copy the contents of the buffer as they're irrelevant now
55        if self.pos == self.end {
56            let capacity = self.buf.capacity();
57            // free the existing memory
58            self.buf = RawBuf::with_capacity(0);
59            self.buf = RawBuf::with_capacity(capacity + additional);
60            return true;
61        }
62
63        self.buf.reserve(additional - usable_space)
64    }
65
66    pub fn make_room(&mut self) {
67        self.check_cursors();
68
69        // no room at the head of the buffer
70        if self.pos == 0 { return; }
71
72        // simply move the bytes down to the beginning
73        let len = self.len();
74
75        safemem::copy_over(unsafe { self.buf.as_mut_slice() },
76                           self.pos, 0, len);
77
78        self.pos = 0;
79        self.end = len;
80    }
81
82    pub fn buf(&self) -> &[u8] {
83        unsafe {
84            &self.buf.as_slice()[self.pos .. self.end]
85        }
86    }
87
88    pub fn buf_mut(&mut self) -> &mut [u8] {
89        unsafe {
90            &mut self.buf.as_mut_slice()[self.pos .. self.end]
91        }
92    }
93
94    pub unsafe fn write_buf(&mut self) -> &mut [u8] {
95        &mut self.buf.as_mut_slice()[self.end ..]
96    }
97
98    pub unsafe fn bytes_written(&mut self, amt: usize) {
99        self.end = cmp::min(self.end + amt, self.capacity());
100    }
101
102    pub fn consume(&mut self, amt: usize) {
103        self.pos = cmp::min(self.pos + amt, self.end);
104        self.check_cursors();
105    }
106
107    pub fn check_cursors(&mut self) -> bool {
108        if self.pos == self.end {
109            self.pos = 0;
110            self.end = 0;
111            true
112        } else {
113            false
114        }
115    }
116}
117
118#[cfg(not(feature = "nightly"))]
119mod impl_ {
120    use std::mem;
121
122    pub struct RawBuf {
123        buf: Box<[u8]>,
124    }
125
126    impl RawBuf {
127        pub fn with_capacity(capacity: usize) -> Self {
128            let mut buf = Vec::with_capacity(capacity);
129            let true_cap = buf.capacity();
130
131            unsafe {
132                buf.set_len(true_cap);
133            }
134
135            RawBuf {
136                buf: buf.into_boxed_slice(),
137            }
138        }
139
140        pub fn capacity(&self) -> usize {
141            self.buf.len()
142        }
143
144        pub fn reserve(&mut self, additional: usize) -> bool {
145            let mut buf = mem::replace(&mut self.buf, Box::new([])).into_vec();
146
147            let old_ptr = self.buf.as_ptr();
148
149            buf.reserve_exact(additional);
150
151            unsafe {
152                let new_cap = buf.capacity();
153                buf.set_len(new_cap);
154            }
155
156            self.buf = buf.into_boxed_slice();
157
158            old_ptr == self.buf.as_ptr()
159        }
160
161        pub fn reserve_in_place(&mut self, _additional: usize) -> bool {
162            // `Vec` does not support this
163            return false;
164        }
165
166        pub unsafe fn as_slice(&self) -> &[u8] {
167            &self.buf
168        }
169
170        pub unsafe fn as_mut_slice(&mut self) -> &mut [u8] {
171            &mut self.buf
172        }
173    }
174}
175
176#[cfg(feature = "nightly")]
177mod impl_ {
178    extern crate alloc;
179
180    use self::alloc::raw_vec::RawVec;
181
182    use std::slice;
183
184    pub struct RawBuf {
185        buf: RawVec<u8>,
186    }
187
188    impl RawBuf {
189        pub fn with_capacity(capacity: usize) -> Self {
190            RawBuf {
191                buf: RawVec::with_capacity(capacity)
192            }
193        }
194
195        pub fn capacity(&self) -> usize {
196            self.buf.cap()
197        }
198
199        pub fn reserve(&mut self, additional: usize) -> bool {
200            let cap = self.capacity();
201            let old_ptr = self.buf.ptr();
202            self.buf.reserve_exact(cap, additional);
203            old_ptr != self.buf.ptr()
204        }
205
206        pub fn reserve_in_place(&mut self, additional: usize) -> bool {
207            let cap = self.capacity();
208            self.buf.reserve_in_place(cap, additional)
209        }
210
211        pub unsafe fn as_slice(&self) -> &[u8] {
212            slice::from_raw_parts(self.buf.ptr(), self.buf.cap())
213        }
214
215        pub unsafe fn as_mut_slice(&mut self) -> &mut [u8] {
216            slice::from_raw_parts_mut(self.buf.ptr(), self.buf.cap())
217        }
218
219    }
220}
221
222#[test]
223fn read_into_full() {
224    use Buffer;
225
226    let mut buffer = Buffer::with_capacity(1);
227
228    assert_eq!(buffer.capacity(), 1);
229
230    let mut bytes = &[1u8, 2][..];
231
232    // Result<usize, io::Error> does not impl PartialEq
233    assert_eq!(buffer.read_from(&mut bytes).unwrap(), 1);
234    assert_eq!(buffer.read_from(&mut bytes).unwrap(), 0);
235}