#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(
rust_2018_idioms,
missing_docs,
missing_debug_implementations,
unused_lifetimes,
unused_qualifications
)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
pub mod index;
pub mod unmanaged;
pub mod vec;
pub trait Incrementable: PartialOrd + Sized {
fn next(&self) -> Option<Self>;
fn max() -> Option<Self>;
}
macro_rules! make_incremental_int_impl {
($ty:ident) => {
impl Incrementable for $ty {
fn next(&self) -> Option<Self> {
self.checked_add(1)
}
fn max() -> Option<Self> {
Some(Self::MAX)
}
}
};
}
make_incremental_int_impl!(u8);
make_incremental_int_impl!(u16);
make_incremental_int_impl!(u32);
make_incremental_int_impl!(u64);
make_incremental_int_impl!(usize);
make_incremental_int_impl!(i8);
make_incremental_int_impl!(i16);
make_incremental_int_impl!(i32);
make_incremental_int_impl!(i64);
make_incremental_int_impl!(isize);
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[derive(Debug)]
enum ErrorCode {
#[cfg_attr(feature = "std", error("index out of bounds"))]
IndexOutOfBounds,
#[cfg_attr(
feature = "std",
error("generational index's generation is less than the existing element's generation")
)]
LessThanExistingGeneration,
#[cfg_attr(
feature = "std",
error("element's generation does not equal the generation index's generation")
)]
NotEqualGeneration,
#[cfg_attr(feature = "std", error("cannot allocate a generational index"))]
CannotAllocateGenerationalIndex,
#[cfg_attr(
feature = "std",
error("generation is already equal to existing generation")
)]
AlreadyEqualGeneration,
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(feature = "std", error(transparent))]
pub struct Error {
code: ErrorCode,
}
impl Error {
#[inline]
pub(crate) fn index_out_of_bounds() -> Self {
Error {
code: ErrorCode::IndexOutOfBounds,
}
}
#[must_use]
pub fn is_index_out_of_bounds(&self) -> bool {
matches!(self.code, ErrorCode::IndexOutOfBounds)
}
#[inline]
pub(crate) fn less_than_existing_generation() -> Self {
Error {
code: ErrorCode::LessThanExistingGeneration,
}
}
#[must_use]
pub fn is_generation_less_than_existing(&self) -> bool {
matches!(self.code, ErrorCode::LessThanExistingGeneration)
}
#[inline]
pub(crate) fn not_equal_generation() -> Self {
Error {
code: ErrorCode::NotEqualGeneration,
}
}
#[must_use]
pub fn is_not_equal_generation_error(&self) -> bool {
matches!(self.code, ErrorCode::NotEqualGeneration)
}
#[inline]
pub(crate) fn cannot_allocate_generational_index() -> Self {
Error {
code: ErrorCode::CannotAllocateGenerationalIndex,
}
}
#[must_use]
pub fn is_generational_index_allocation_error(&self) -> bool {
matches!(self.code, ErrorCode::CannotAllocateGenerationalIndex)
}
#[inline]
pub(crate) fn already_equal_generation() -> Self {
Error {
code: ErrorCode::AlreadyEqualGeneration,
}
}
#[must_use]
pub fn is_already_equal_generation_error(&self) -> bool {
matches!(self.code, ErrorCode::AlreadyEqualGeneration)
}
}
pub use vec::GenVec;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn incrementable_overflow() {
assert_eq!(u8::MAX.next(), None);
assert_eq!(u16::MAX.next(), None);
assert_eq!(u32::MAX.next(), None);
assert_eq!(u64::MAX.next(), None);
assert_eq!(usize::MAX.next(), None);
assert_eq!(i8::MAX.next(), None);
assert_eq!(i16::MAX.next(), None);
assert_eq!(i32::MAX.next(), None);
assert_eq!(i64::MAX.next(), None);
assert_eq!(isize::MAX.next(), None);
}
}