1#![warn(missing_debug_implementations)]
6#![warn(missing_docs)]
7
8use core::any;
15use core::array;
16use core::cmp;
17use core::convert;
18use core::convert::TryFrom;
19use core::error;
20use core::fmt;
21use core::hash::{Hash, Hasher};
22use core::marker::PhantomData;
23use core::mem;
24use core::mem::MaybeUninit;
25use core::num;
26use core::ops;
27use core::slice;
28use core::str;
29
30pub struct Andex<M, const SIZE: usize>(PhantomData<M>, usize);
50
51impl<M, const SIZE: usize> Andex<M, SIZE> {
56 pub const SIZE: usize = SIZE;
59
60 pub const FIRST: Andex<M, SIZE> = Andex(PhantomData, 0);
62
63 pub const LAST: Andex<M, SIZE> = Andex(PhantomData, SIZE - 1);
65
66 #[inline]
93 pub const fn new<const N: usize>() -> Self {
94 const ASSERT: [(); 1] = [(); 1];
96 #[allow(clippy::no_effect)]
97 ASSERT[(N >= SIZE) as usize];
98 Andex(PhantomData, N)
99 }
100
101 #[inline]
107 pub const fn pair(self) -> Self {
108 Andex(PhantomData, SIZE - self.1 - 1)
109 }
110
111 #[inline]
113 pub fn next(self) -> Option<Self> {
114 let i = usize::from(self);
115 if i < SIZE - 1 {
116 Some(Andex(PhantomData, i + 1))
117 } else {
118 None
119 }
120 }
121
122 #[inline]
126 fn index_arr<'a, T>(&self, arr: &'a [T]) -> &'a T {
127 unsafe { arr.get_unchecked(usize::from(self)) }
128 }
129
130 #[inline]
134 fn index_arr_mut<'a, T>(&self, arr: &'a mut [T]) -> &'a mut T {
135 unsafe { arr.get_unchecked_mut(usize::from(self)) }
136 }
137
138 pub fn iter() -> AndexIterator<M, SIZE> {
158 AndexIterator::<M, SIZE>::default()
159 }
160}
161
162impl<M, const SIZE: usize> Clone for Andex<M, SIZE> {
168 fn clone(&self) -> Self {
169 *self
170 }
171}
172
173impl<M, const SIZE: usize> Copy for Andex<M, SIZE> {}
174
175impl<M, const SIZE: usize> Hash for Andex<M, SIZE> {
176 fn hash<H: Hasher>(&self, state: &mut H) {
177 self.1.hash(state);
178 }
179}
180
181impl<M, const SIZE: usize> Default for Andex<M, SIZE> {
182 fn default() -> Self {
183 Andex(PhantomData, 0)
184 }
185}
186
187impl<M, const SIZE: usize> PartialEq for Andex<M, SIZE> {
188 fn eq(&self, other: &Self) -> bool {
189 self.1 == other.1
190 }
191}
192
193impl<M, const SIZE: usize> Eq for Andex<M, SIZE> {}
194
195impl<M, const SIZE: usize> PartialOrd for Andex<M, SIZE> {
196 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
197 Some(self.cmp(other))
198 }
199}
200
201impl<M, const SIZE: usize> Ord for Andex<M, SIZE> {
202 fn cmp(&self, other: &Self) -> cmp::Ordering {
203 self.1.cmp(&other.1)
204 }
205}
206
207impl<M, const SIZE: usize> From<Andex<M, SIZE>> for usize {
208 fn from(andex: Andex<M, SIZE>) -> Self {
209 andex.1
210 }
211}
212
213impl<M, const SIZE: usize> From<&Andex<M, SIZE>> for usize {
214 fn from(andex: &Andex<M, SIZE>) -> Self {
215 andex.1
216 }
217}
218
219impl<M, const SIZE: usize> convert::TryFrom<usize> for Andex<M, SIZE> {
220 type Error = Error;
221 fn try_from(value: usize) -> Result<Self, Self::Error> {
222 if value < SIZE {
223 Ok(Andex(PhantomData, value))
224 } else {
225 Err(Error::OutOfBounds { value, size: SIZE })
226 }
227 }
228}
229
230impl<M, const SIZE: usize> fmt::Debug for Andex<M, SIZE> {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 write!(f, "{:?}", usize::from(self))
233 }
234}
235
236impl<M, const SIZE: usize> fmt::Display for Andex<M, SIZE> {
237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 write!(f, "{}", usize::from(self))
239 }
240}
241
242impl<M, const SIZE: usize> str::FromStr for Andex<M, SIZE> {
243 type Err = Error;
244
245 fn from_str(s: &str) -> Result<Self, Self::Err> {
246 Self::try_from(usize::from_str(s)?)
247 }
248}
249
250pub struct AndexIterator<M, const SIZE: usize>(Option<Andex<M, SIZE>>);
270
271impl<M, const SIZE: usize> fmt::Debug for AndexIterator<M, SIZE> {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 write!(f, "AndexIterator({:?})", self.0)
274 }
275}
276
277impl<M, const SIZE: usize> Default for AndexIterator<M, SIZE> {
278 fn default() -> Self {
279 AndexIterator(Some(Andex::<M, SIZE>::default()))
280 }
281}
282
283impl<M, const SIZE: usize> Iterator for AndexIterator<M, SIZE> {
284 type Item = Andex<M, SIZE>;
285 fn next(&mut self) -> Option<Self::Item> {
286 if let Some(i) = self.0.take() {
287 self.0 = i.next();
288 Some(i)
289 } else {
290 None
291 }
292 }
293}
294
295#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
326pub struct AndexableArray<A, Item, const SIZE: usize>(PhantomData<A>, [Item; SIZE]);
327
328impl<A, Item: fmt::Debug, const SIZE: usize> fmt::Debug for AndexableArray<A, Item, SIZE> {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 write!(
331 f,
332 "AndexableArray<{}>({:?})",
333 any::type_name::<Item>(),
334 self.1
335 )
336 }
337}
338
339#[macro_export]
355macro_rules! andex_array {
356 ($andex: ty, $item: ty) => {
357 $crate::AndexableArray<$andex, $item, { <$andex>::SIZE }>
358 };
359}
360
361impl<A, Item, const SIZE: usize> AndexableArray<A, Item, SIZE> {
362 pub fn iter(&self) -> impl Iterator<Item = &Item> {
364 self.1.iter()
365 }
366}
367
368impl<A, Item: Copy, const SIZE: usize> Clone for AndexableArray<A, Item, SIZE> {
369 fn clone(&self) -> Self {
370 *self
371 }
372}
373
374impl<A, Item: Copy, const SIZE: usize> Copy for AndexableArray<A, Item, SIZE> {}
375
376impl<A, Item: Default + Copy, const SIZE: usize> Default for AndexableArray<A, Item, SIZE> {
377 fn default() -> Self {
378 AndexableArray(Default::default(), [Default::default(); SIZE])
379 }
380}
381
382impl<A, Item, const SIZE: usize> ops::Index<Andex<A, SIZE>>
383 for AndexableArray<Andex<A, SIZE>, Item, SIZE>
384{
385 type Output = Item;
386 fn index(&self, index: Andex<A, SIZE>) -> &Self::Output {
387 index.index_arr(&self.1)
388 }
389}
390
391impl<A, Item, const SIZE: usize> ops::IndexMut<Andex<A, SIZE>>
392 for AndexableArray<Andex<A, SIZE>, Item, SIZE>
393{
394 fn index_mut(&mut self, index: Andex<A, SIZE>) -> &mut Item {
395 index.index_arr_mut(&mut self.1)
396 }
397}
398
399impl<A, Item, const SIZE: usize> ops::Index<&Andex<A, SIZE>>
400 for AndexableArray<Andex<A, SIZE>, Item, SIZE>
401{
402 type Output = Item;
403 fn index(&self, index: &Andex<A, SIZE>) -> &Self::Output {
404 index.index_arr(&self.1)
405 }
406}
407
408impl<A, Item, const SIZE: usize> ops::IndexMut<&Andex<A, SIZE>>
409 for AndexableArray<Andex<A, SIZE>, Item, SIZE>
410{
411 fn index_mut(&mut self, index: &Andex<A, SIZE>) -> &mut Item {
412 index.index_arr_mut(&mut self.1)
413 }
414}
415
416impl<A, Item, const SIZE: usize> convert::AsRef<[Item; SIZE]> for AndexableArray<A, Item, SIZE> {
417 fn as_ref(&self) -> &[Item; SIZE] {
418 &self.1
419 }
420}
421
422impl<A, Item, const SIZE: usize> convert::AsMut<[Item; SIZE]> for AndexableArray<A, Item, SIZE> {
423 fn as_mut(&mut self) -> &mut [Item; SIZE] {
424 &mut self.1
425 }
426}
427
428impl<A, Item, const SIZE: usize> From<[Item; SIZE]> for AndexableArray<A, Item, SIZE> {
429 fn from(array: [Item; SIZE]) -> Self {
430 Self(PhantomData, array)
431 }
432}
433
434impl<A, Item, const SIZE: usize> From<&[Item; SIZE]> for AndexableArray<A, Item, SIZE>
435where
436 Item: Copy,
437{
438 fn from(array: &[Item; SIZE]) -> Self {
439 Self(PhantomData, *array)
440 }
441}
442
443impl<A, Item, const SIZE: usize> From<AndexableArray<A, Item, SIZE>> for [Item; SIZE]
444where
445 Item: Copy,
446{
447 fn from(andexable_array: AndexableArray<A, Item, SIZE>) -> [Item; SIZE] {
448 andexable_array.1
449 }
450}
451
452impl<A, Item, const SIZE: usize> From<&AndexableArray<A, Item, SIZE>> for [Item; SIZE]
453where
454 Item: Copy,
455{
456 fn from(andexable_array: &AndexableArray<A, Item, SIZE>) -> [Item; SIZE] {
457 andexable_array.1
458 }
459}
460
461impl<A, Item, const SIZE: usize> IntoIterator for AndexableArray<A, Item, SIZE> {
462 type Item = Item;
463 type IntoIter = array::IntoIter<Item, SIZE>;
464 fn into_iter(self) -> Self::IntoIter {
465 IntoIterator::into_iter(self.1)
466 }
467}
468
469impl<'a, A, Item, const SIZE: usize> IntoIterator for &'a AndexableArray<A, Item, SIZE> {
470 type Item = &'a Item;
471 type IntoIter = slice::Iter<'a, Item>;
472 fn into_iter(self) -> Self::IntoIter {
473 self.1.iter()
474 }
475}
476
477impl<'a, A, Item, const SIZE: usize> IntoIterator for &'a mut AndexableArray<A, Item, SIZE> {
478 type Item = &'a mut Item;
479 type IntoIter = slice::IterMut<'a, Item>;
480 fn into_iter(self) -> Self::IntoIter {
481 self.1.iter_mut()
482 }
483}
484
485impl<A, Item, const SIZE: usize> core::iter::FromIterator<Item> for AndexableArray<A, Item, SIZE> {
486 fn from_iter<I: core::iter::IntoIterator<Item = Item>>(intoiter: I) -> Self {
487 let mut andexable = AndexableArray::<A, MaybeUninit<Item>, SIZE>(PhantomData, unsafe {
488 mem::MaybeUninit::uninit().assume_init()
489 });
490 let mut iter = intoiter.into_iter();
491 for item in &mut andexable {
492 if let Some(fromiter) = iter.next() {
493 item.write(fromiter);
494 } else {
495 panic!("iterator too short for andexable type");
496 }
497 }
498 if iter.next().is_some() {
499 panic!("iterator too long for andexable type");
500 }
501
502 unsafe { mem::transmute_copy::<_, AndexableArray<A, Item, SIZE>>(&andexable) }
503 }
504}
505
506impl<'a, A, Item: 'a + Copy, const SIZE: usize> core::iter::FromIterator<&'a Item>
507 for AndexableArray<A, Item, SIZE>
508{
509 fn from_iter<I: core::iter::IntoIterator<Item = &'a Item>>(intoiter: I) -> Self {
510 let mut andexable = AndexableArray::<A, MaybeUninit<Item>, SIZE>(PhantomData, unsafe {
511 mem::MaybeUninit::uninit().assume_init()
512 });
513 let mut iter = intoiter.into_iter();
514 for item in &mut andexable {
515 if let Some(&fromiter) = iter.next() {
516 item.write(fromiter);
517 } else {
518 panic!("iterator too short for andexable type");
519 }
520 }
521 if iter.next().is_some() {
522 panic!("iterator too long for andexable type");
523 }
524
525 unsafe { mem::transmute_copy::<_, AndexableArray<A, Item, SIZE>>(&andexable) }
526 }
527}
528
529#[derive(Debug, Clone)]
547pub enum Error {
548 OutOfBounds {
550 value: usize,
553 size: usize,
557 },
558 ParseIntError(num::ParseIntError),
560}
561
562impl error::Error for Error {}
563
564impl From<num::ParseIntError> for Error {
565 fn from(err: num::ParseIntError) -> Self {
566 Error::ParseIntError(err)
567 }
568}
569
570impl fmt::Display for Error {
571 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572 match self {
573 Error::OutOfBounds { value, size } => write!(
574 f,
575 "value {} is out-of-bounds for index with size {}",
576 value, size
577 ),
578 Error::ParseIntError(err) => write!(f, "{}", err),
579 }
580 }
581}