1#[repr(C)]
14#[allow(clippy::module_name_repetitions)]
15pub struct SliceN<T, const N: usize> {
16 pub head: [T; N],
18 pub tail: [T],
20}
21
22impl<T, const N: usize> SliceN<T, N> {
23 pub unsafe fn increase_unchecked<const M: usize>(&self) -> &SliceN<T, { N + M }> {
27 let (p, meta) = (self as *const SliceN<T, N>).to_raw_parts();
28 &*core::ptr::from_raw_parts(p, meta - M)
29 }
30
31 pub unsafe fn increase_unchecked_mut<const M: usize>(&mut self) -> &mut SliceN<T, { N + M }> {
35 let (p, meta) = (self as *mut SliceN<T, N>).to_raw_parts();
36 &mut *core::ptr::from_raw_parts_mut(p, meta - M)
37 }
38
39 pub fn increase<const M: usize>(&self) -> Result<&SliceN<T, { N + M }>, NotEnoughEntries> {
43 if self.tail.len() < M {
44 Err(NotEnoughEntries)
45 } else {
46 unsafe { Ok(self.increase_unchecked::<M>()) }
47 }
48 }
49
50 pub fn increase_mut<const M: usize>(
54 &mut self,
55 ) -> Result<&mut SliceN<T, { N + M }>, NotEnoughEntries> {
56 if self.tail.len() < M {
57 Err(NotEnoughEntries)
58 } else {
59 unsafe { Ok(self.increase_unchecked_mut::<M>()) }
60 }
61 }
62
63 pub fn downsize<const M: usize>(&self) -> &SliceN<T, M>
65 where
66 [T; N - M]: Sized, {
68 unsafe { SliceN::<T, M>::from_unchecked(self) }
69 }
70
71 pub fn downsize_mut<const M: usize>(&mut self) -> &mut SliceN<T, M>
73 where
74 [T; N - M]: Sized, {
76 unsafe { SliceN::<T, M>::from_unchecked_mut(self) }
77 }
78
79 pub unsafe fn from_unchecked(slice: &[T]) -> &Self {
83 let (p, meta) = (slice as *const [T]).to_raw_parts();
85 &*core::ptr::from_raw_parts(p, meta - N)
87 }
88
89 pub unsafe fn from_unchecked_mut(slice: &mut [T]) -> &mut Self {
93 let (p, meta) = (slice as *mut [T]).to_raw_parts();
95 &mut *core::ptr::from_raw_parts_mut(p, meta - N)
97 }
98}
99
100#[derive(Debug)]
102pub struct NotEnoughEntries;
103
104impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a SliceN<T, N> {
105 type Error = NotEnoughEntries;
106 fn try_from(value: &'a [T]) -> Result<Self, Self::Error> {
107 if value.len() < N {
108 Err(NotEnoughEntries)
109 } else {
110 unsafe { Ok(SliceN::<T, N>::from_unchecked(value)) }
111 }
112 }
113}
114
115impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut SliceN<T, N> {
116 type Error = NotEnoughEntries;
117 fn try_from(value: &'a mut [T]) -> Result<Self, Self::Error> {
118 if value.len() < N {
119 Err(NotEnoughEntries)
120 } else {
121 unsafe { Ok(SliceN::<T, N>::from_unchecked_mut(value)) }
122 }
123 }
124}
125
126use core::fmt;
127impl<T: fmt::Debug, const N: usize> fmt::Debug for SliceN<T, N> {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 f.debug_list().entries(self.iter()).finish()
130 }
131}
132
133use core::ops::{Deref, DerefMut};
134
135impl<T, const N: usize> Deref for SliceN<T, N> {
136 type Target = [T];
137 fn deref(&self) -> &Self::Target {
138 let (p, meta) = (self as *const SliceN<T, N>).to_raw_parts();
140 unsafe { &*core::ptr::from_raw_parts(p, meta + N) }
142 }
143}
144
145impl<T, const N: usize> DerefMut for SliceN<T, N> {
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 let (p, meta) = (self as *mut SliceN<T, N>).to_raw_parts();
149 unsafe { &mut *core::ptr::from_raw_parts_mut(p, meta + N) }
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use crate::SliceN;
157
158 #[test]
159 fn slice_n() {
160 let a: &[_] = &[1, 2, 3, 4, 5];
161 let b: &SliceN<_, 3> = a.try_into().unwrap();
162
163 assert_eq!(b.len(), 5);
164 assert_eq!(b.head, [1, 2, 3]);
165 assert_eq!(b.tail, [4, 5]);
166 assert_eq!(&**b, a);
167
168 let b = b.increase::<2>().unwrap();
169 assert_eq!(b.head, [1, 2, 3, 4, 5]);
170 assert_eq!(b.tail, []);
171 let _ = b.increase::<1>().unwrap_err();
172 let _ = <&SliceN<_, 6>>::try_from(a).unwrap_err();
173 }
174
175 #[test]
176 fn slice_n_mut() {
177 let a: &mut [_] = &mut [1, 2, 3, 4, 5];
178 let b: &mut SliceN<_, 3> = a.try_into().unwrap();
179
180 b.head = [3, 2, 1];
181 b.downsize_mut::<2>().head = [9, 8];
182
183 assert_eq!(a, [9, 8, 1, 4, 5]);
184 }
185}