make Queue::new() a const fn

This commit is contained in:
tali 2023-04-14 17:33:38 -04:00
parent 82311fc9b6
commit ac487eec38
1 changed files with 14 additions and 10 deletions

View File

@ -11,17 +11,21 @@ pub struct Queue<'a, T: Copy> {
impl<'a, T: Copy> Queue<'a, T> {
/// Constructs a new queue.
pub fn new(mut hold: Option<T>, mut next: &'a [T]) -> Self {
if hold.is_none() && !next.is_empty() {
hold = Some(next[0]);
next = &next[1..];
pub const fn new(mut hold: Option<T>, mut next: &'a [T]) -> Self {
// SIGH. so `hold.is_none()` is not valid in `const fn`, for some obscure reason.
#[allow(clippy::redundant_pattern_matching)]
if let None = hold {
if let Some((hd, tl)) = next.split_first() {
hold = Some(*hd);
next = tl;
}
}
Self { hold, next }
}
/// Returns `true` if the queue is completely empty (i.e., `reachable()` would yield
/// no values).
pub fn is_empty(&self) -> bool {
pub const fn is_empty(&self) -> bool {
// HACK: its impossible for `next` to be non-empty and `hold` to be None, because
// if `next` was non-empty then the `new` constructor would automatically move
// some value into the hold slot.
@ -113,15 +117,15 @@ mod test {
#[test]
fn test_queue_remove() {
assert_eq!(
Queue::new(None, &["A", "B", "C"]).remove(&"A"),
Queue::new(None, &["A", "B", "C"]).remove("A"),
Queue::new(Some("B"), &["C"])
);
assert_eq!(
Queue::new(Some("D"), &["A", "B", "C"]).remove(&"A"),
Queue::new(Some("D"), &["A", "B", "C"]).remove("A"),
Queue::new(Some("D"), &["B", "C"])
);
assert_eq!(
Queue::new(None, &["A", "B", "C"]).remove(&"B"),
Queue::new(None, &["A", "B", "C"]).remove("B"),
Queue::new(None, &["A", "C"])
);
}
@ -129,12 +133,12 @@ mod test {
#[test]
#[should_panic]
fn test_queue_bad_remove_1() {
Queue::new(None, &["A", "B", "C"]).remove(&"C");
Queue::new(None, &["A", "B", "C"]).remove("C");
}
#[test]
#[should_panic]
fn test_queue_bad_remove_2() {
Queue::new(Some("D"), &["A", "B", "C"]).remove(&"B");
Queue::new(Some("D"), &["A", "B", "C"]).remove("B");
}
}