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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#[repr(C)]
pub struct SliceN<T, const N: usize> {
pub head: [T; N],
pub tail: [T],
}
impl<T, const N: usize> SliceN<T, N> {
pub fn len(&self) -> usize {
N + self.tail.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn from_unchecked(slice: &[T]) -> &Self {
let (p, meta) = (slice as *const [T]).to_raw_parts();
unsafe { &*core::ptr::from_raw_parts(p, meta - N) }
}
pub fn from_unchecked_mut(slice: &mut [T]) -> &mut Self {
let (p, meta) = (slice as *mut [T]).to_raw_parts();
unsafe { &mut *core::ptr::from_raw_parts_mut(p, meta - N) }
}
}
#[derive(Debug)]
pub struct NotEnoughEntries;
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a SliceN<T, N> {
type Error = NotEnoughEntries;
fn try_from(value: &'a [T]) -> Result<Self, Self::Error> {
if value.len() < N {
Err(NotEnoughEntries)
} else {
Ok(SliceN::<T, N>::from_unchecked(value))
}
}
}
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut SliceN<T, N> {
type Error = NotEnoughEntries;
fn try_from(value: &'a mut [T]) -> Result<Self, Self::Error> {
if value.len() < N {
Err(NotEnoughEntries)
} else {
Ok(SliceN::<T, N>::from_unchecked_mut(value))
}
}
}
use core::fmt;
impl<T: fmt::Debug, const N: usize> fmt::Debug for SliceN<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.head.iter())
.entries(self.tail.iter())
.finish()
}
}
use core::ops::{Deref, DerefMut};
impl<T, const N: usize> Deref for SliceN<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let (p, meta) = (self as *const SliceN<T, N>).to_raw_parts();
unsafe { &*core::ptr::from_raw_parts(p, meta + N) }
}
}
impl<T, const N: usize> DerefMut for SliceN<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
let (p, meta) = (self as *mut SliceN<T, N>).to_raw_parts();
unsafe { &mut *core::ptr::from_raw_parts_mut(p, meta + N) }
}
}
#[cfg(test)]
mod tests {
use core::ops::Deref;
use crate::SliceN;
#[test]
fn slice_n() {
let a: &[_] = &[1, 2, 3, 4, 5];
let b: &SliceN<_, 3> = a.try_into().unwrap();
assert_eq!(b.len(), 5);
assert_eq!(b.head, [1, 2, 3]);
assert_eq!(b.tail, [4, 5]);
assert_eq!(b.deref(), a);
let _ = <&SliceN<_, 6>>::try_from(a).unwrap_err();
}
#[test]
fn slice_n_mut() {
let a: &mut [_] = &mut [1, 2, 3, 4, 5];
let b: &mut SliceN<_, 3> = a.try_into().unwrap();
b.head = [3, 2, 1];
assert_eq!(a, [3, 2, 1, 4, 5]);
}
}