buf_ref_reader/buffer/
mmap.rs

1/*
2SliceDeque is quite inconvenient, e.g.:
3- you still need to resort to `unsafe {}`
4  to append data through `&mut [u8]`
5  and advance tail position accordingly,
6- you still need to be careful with pointers to head/tail
7  and actively prevent underruns/overruns,
8- borrow checker still messes up reader methods
9  (e.g. `buf.move_head()` after `buf.as_slice()`).
10Hence we drop to a lower level thing.
11
12But even this lower level buffer is not without its own warts:
13it operates with an overall size of a mirrored buffer, not one of its halves,
14which results in a lot of unnecessary `* 2` on the user's side
15and lots of `/ 2`, `% 2`, and `assert!`s in the crate that implements it.
16And, yes, this is just utterly confusing:
17why report len() of X when you can only put X/2 elements inside?
18*/
19use slice_deque::{Buffer, AllocError};
20
21/// Buffer that uses circular buffer implemented with mirrored memory maps
22pub struct MmapBuffer {
23	buf: Buffer<u8>,
24	/*
25	We keep size of a `buf`'s size on our own because `buf.len()`:
26	- returns twice the amount of data buffer can actually handle
27	  (i.e. size of mmaped region with two mirrors),
28	  which makes it confusing, and it's also an error waiting to happen,
29	- it also causes an immutable borrowing of `buf`,
30	  thus making most of manipulations with `buf`'s content inconvenient.
31	*/
32	bufsize: usize,
33	// position of data within the `buf`
34	start: usize,
35	len: usize,
36}
37impl super::Buffer for MmapBuffer {
38	type Error = AllocError;
39	fn new(size: usize) -> Result<Self, AllocError> {
40		let buf = Buffer::uninitialized(size * 2)?;
41		// slice-deque will round bufsize to the nearest page size or something,
42		// so we query it back here
43		let bufsize = buf.len() / 2;
44		Ok(MmapBuffer {
45			buf, bufsize,
46			start: 0, len: 0,
47		})
48	}
49	fn filled(&self) -> &[u8] {
50		&(unsafe {
51			self.buf.as_slice()
52		})[ self.start .. (self.start + self.len) ]
53	}
54	// make room for new data one way or the other
55	fn enlarge(&mut self) -> Result<(), AllocError> {
56		if self.start == 0 && self.len == self.bufsize {
57			/*
58			we used to have configurable increments for the bufsize
59			now though we double buffer size, just like rust's vec/raw_vec do
60			*/
61			self.bufsize *= 2;
62			let mut new = Buffer::uninitialized(self.bufsize * 2)?;
63			// see .new() for th reasons why we read bufsize back
64			self.bufsize = new.len() / 2;
65			// move data at the start of new buffer
66			unsafe {
67				core::ptr::copy(
68					self.buf.as_mut_slice()[self.start..].as_mut_ptr(),
69					new.as_mut_slice().as_mut_ptr(),
70					self.len,
71				);
72			}
73			self.start = 0;
74			self.buf = new;
75		} else {
76			// there's plenty of room in the buffer,
77			// nothing to do here
78		}
79		Ok(())
80	}
81	/*
82	return b-through-a:
83	| a--b | a--b |
84	|-b  a-|-b  a-|
85	*/
86	fn appendable(&mut self) -> &mut [u8] {
87		let end = self.start + self.len;
88		let remaining = self.bufsize - self.len;
89		&mut (unsafe {
90			self.buf.as_mut_slice()
91		})[ end .. (end+remaining) ]
92	}
93	fn grow(&mut self, amount: usize) {
94		self.len += amount;
95	}
96	/*
97	returns reference to first half of the buffer
98	up to the size of `amount`,
99	which is going to be discarded
100	after lifetime of returned slice comes to an end
101	*/
102	fn consume(&mut self, amount: usize) -> &[u8] {
103		let start = self.start;
104		let amount = std::cmp::min(amount, self.len());
105
106		self.start += amount;
107		if self.start >= self.bufsize {
108			// keep self.start within bufsize
109			self.start -= self.bufsize;
110		}
111		self.len -= amount;
112		&(unsafe {
113			self.buf.as_mut_slice()
114		})[ start .. (start+amount) ]
115	}
116	fn len(&self) -> usize {
117		self.len
118	}
119}