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
pub trait RingBuf {
fn write(&mut self, data: &[u8]);
fn read(&mut self, data: &mut [u8]) -> (usize, bool);
}
#[repr(C)]
pub struct RingBuffer<const SIZE: usize> {
signature: u32,
read_pos: usize,
write_pos: usize,
overwritten: bool,
buf: [u8; SIZE],
}
impl<const SIZE: usize> RingBuffer<SIZE> {
const SIGNATURE: u32 = 0xb0ffe300;
fn validate(&mut self) {
let valid = self.signature == Self::SIGNATURE
&& self.read_pos < self.buf.len()
&& self.write_pos < self.buf.len();
if !valid {
self.buf.fill(0);
self.read_pos = 0;
self.write_pos = 0;
self.overwritten = false;
self.signature = Self::SIGNATURE;
}
}
}
impl<const SIZE: usize> RingBuf for RingBuffer<SIZE> {
fn write(&mut self, mut data: &[u8]) {
self.validate();
while !data.is_empty() {
let to_end = self.buf.len() - self.write_pos;
let (part, rest) = data.split_at(to_end.min(data.len()));
data = rest;
let from = self.write_pos;
let to = self.write_pos + part.len();
self.buf[from..to].copy_from_slice(part);
if from < self.read_pos && to >= self.read_pos {
self.overwritten = true;
self.read_pos = to + 1;
if self.read_pos >= self.buf.len() {
self.read_pos = 0;
}
}
self.write_pos = to;
if self.write_pos == self.buf.len() {
self.write_pos = 0;
}
}
}
fn read(&mut self, data: &mut [u8]) -> (usize, bool) {
self.validate();
let avail = if self.read_pos > self.write_pos {
self.buf.len() - self.read_pos
} else {
self.write_pos - self.read_pos
};
let n = avail.min(data.len());
let from = self.read_pos;
let to = self.read_pos + n;
data[..n].copy_from_slice(&self.buf[from..to]);
self.read_pos = to;
if self.read_pos == self.buf.len() {
self.read_pos = 0;
}
let overwritten = self.overwritten;
self.overwritten = false;
(n, overwritten)
}
}