chiark / gitweb /
genericise Queue
[hippotat.git] / src / queue.rs
1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 use crate::prelude::*;
6
7 #[derive(Default,Clone)]
8 pub struct Queue<E> {
9   content: usize,
10   eaten1: usize, // 0 <= eaten1 < queue.front()...len()
11   queue: VecDeque<E>,
12 }
13
14 impl<E> Debug for Queue<E> where E: AsRef<[u8]> {
15   #[throws(fmt::Error)]
16   fn fmt(&self, f: &mut fmt::Formatter) {
17     write!(f, "Queue{{content={},eaten1={},queue=[",
18            self.content, self.eaten1)?;
19     for q in &self.queue { write!(f, "{},", q.as_ref().len())?; }
20     write!(f, "]}}")?;
21   }
22 }
23
24 impl<E> Queue<E> where E: AsRef<[u8]> {
25   pub fn push<B: Into<E>>(&mut self, b: B) {
26     self.push_(b.into());
27   }
28   pub fn push_(&mut self, b: E) {
29     let l = b.as_ref().len();
30     self.queue.push_back(b);
31     self.content += l;
32   }
33   pub fn is_empty(&self) -> bool { self.content == 0 }
34 }
35
36 impl<E> Extend<E> for Queue<E> where E: AsRef<[u8]> {
37   fn extend<I>(&mut self, it: I)
38   where I: IntoIterator<Item=E>
39   {
40     for b in it { self.push(b) }
41   }
42 }
43
44 impl<E> hyper::body::Buf for Queue<E> where E: AsRef<[u8]> {
45   fn remaining(&self) -> usize { self.content }
46   fn chunk(&self) -> &[u8] {
47     let front = if let Some(f) = self.queue.front() { f } else { return &[] };
48     &front.as_ref()[ self.eaten1.. ]
49   }
50   fn advance(&mut self, cnt: usize) {
51     self.content -= cnt;
52     self.eaten1 += cnt;
53     loop {
54       if self.eaten1 == 0 { break }
55       let front = self.queue.front().unwrap();
56       if self.eaten1 < front.as_ref().len() { break; }
57       self.eaten1 -= front.as_ref().len();
58       self.queue.pop_front().unwrap();
59     }
60   }
61 }