freelist_rs/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/freelist-rs
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use core::fmt;
7use std::{error::Error, fmt::Display};
8
9/*
10 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/nimble-rust/nimble
11 * Licensed under the MIT License. See LICENSE in the project root for license information.
12 */
13pub struct FreeList<T> {
14    free_numbers: Vec<T>,
15}
16
17#[derive(Debug, PartialEq, Eq)]
18pub enum FreeListError {
19    ItemNotInTheList,
20}
21
22impl Display for FreeListError {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        write!(f, "freelist-error:{:?}", self)
25    }
26}
27
28impl Error for FreeListError {}
29
30#[allow(unused)]
31impl<T: Copy + PartialEq + fmt::Debug + TryFrom<usize>> FreeList<T> {
32    pub fn new(count: usize) -> Self {
33        let mut free_numbers = Vec::with_capacity(count);
34        for i in (0..count).rev() {
35            if let Ok(val) = T::try_from(i) {
36                free_numbers.push(val);
37            } else {
38                panic!(
39                    "The type `{}` cannot represent the number `{}`",
40                    std::any::type_name::<T>(),
41                    i
42                );
43            }
44        }
45        Self { free_numbers }
46    }
47
48    pub fn allocate(&mut self) -> Option<T> {
49        self.free_numbers.pop()
50    }
51
52    pub fn allocate_count(&mut self, num: usize) -> Option<Vec<T>> {
53        if num == 0 {
54            return Some(Vec::new());
55        }
56        if self.free_numbers.len() < num {
57            return None;
58        }
59
60        let mut allocated = Vec::with_capacity(num); // Pre-allocate space for the new Vec
61        for _ in 0..num {
62            let val = self
63                .free_numbers
64                .pop()
65                .expect("we have checked the len() previously");
66            allocated.push(val);
67        }
68        Some(allocated)
69    }
70
71    pub fn free(&mut self, id: T) -> Result<(), FreeListError> {
72        if self.free_numbers.contains(&id) {
73            Err(FreeListError::ItemNotInTheList)
74        } else {
75            self.free_numbers.insert(0, id);
76            Ok(())
77        }
78    }
79
80    pub fn free_slice(&mut self, ids: &[T]) -> Result<(), FreeListError> {
81        for id in ids {
82            if self.free_numbers.contains(id) {
83                return Err(FreeListError::ItemNotInTheList);
84            } else {
85                self.free_numbers.insert(0, *id);
86            }
87        }
88        Ok(())
89    }
90
91    pub fn len(&self) -> usize {
92        self.free_numbers.len()
93    }
94
95    pub fn is_empty(&self) -> bool {
96        self.free_numbers.is_empty()
97    }
98}