1pub mod compose;
2pub mod del;
3pub mod empty;
4pub mod evt;
5pub mod full;
6pub mod integer;
7pub mod item;
8pub mod list;
9pub mod next;
10pub mod push;
11pub mod read;
12pub mod request;
13pub mod u;
14pub mod write;
15
16use crate::evt::Event;
17use crate::request::Request;
18
19use crate::item::{Item, Name};
20
21fn remove_item<R>(buf: &mut R, n: Name) -> Result<u64, Event>
22where
23 R: RingBuffer,
24{
25 let q: Request = Request::Del(n);
26 match buf.handle(q) {
27 Event::Success => Ok(1),
28 e => Err(e),
29 }
30}
31
32fn remove_broken_item<R>(buf: &mut R, n: Name) -> Result<u64, Event>
33where
34 R: RingBuffer,
35{
36 let q: Request = Request::Get(n);
37 match buf.handle(q) {
38 Event::Broken(broken_name) => remove_item(buf, broken_name),
39 _ => Ok(0),
40 }
41}
42
43fn remove_broken_items<R>(buf: &mut R, names: Vec<Name>) -> Result<u64, Event>
44where
45 R: RingBuffer,
46{
47 names.into_iter().try_fold(0, |tot, name| {
48 remove_broken_item(buf, name).map(|cnt: u64| cnt + tot)
49 })
50}
51
52fn remove_broken_items_from_list<R>(buf: &mut R) -> Result<u64, Event>
53where
54 R: RingBuffer,
55{
56 let q: Request = Request::List;
57 match buf.handle(q) {
58 Event::NamesGot(names) => remove_broken_items(buf, names),
59 e => Err(e),
60 }
61}
62
63pub fn remove_broken_buffers<R>(buf: &mut R) -> Event
67where
68 R: RingBuffer,
69{
70 remove_broken_items_from_list(buf)
71 .map(Event::BrokenItemsRemoved)
72 .unwrap_or_else(|e| {
73 Event::UnexpectedError(format!("Unable to remove broken items: {:#?}", e))
74 })
75}
76
77pub trait RingBuffer {
79 fn handle(&mut self, req: Request) -> Event;
80}
81
82pub fn ring_buffer_new<R>(mut r: R) -> impl FnMut(Request) -> Event
84where
85 R: RingBuffer,
86{
87 move |req: Request| r.handle(req)
88}
89
90pub struct FsRingBuffer<G, D, P, L> {
92 pub get: G,
93 pub del: D,
94 pub push: P,
95 pub list: L,
96}
97
98impl<G, D, P, L> FsRingBuffer<G, D, P, L>
99where
100 G: Fn(Name) -> Event,
101 D: Fn(Name) -> Event,
102 P: FnMut(Item) -> Event,
103 L: Fn() -> Event,
104{
105 fn handle_get(&mut self, name: Name) -> Event {
106 (self.get)(name)
107 }
108
109 fn handle_del(&mut self, name: Name) -> Event {
110 (self.del)(name)
111 }
112
113 fn handle_push(&mut self, item: Item) -> Event {
114 (self.push)(item)
115 }
116
117 fn handle_list(&mut self) -> Event {
118 (self.list)()
119 }
120}
121
122impl<G, D, P, L> RingBuffer for FsRingBuffer<G, D, P, L>
123where
124 G: Fn(Name) -> Event,
125 D: Fn(Name) -> Event,
126 P: FnMut(Item) -> Event,
127 L: Fn() -> Event,
128{
129 fn handle(&mut self, req: Request) -> Event {
130 match req {
131 Request::Get(name) => self.handle_get(name),
132 Request::Del(name) => self.handle_del(name),
133 Request::Push(item) => self.handle_push(item),
134 Request::List => self.handle_list(),
135 Request::Vacuum => remove_broken_buffers(self),
136 }
137 }
138}
139
140#[cfg(test)]
141mod test_lib {
142
143 mod remove_broken_buffers {
144 use std::fs;
145 use std::path::Path;
146
147 use crate::evt::Event;
148 use crate::request::Request;
149 use crate::u::buf::ring_buffer_u8_new_default;
150 use crate::u::buf::ring_buffer_u8_new_default_with_checksum;
151
152 #[test]
153 #[ignore]
154 fn test_without_checksum() {
155 let dirname = Path::new("./test.d/lib/remove_broken_buffers/test_without_checksum.d");
156 fs::remove_dir_all(&dirname).ok();
157 fs::create_dir_all(&dirname).unwrap();
158
159 let mut handler = ring_buffer_u8_new_default(&dirname).unwrap();
160 let filename = dirname.join("42");
161 fs::write(filename, b"cafef00ddeadbeafface864299792458").unwrap();
162 let q: Request = Request::Vacuum;
163 match handler(q) {
164 Event::BrokenItemsRemoved(cnt) => {
165 assert_eq!(cnt, 0);
166 }
167 e => {
168 panic!("Unexpected event: {:#?}", e)
169 }
170 }
171 }
172
173 #[test]
174 #[ignore]
175 fn test_invalid() {
176 let dirname = Path::new("./test.d/lib/remove_broken_buffers/test_invalid.d");
177 fs::remove_dir_all(&dirname).ok();
178 fs::create_dir_all(&dirname).unwrap();
179
180 let chk = |_: &[u8]| b"cafef00ddeadbeafface864299792458".to_vec();
181
182 let mut handler =
183 ring_buffer_u8_new_default_with_checksum(&dirname, 7, chk, chk).unwrap();
184 let filename = dirname.join("42");
185 fs::write(filename, b"cafef00ddeadbeafface864299792458").unwrap();
186 let q: Request = Request::Vacuum;
187 match handler(q) {
188 Event::BrokenItemsRemoved(cnt) => {
189 assert_eq!(cnt, 1);
190 }
191 e => {
192 panic!("Unexpected event: {:#?}", e)
193 }
194 }
195 }
196
197 #[test]
198 #[ignore]
199 fn test_valid() {
200 let dirname = Path::new("./test.d/lib/remove_broken_buffers/test_valid.d");
201 fs::remove_dir_all(&dirname).ok();
202 fs::create_dir_all(&dirname).unwrap();
203
204 let chk = |_: &[u8]| b"cafef00ddeadbeafface864299792458".to_vec();
205
206 let mut handler =
207 ring_buffer_u8_new_default_with_checksum(&dirname, 32, chk, chk).unwrap();
208 let filename = dirname.join("42");
209 fs::write(filename, b"ZZcafef00ddeadbeafface864299792458").unwrap();
210 let q: Request = Request::Vacuum;
211 match handler(q) {
212 Event::BrokenItemsRemoved(cnt) => {
213 assert_eq!(cnt, 0);
214 }
215 e => {
216 panic!("Unexpected event: {:#?}", e)
217 }
218 }
219 }
220 }
221}