lapin_async/
buffer.rs

1use std::{cmp, ptr};
2
3#[derive(Debug,PartialEq,Clone)]
4pub(crate) struct Buffer {
5  memory:   Vec<u8>,
6  capacity: usize,
7  position: usize,
8  end:      usize
9}
10
11impl Buffer {
12  pub(crate) fn with_capacity(capacity: usize) -> Buffer {
13    Buffer {
14      memory:   vec![0; capacity],
15      capacity,
16      position: 0,
17      end:      0
18    }
19  }
20
21  pub(crate) fn grow(&mut self, new_size: usize) -> bool {
22    if self.capacity >= new_size {
23      return false;
24    }
25
26    self.memory.resize(new_size, 0);
27    self.capacity = new_size;
28    true
29  }
30
31  pub(crate) fn available_data(&self) -> usize {
32    self.end - self.position
33  }
34
35  pub(crate) fn available_space(&self) -> usize {
36    self.capacity - self.end
37  }
38
39  pub(crate) fn consume(&mut self, count: usize) -> usize {
40    let cnt        = cmp::min(count, self.available_data());
41    self.position += cnt;
42    cnt
43  }
44
45  pub(crate) fn fill(&mut self, count: usize) -> usize {
46    let cnt   = cmp::min(count, self.available_space());
47    self.end += cnt;
48    cnt
49  }
50
51  pub(crate) fn data(&self) -> &[u8] {
52    &self.memory[self.position..self.end]
53  }
54
55  pub(crate) fn space(&mut self) -> &mut [u8] {
56    &mut self.memory[self.end..self.capacity]
57  }
58
59  pub(crate) fn shift(&mut self) {
60    let length = self.end - self.position;
61    unsafe {
62      ptr::copy((&self.memory[self.position..self.end]).as_ptr(), (&mut self.memory[..length]).as_mut_ptr(), length);
63    }
64    self.position = 0;
65    self.end      = length;
66  }
67
68  pub(crate) fn shift_unless_available(&mut self, size: usize) {
69    if self.available_space() < size {
70      self.shift();
71    }
72  }
73}
74
75#[cfg(test)]
76mod tests {
77  use super::*;
78  use std::io::Write;
79
80  #[test]
81  fn fill_and_consume() {
82    let mut b = Buffer::with_capacity(10);
83    assert_eq!(b.available_data(), 0);
84    assert_eq!(b.available_space(), 10);
85    let res = b.space().write(&b"abcd"[..]).map(|size| { b.fill(size); size });
86    assert_eq!(res.ok(), Some(4));
87    assert_eq!(b.available_data(), 4);
88    assert_eq!(b.available_space(), 6);
89
90    assert_eq!(b.data(), &b"abcd"[..]);
91
92    b.consume(2);
93    assert_eq!(b.available_data(), 2);
94    assert_eq!(b.available_space(), 6);
95    assert_eq!(b.data(), &b"cd"[..]);
96
97    b.shift();
98    assert_eq!(b.available_data(), 2);
99    assert_eq!(b.available_space(), 8);
100    assert_eq!(b.data(), &b"cd"[..]);
101
102    assert_eq!(b.space().write(&b"efghijklmnop"[..]).map(|size| { b.fill(size); size }).ok(), Some(8));
103    assert_eq!(b.available_data(), 10);
104    assert_eq!(b.available_space(), 0);
105    assert_eq!(b.data(), &b"cdefghijkl"[..]);
106    b.shift();
107    assert_eq!(b.available_data(), 10);
108    assert_eq!(b.available_space(), 0);
109    assert_eq!(b.data(), &b"cdefghijkl"[..]);
110  }
111}