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