      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

    use slab::Slab;

    /// Buffers frames for multiple streams.
    #[derive(Debug)]
    pub struct Buffer<T> {
        slab: Slab<Slot<T>>,
    }

    /// A sequence of frames in a `Buffer`
    #[derive(Debug)]
    pub struct Deque {
        indices: Option<Indices>,
    }

    /// Tracks the head & tail for a sequence of frames in a `Buffer`.
    #[derive(Debug, Default, Copy, Clone)]
    struct Indices {
        head: usize,
        tail: usize,
    }

    #[derive(Debug)]
    struct Slot<T> {
        value: T,
        next: Option<usize>,
    }

    impl<T> Buffer<T> {
        pub fn new() -> Self {
            Buffer { slab: Slab::new() }
        }
    }

    impl Deque {
        pub fn new() -> Self {
            Deque { indices: None }
        }

        pub fn is_empty(&self) -> bool {
            self.indices.is_none()
        }

        pub fn push_back<T>(&mut self, buf: &mut Buffer<T>, value: T) {
            let key = buf.slab.insert(Slot { value, next: None });

            match self.indices {
                Some(ref mut idxs) => {
                    buf.slab[idxs.tail].next = Some(key);
                    idxs.tail = key;
                }
                None => {
                    self.indices = Some(Indices {
                        head: key,
                        tail: key,
                    });
                }
            }
        }

        pub fn push_front<T>(&mut self, buf: &mut Buffer<T>, value: T) {
            let key = buf.slab.insert(Slot { value, next: None });

            match self.indices {
                Some(ref mut idxs) => {
                    buf.slab[key].next = Some(idxs.head);
                    idxs.head = key;
                }
                None => {
                    self.indices = Some(Indices {
                        head: key,
                        tail: key,
                    });
                }
            }
        }

        pub fn pop_front<T>(&mut self, buf: &mut Buffer<T>) -> Option<T> {
            match self.indices {
                Some(mut idxs) => {
                    let mut slot = buf.slab.remove(idxs.head);

                    if idxs.head == idxs.tail {
                        assert!(slot.next.is_none());
                        self.indices = None;
                    } else {
                        idxs.head = slot.next.take().unwrap();
                        self.indices = Some(idxs);
                    }

                    Some(slot.value)
                }
                None => None,
            }
        }

        /*
        pub fn peek_front<'a, T>(&self, buf: &'a Buffer<T>) -> Option<&'a T> {
            match self.indices {
                Some(idxs) => Some(&buf.slab[idxs.head].value),
                None => None,
            }
        }
        */
    }