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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//! Generic implementations for queues.

#[cfg(feature = "alloc")]
mod queue_alloc;
#[cfg(feature = "alloc")]
pub use queue_alloc::*;

#[cfg(feature = "alloc")]
mod park_queue;
#[cfg(feature = "alloc")]
pub use park_queue::*;

#[cfg(feature = "impl_crossbeam")]
mod queue_crossbeam;

use core::future::Future;
use core::time::Duration;

/// A generic queue that supports try operations
pub trait TryQueue {
    /// The type the queue holds.
    type Item;
    /// Tries to append an item to the queue returning `None` if unsuccessful
    fn try_push(&self, value: Self::Item) -> Result<(), Self::Item>;
    /// Tries to receive an item from the queue returning `None` if none
    /// available
    fn try_pop(&self) -> Option<Self::Item>;
    /// Clears the queue
    fn clear(&self);
}

/// A generic queue that can push and pop in FIFO order
pub trait Queue: TryQueue {
    /// Appends an item to the end of the queue blocking until appended
    fn push(&self, value: Self::Item);

    /// Blocks until an item is received from the queue
    fn pop(&self) -> Self::Item;
}
/// A Queue that can be accessed asynchronously
pub trait AsyncQueue {
    /// The type the queue holds.
    type AsyncItem;
    /// The future returned by `push_async`
    type PushFuture: Future<Output = ()>;
    /// The future returned by `pop_async`
    type PopFuture: Future<Output = Self::AsyncItem>;

    /// Appends to the queue asynchronously.
    fn push_async(&self, value: Self::AsyncItem) -> Self::PushFuture;
    /// Receives from the queue asynchronously.
    fn pop_async(&self) -> Self::PopFuture;
}
/// A Queue that can timeout on push and pop operations
pub trait TimeoutQueue: Queue {
    /// Appends an item to the end of the queue blocking until appended or timeout
    fn push_timeout(&self, value: Self::Item, timeout: Duration) -> Result<(), Self::Item>;
    /// Blocks until an item is received from the queue or timeout
    fn pop_timeout(&self, timeout: Duration) -> Option<Self::Item>;
}
/// An Async Queue that can timeout on push and pop operations
pub trait AsyncTimeoutQueue: AsyncQueue {
    /// The future returned by [`AsyncTimeoutQueue::push_timeout_async`]
    type PushTimeoutFuture: Future<Output = Result<(), Self::AsyncItem>>;
    /// The future returned by [`AsyncTimeoutQueue::pop_timeout_async`]
    type PopTimeoutFuture: Future<Output = Option<Self::AsyncItem>>;
    /// Pushes an item to the queue asynchronously with a timeout
    fn push_timeout_async(
        &self,
        value: Self::AsyncItem,
        timeout: Duration,
    ) -> Self::PushTimeoutFuture;
    /// Pops an item from the queue asynchronously with a timeout
    fn pop_timeout_async(&self, timeout: Duration) -> Self::PopTimeoutFuture;
}
/// A queue that can be attempt to be prepended to
pub trait TryPrependQueue: TryQueue {
    /// Adds an item to the front of the queue without blocking
    fn try_push_front(&self, value: Self::Item) -> Result<(), Self::Item>;
}
/// A queue that can be prepended (items placed in front)
pub trait PrependQueue: Queue + TryPrependQueue {
    /// Adds an item to the front of the queue blocking until able
    fn push_front(&self, value: Self::Item);
}
/// An async queue that can be prepended (items placed in front)
pub trait AsyncPrependQueue: AsyncQueue {
    /// The future returned by `prepend_async`
    type PushBackFuture: Future<Output = ()>;

    /// Adds to the front of the queue asynchronously
    fn push_front_async(&self, value: Self::AsyncItem) -> Self::PushBackFuture;
}
/// A queue that can try to be read in reverse.
pub trait TryReverseQueue: TryQueue {
    /// Non blocking version of `receive_back`
    fn try_pop_back(&self) -> Option<Self::Item>;
}
/// A queue that can be read in reverse.
pub trait ReverseQueue: TryReverseQueue + Queue {
    /// Reads from the back of the queue
    fn pop_back(&self) -> Self::Item;
}
/// An asynchronous queue that can be read in reverse
pub trait AsyncReverseQueue: AsyncQueue {
    /// The future returned by `receive_back_async`
    type PopBackFuture: Future<Output = Self::AsyncItem>;

    /// Reads the back of the queue
    fn pop_back_async(&self) -> Self::PopBackFuture;
}
/// A queue that can try to be peeked into
pub trait TryPeekQueue: TryQueue {
    /// The type that `peek` returns
    type Peeked;
    /// Non blocking `peek`
    fn try_peek(&self) -> Option<Self::Peeked>;
}
/// A queue that can be peeked into
pub trait PeekQueue: Queue + TryPeekQueue {
    /// Peeks into the queue blocking until item is in
    fn peek(&self) -> Self::Peeked;
}
/// An async queue that can be peeked into
pub trait AsyncPeekQueue: AsyncQueue {
    /// The type that is peeked
    type AsyncPeeked;
    /// The future returned by `peek_async`
    type PeekFuture: Future<Output = Self::AsyncPeeked>;

    /// Peeks into the queue asynchronously
    fn peek_async(&self) -> Self::PeekFuture;
}
/// A queue that can try to be peeked from behind
pub trait TryPeekReverseQueue: TryPeekQueue + TryReverseQueue {
    /// Peeks the rear item without blocking
    fn try_peek_back(&self) -> Option<Self::Peeked>;
}
/// A queue that can be peeked from behind
pub trait PeekReverseQueue: PeekQueue + ReverseQueue + TryPeekReverseQueue {
    /// Peeks the rear item of the queue blocking until available
    fn peek_back(&self) -> Self::Peeked;
}
/// A queue that can be peeked from behind asynchronously
pub trait AsyncPeekReverseQueue: AsyncPeekQueue + AsyncReverseQueue {
    /// The future returned by `peek_back_async`
    type PeekBackFuture: Future<Output = Self::AsyncPeeked>;
    /// Peeks the rear item of the queue blocking until available
    fn peek_back_async(&self) -> Self::PeekBackFuture;
}
/// A queue that can try to be written and read from both ends
pub trait TryDoubleEndedQueue: TryPrependQueue + TryReverseQueue {}
/// A queue that can be written and read from both ends
pub trait DoubleEndedQueue: PrependQueue + ReverseQueue + TryDoubleEndedQueue {}
/// An async queue that can be written and read from both ends
pub trait AsyncDoubleEndedQueue: AsyncPrependQueue + AsyncReverseQueue {}

#[cfg(test)]
pub(super) mod test {
    use crate::queue::{Queue, TryQueue};
    pub fn try_queue_test<Q>(queue: Q)
    where
        Q: TryQueue<Item = usize>,
    {
        assert!(queue.try_pop().is_none());
        assert!(queue.try_push(100).is_ok());
        assert_eq!(queue.try_pop(), Some(100));
        assert!(queue.try_push(200).is_ok());
        queue.clear();
        assert!(queue.try_pop().is_none());
    }

    pub fn queue_test<Q>(queue: Q)
    where
        Q: Queue<Item = usize>,
    {
        assert!(queue.try_pop().is_none());
        queue.push(100);
        assert_eq!(queue.pop(), 100);
        queue.push(200);
        queue.clear();
        assert!(queue.try_pop().is_none());
    }
}