1#![doc = include_str!("../README.md")]
10#![cfg_attr(docsrs, feature(doc_cfg))]
11#![warn(
12 rust_2018_idioms,
13 missing_docs,
14 missing_debug_implementations,
15 unused_lifetimes,
16 unused_qualifications
17)]
18#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(all(feature = "alloc", not(feature = "std")))]
21extern crate alloc;
22
23use core::fmt;
24
25pub mod index;
26pub mod unmanaged;
27pub mod vec;
28
29pub trait Incrementable: PartialOrd + Sized {
47 fn next(&self) -> Option<Self>;
49
50 fn max() -> Option<Self>;
56}
57
58macro_rules! make_incremental_int_impl {
60 ($ty:ident) => {
61 impl Incrementable for $ty {
62 fn next(&self) -> Option<Self> {
63 self.checked_add(1)
64 }
65
66 fn max() -> Option<Self> {
67 Some(Self::MAX)
68 }
69 }
70 };
71}
72
73make_incremental_int_impl!(u8);
74make_incremental_int_impl!(u16);
75make_incremental_int_impl!(u32);
76make_incremental_int_impl!(u64);
77make_incremental_int_impl!(usize);
78make_incremental_int_impl!(i8);
79make_incremental_int_impl!(i16);
80make_incremental_int_impl!(i32);
81make_incremental_int_impl!(i64);
82make_incremental_int_impl!(isize);
83
84#[derive(Debug)]
85enum ErrorCode {
86 IndexOutOfBounds,
87 LessThanExistingGeneration,
88 NotEqualGeneration,
89 CannotAllocateGenerationalIndex,
90 AlreadyEqualGeneration,
91}
92
93impl fmt::Display for ErrorCode {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self {
96 ErrorCode::IndexOutOfBounds => f.write_str("index out of bounds"),
97 ErrorCode::LessThanExistingGeneration => f.write_str(
98 "generational index's generation is less than the existing element's generation",
99 ),
100 ErrorCode::NotEqualGeneration => {
101 f.write_str("element's generation does not equal the generation index's generation")
102 }
103 ErrorCode::CannotAllocateGenerationalIndex => {
104 f.write_str("cannot allocate a generational index")
105 }
106 ErrorCode::AlreadyEqualGeneration => {
107 f.write_str("generation is already equal to existing generation")
108 }
109 }
110 }
111}
112
113#[derive(Debug)]
115pub struct Error {
116 code: ErrorCode,
117}
118
119impl fmt::Display for Error {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
121 fmt::Display::fmt(&self.code, f)
122 }
123}
124
125#[cfg(feature = "std")]
126impl std::error::Error for Error {
127 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
128 None
129 }
130}
131
132impl Error {
133 #[inline]
134 pub(crate) fn index_out_of_bounds() -> Self {
135 Error {
136 code: ErrorCode::IndexOutOfBounds,
137 }
138 }
139
140 #[must_use]
142 pub fn is_index_out_of_bounds(&self) -> bool {
143 matches!(self.code, ErrorCode::IndexOutOfBounds)
144 }
145
146 #[inline]
147 pub(crate) fn less_than_existing_generation() -> Self {
148 Error {
149 code: ErrorCode::LessThanExistingGeneration,
150 }
151 }
152
153 #[must_use]
155 pub fn is_generation_less_than_existing(&self) -> bool {
156 matches!(self.code, ErrorCode::LessThanExistingGeneration)
157 }
158
159 #[inline]
160 pub(crate) fn not_equal_generation() -> Self {
161 Error {
162 code: ErrorCode::NotEqualGeneration,
163 }
164 }
165
166 #[must_use]
168 pub fn is_not_equal_generation_error(&self) -> bool {
169 matches!(self.code, ErrorCode::NotEqualGeneration)
170 }
171
172 #[inline]
173 pub(crate) fn cannot_allocate_generational_index() -> Self {
174 Error {
175 code: ErrorCode::CannotAllocateGenerationalIndex,
176 }
177 }
178
179 #[must_use]
181 pub fn is_generational_index_allocation_error(&self) -> bool {
182 matches!(self.code, ErrorCode::CannotAllocateGenerationalIndex)
183 }
184
185 #[inline]
186 pub(crate) fn already_equal_generation() -> Self {
187 Error {
188 code: ErrorCode::AlreadyEqualGeneration,
189 }
190 }
191
192 #[must_use]
194 pub fn is_already_equal_generation_error(&self) -> bool {
195 matches!(self.code, ErrorCode::AlreadyEqualGeneration)
196 }
197}
198
199pub use vec::GenVec;
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn incrementable_overflow() {
207 assert_eq!(u8::MAX.next(), None);
208 assert_eq!(u16::MAX.next(), None);
209 assert_eq!(u32::MAX.next(), None);
210 assert_eq!(u64::MAX.next(), None);
211 assert_eq!(usize::MAX.next(), None);
212 assert_eq!(i8::MAX.next(), None);
213 assert_eq!(i16::MAX.next(), None);
214 assert_eq!(i32::MAX.next(), None);
215 assert_eq!(i64::MAX.next(), None);
216 assert_eq!(isize::MAX.next(), None);
217 }
218}