const_base/
array_str.rs

1use core::{
2    cmp::PartialEq,
3    fmt::{self, Debug, Display},
4};
5
6pub use arr::ArrayStr;
7
8mod arr {
9    /// A utf-8 byte array
10    ///
11    /// # Example
12    ///
13    /// ```rust
14    /// use const_base::ArrayStr;
15    ///
16    /// static ARR_STR: ArrayStr<12> = ArrayStr::from_utf8_unwrap(*b"hello world!");
17    ///
18    /// assert_eq!(ARR_STR.as_str(), "hello world!");
19    /// assert_eq!(ARR_STR, "hello world!");
20    ///
21    /// ```
22    #[derive(Copy, Clone, PartialEq, Eq)]
23    #[repr(transparent)]
24    pub struct ArrayStr<const N: usize> {
25        arr: [u8; N],
26    }
27
28    impl<const N: usize> ArrayStr<N> {
29        /// Constructs an `ArrayStr`, returning an error if `arr` isn't valid utf-8.
30        pub const fn from_utf8(arr: [u8; N]) -> Result<Self, core::str::Utf8Error> {
31            match core::str::from_utf8(&arr) {
32                Ok(_) => Ok(Self { arr }),
33                Err(e) => Err(e),
34            }
35        }
36
37        /// Constructs an `ArrayStr`
38        ///
39        /// # Panics
40        ///
41        /// Panics if `arr` isn't valid utf-8.
42        pub const fn from_utf8_unwrap(arr: [u8; N]) -> Self {
43            const_panic::unwrap_ok!(Self::from_utf8(arr))
44        }
45
46        /// Constructs an `ArrayStr`
47        ///
48        /// # Safety
49        ///
50        /// `arr` must be valid utf-8.
51        pub const unsafe fn from_utf8_unchecked(arr: [u8; N]) -> Self {
52            Self { arr }
53        }
54
55        /// Gets a reference to the wrapped byte array.
56        pub const fn as_array(&self) -> &[u8; N] {
57            &self.arr
58        }
59
60        /// Gets a slice of the wrapped byte array.
61        pub const fn as_slice(&self) -> &[u8] {
62            &self.arr
63        }
64
65        /// Unwraps this into the wrapped byte array.
66        pub const fn into_array(self) -> [u8; N] {
67            self.arr
68        }
69    }
70}
71
72impl<const N: usize> ArrayStr<N> {
73    /// Gets the length of this array string.
74    pub const fn len(&self) -> usize {
75        N
76    }
77
78    /// Gets a string slice of the entire array string.
79    pub const fn as_str(&self) -> &str {
80        // SAFETY: the constructor functions check that the string is valid utf-8
81        unsafe { core::str::from_utf8_unchecked(self.as_array()) }
82    }
83}
84
85impl<const N: usize> PartialEq<str> for ArrayStr<N> {
86    fn eq(&self, rhs: &str) -> bool {
87        self.as_str() == rhs
88    }
89}
90
91impl<const N: usize> PartialEq<&str> for ArrayStr<N> {
92    fn eq(&self, rhs: &&str) -> bool {
93        self.as_str() == *rhs
94    }
95}
96
97impl<const N: usize> PartialEq<ArrayStr<N>> for str {
98    fn eq(&self, rhs: &ArrayStr<N>) -> bool {
99        self == rhs.as_str()
100    }
101}
102
103impl<const N: usize> PartialEq<ArrayStr<N>> for &str {
104    fn eq(&self, rhs: &ArrayStr<N>) -> bool {
105        *self == rhs.as_str()
106    }
107}
108
109impl<const N: usize> Display for ArrayStr<N> {
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        Display::fmt(self.as_str(), f)
112    }
113}
114
115impl<const N: usize> Debug for ArrayStr<N> {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        Debug::fmt(self.as_str(), f)
118    }
119}