1
- use std:: { fmt:: Debug , hash:: Hash } ;
1
+ use std:: { fmt:: Debug , hash:: Hash , mem :: ManuallyDrop , ptr :: NonNull } ;
2
2
3
3
use crate :: {
4
4
length:: { InvalidLength , SmallLen , ValidLength } ,
5
5
logging:: error,
6
- non_empty_array:: NonEmptyFixedArray ,
7
6
} ;
8
7
9
8
/// A fixed size array with length provided at creation denoted in a [`ValidLength`], by default [`u32`].
10
9
///
11
10
/// See module level documentation for more information.
12
- #[ derive( Clone ) ]
13
- pub struct FixedArray < T , LenT : ValidLength = SmallLen > ( Option < NonEmptyFixedArray < T , LenT > > ) ;
11
+ pub struct FixedArray < T , LenT : ValidLength = SmallLen > {
12
+ ptr : NonNull < T > ,
13
+ len : LenT ,
14
+ }
14
15
15
16
impl < T , LenT : ValidLength > FixedArray < T , LenT > {
16
17
/// Alias to [`FixedArray::empty`].
@@ -22,14 +23,14 @@ impl<T, LenT: ValidLength> FixedArray<T, LenT> {
22
23
/// Creates a new, empty [`FixedArray`] that cannot be pushed to.
23
24
#[ must_use]
24
25
pub fn empty ( ) -> Self {
25
- Self ( None )
26
+ Self {
27
+ ptr : NonNull :: dangling ( ) ,
28
+ len : LenT :: ZERO ,
29
+ }
26
30
}
27
31
28
32
pub ( crate ) fn small_len ( & self ) -> LenT {
29
- self . 0
30
- . as_ref ( )
31
- . map ( NonEmptyFixedArray :: small_len)
32
- . unwrap_or_default ( )
33
+ self . len
33
34
}
34
35
35
36
/// Returns the length of the [`FixedArray`].
@@ -41,7 +42,7 @@ impl<T, LenT: ValidLength> FixedArray<T, LenT> {
41
42
/// Returns if the length is equal to 0.
42
43
#[ must_use]
43
44
pub fn is_empty ( & self ) -> bool {
44
- self . 0 . is_none ( )
45
+ self . len ( ) == 0
45
46
}
46
47
47
48
/// Converts [`FixedArray<T>`] to [`Vec<T>`], this operation should be cheap.
@@ -67,31 +68,56 @@ impl<T, LenT: ValidLength> FixedArray<T, LenT> {
67
68
pub fn as_slice_mut ( & mut self ) -> & mut [ T ] {
68
69
self
69
70
}
70
- }
71
71
72
- impl < T , LenT : ValidLength > Default for FixedArray < T , LenT > {
73
- /// Creates a new, empty [`FixedArray`] that cannot be pushed to.
74
- fn default ( ) -> Self {
75
- Self :: empty ( )
72
+ /// Converts the [`FixedArray`] to it's original [`Box<T>`].
73
+ ///
74
+ /// # Safety
75
+ /// `self` must never be used again, and it is highly recommended to wrap in [`ManuallyDrop`] before calling.
76
+ pub ( crate ) unsafe fn as_box ( & mut self ) -> Box < [ T ] > {
77
+ let slice = self . as_slice_mut ( ) ;
78
+
79
+ // SAFETY: `self` has been derived from `Box<[T]>`
80
+ unsafe { Box :: from_raw ( slice) }
76
81
}
77
82
}
78
83
84
+ unsafe impl < T : Send , LenT : ValidLength > Send for FixedArray < T , LenT > { }
85
+ unsafe impl < T : Sync , LenT : ValidLength > Sync for FixedArray < T , LenT > { }
86
+
79
87
impl < T , LenT : ValidLength > std:: ops:: Deref for FixedArray < T , LenT > {
80
88
type Target = [ T ] ;
81
89
fn deref ( & self ) -> & Self :: Target {
82
- self . 0
83
- . as_ref ( )
84
- . map ( NonEmptyFixedArray :: as_slice)
85
- . unwrap_or_default ( )
90
+ // SAFETY: `self.ptr` and `self.len` are both valid and derived from `Box<[T]>`.
91
+ unsafe { std:: slice:: from_raw_parts ( self . ptr . as_ptr ( ) , self . small_len ( ) . to_usize ( ) ) }
86
92
}
87
93
}
88
94
89
95
impl < T , LenT : ValidLength > std:: ops:: DerefMut for FixedArray < T , LenT > {
90
96
fn deref_mut ( & mut self ) -> & mut Self :: Target {
91
- self . 0
92
- . as_mut ( )
93
- . map ( NonEmptyFixedArray :: as_mut_slice)
94
- . unwrap_or_default ( )
97
+ // SAFETY: `self.ptr` and `self.len` are both valid and derived from `Box<[T]>`.
98
+ unsafe { std:: slice:: from_raw_parts_mut ( self . ptr . as_ptr ( ) , self . small_len ( ) . to_usize ( ) ) }
99
+ }
100
+ }
101
+
102
+ impl < T , LenT : ValidLength > Drop for FixedArray < T , LenT > {
103
+ fn drop ( & mut self ) {
104
+ // SAFETY: We never use `self` again, and we are in the drop impl.
105
+ unsafe { self . as_box ( ) } ;
106
+ }
107
+ }
108
+
109
+ impl < T , LenT : ValidLength > Default for FixedArray < T , LenT > {
110
+ /// Creates a new, empty [`FixedArray`] that cannot be pushed to.
111
+ fn default ( ) -> Self {
112
+ Self :: empty ( )
113
+ }
114
+ }
115
+
116
+ impl < T : Clone , LenT : ValidLength > Clone for FixedArray < T , LenT > {
117
+ fn clone ( & self ) -> Self {
118
+ Box :: < [ T ] > :: from ( self . as_slice ( ) )
119
+ . try_into ( )
120
+ . unwrap_or_else ( |_| panic ! ( "Length of array can't change when cloning" ) )
95
121
}
96
122
}
97
123
@@ -165,7 +191,10 @@ impl<T, LenT: ValidLength> std::iter::FromIterator<T> for FixedArray<T, LenT> {
165
191
166
192
impl < T , LenT : ValidLength > From < FixedArray < T , LenT > > for Box < [ T ] > {
167
193
fn from ( value : FixedArray < T , LenT > ) -> Self {
168
- value. 0 . map ( Box :: from) . unwrap_or_default ( )
194
+ let mut value = ManuallyDrop :: new ( value) ;
195
+
196
+ // SAFETY: We don't use value again, and it is ManuallyDrop.
197
+ unsafe { value. as_box ( ) }
169
198
}
170
199
}
171
200
@@ -178,11 +207,13 @@ impl<T, LenT: ValidLength> From<FixedArray<T, LenT>> for Vec<T> {
178
207
impl < T , LenT : ValidLength > TryFrom < Box < [ T ] > > for FixedArray < T , LenT > {
179
208
type Error = InvalidLength < T > ;
180
209
fn try_from ( boxed_array : Box < [ T ] > ) -> Result < Self , Self :: Error > {
181
- match NonEmptyFixedArray :: try_from ( boxed_array) {
182
- Ok ( arr) => Ok ( Self ( Some ( arr) ) ) ,
183
- Err ( None ) => Ok ( Self ( None ) ) ,
184
- Err ( Some ( err) ) => Err ( err) ,
185
- }
210
+ let ( len, boxed_array) = LenT :: from_usize ( boxed_array) ?;
211
+ let array_ptr = Box :: into_raw ( boxed_array) . cast :: < T > ( ) ;
212
+
213
+ Ok ( Self {
214
+ ptr : NonNull :: new ( array_ptr) . expect ( "Box ptr != nullptr" ) ,
215
+ len,
216
+ } )
186
217
}
187
218
}
188
219
0 commit comments