From ac487eec3898bb887fc1755fe1d426c2003e0a77 Mon Sep 17 00:00:00 2001 From: tali Date: Fri, 14 Apr 2023 17:33:38 -0400 Subject: [PATCH] make Queue::new() a const fn --- mino/src/queue.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/mino/src/queue.rs b/mino/src/queue.rs index 553f45b..6a6fd36 100644 --- a/mino/src/queue.rs +++ b/mino/src/queue.rs @@ -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, 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, 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"); } }