devela/data/collections/array/
ext.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// devela::data::array::ext
//
//!
//

use crate::{Debug, Display, FmtResult, Formatter};

/// A formatting wrapper for core [arrays][array], implementing [`Display`] and [`Debug`].
///
/// It is created by the [`ExtArray::fmt`] method.
#[repr(transparent)]
pub struct ArrayFmt<'a, T: ExtArray>(&'a T);

/// Private trait for arrays with elements that implement [`Display`].
trait ArrayDisplay: ExtArray {
    fn fmt_display(&self, f: &mut Formatter) -> FmtResult<()>;
}

/// Private trait for arrays with elements that implement [`Debug`].
///
/// This trait is a bit redundant since arrays of any size can impl `Debug`,
/// nevertheless it's better if we can offer the same api in both cases.
trait ArrayDebug: ExtArray {
    fn fmt_debug(&self, f: &mut Formatter) -> FmtResult<()>;
}

impl<T: ArrayDisplay> Display for ArrayFmt<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult<()> {
        self.0.fmt_display(f)
    }
}
impl<T: ArrayDebug> Debug for ArrayFmt<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult<()> {
        self.0.fmt_debug(f)
    }
}

/// Marker trait to prevent downstream implementations of the [`ExtArray`] trait.
trait Sealed {}
impl<T, const LEN: usize> Sealed for [T; LEN] {}

/// Extension trait providing convenience methods for [`[T; N]`][array] arrays.
///
/// This trait is sealed and cannot be implemented for any other type.
#[expect(private_bounds, reason = "Sealed")]
pub trait ExtArray: Sealed {
    /// The length of this array.
    const LEN: usize;

    /// Wraps the array in an [`ArrayFmt`] for formatting purposes.
    #[rustfmt::skip]
    fn fmt(&self) -> ArrayFmt<Self> where Self: Sized { ArrayFmt(self) }
}

impl<T, const LEN: usize> ExtArray for [T; LEN] {
    const LEN: usize = LEN;
}

impl<T: Display, const LEN: usize> ArrayDisplay for [T; LEN] {
    fn fmt_display(&self, f: &mut Formatter) -> FmtResult<()> {
        write!(f, "[")?;
        for (index, element) in self.iter().enumerate() {
            if index > 0 {
                write!(f, ", ")?;
            }
            Display::fmt(element, f)?;
        }
        write!(f, "]")
    }
}
impl<T: Debug, const LEN: usize> ArrayDebug for [T; LEN] {
    fn fmt_debug(&self, f: &mut Formatter) -> FmtResult<()> {
        f.debug_list().entries(self.iter()).finish()
    }
}