1use std::mem::size_of;
61use std::slice;
62
63pub unsafe fn reinterpret_mut_slice<T, S>(slice: &mut [T]) -> &mut [S] {
66 let size_t = size_of::<T>();
67 let size_s = size_of::<S>();
68 let nu_len = if size_t > 0 {
69 assert_ne!(
70 size_s, 0,
71 "Cannot reinterpret a slice of non-zero sized types as a slice of zero sized types."
72 );
73 assert_eq!(
75 (slice.len() * size_t) % size_s,
76 0,
77 "Slice cannot be safely reinterpreted due to a misaligned size"
78 );
79 (slice.len() * size_t) / size_s
80 } else {
81 assert_eq!(
82 size_s, 0,
83 "Cannot reinterpret a slice of zero sized types as a slice of non-zero sized types."
84 );
85 slice.len()
86 };
87 slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut S, nu_len)
88}
89
90pub unsafe fn reinterpret_slice<T, S>(slice: &[T]) -> &[S] {
93 let size_t = size_of::<T>();
94 let size_s = size_of::<S>();
95 let nu_len = if size_t > 0 {
96 assert_ne!(
97 size_s, 0,
98 "Cannot reinterpret a slice of non-zero sized types as a slice of zero sized types."
99 );
100 assert_eq!(
102 (slice.len() * size_t) % size_s,
103 0,
104 "Slice cannot be safely reinterpreted due to a misaligned size"
105 );
106 (slice.len() * size_t) / size_s
107 } else {
108 assert_eq!(
109 size_s, 0,
110 "Cannot reinterpret a slice of zero sized types as a slice of non-zero sized types."
111 );
112 slice.len()
113 };
114 slice::from_raw_parts(slice.as_ptr() as *const S, nu_len)
115}
116
117pub unsafe fn reinterpret_vec<T, S>(mut vec: Vec<T>) -> Vec<S> {
120 let size_t = size_of::<T>();
121 let size_s = size_of::<S>();
122 let nu_vec = if size_t > 0 {
123 assert_ne!(
124 size_s, 0,
125 "Cannot reinterpret a Vec of non-zero sized types as a Vec of zero sized types."
126 );
127 assert_eq!(
129 (vec.len() * size_t) % size_s,
130 0,
131 "Vec cannot be safely reinterpreted due to a misaligned size"
132 );
133 let nu_len = (vec.len() * size_t) / size_s;
134 assert_eq!(
135 (vec.capacity() * size_t) % size_s,
136 0,
137 "Vec cannot be safely reinterpreted due to a misaligned capacity"
138 );
139 let nu_capacity = (vec.capacity() * size_t) / size_s;
140 let vec_ptr = vec.as_mut_ptr();
141 Vec::from_raw_parts(vec_ptr as *mut S, nu_len, nu_capacity)
142 } else {
143 assert_eq!(
144 size_s, 0,
145 "Cannot reinterpret a Vec of zero sized types as a Vec of non-zero sized types."
146 );
147 let nu_len = vec.len();
148 let nu_capacity = vec.capacity();
149 debug_assert_eq!(
150 nu_capacity,
151 (-1isize) as usize,
152 "Capacity should be -1 for 0 sized types. (bug)"
153 );
154 let vec_ptr = vec.as_mut_ptr();
155 Vec::from_raw_parts(vec_ptr as *mut S, nu_len, nu_capacity)
156 };
157 ::std::mem::forget(vec);
158 nu_vec
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
167 fn reinterpret_slice_test() {
168 let vec: Vec<[f64; 3]> = vec![[0.1, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
169 let flat: Vec<f64> = vec![0.1, 1.0, 2.0, 1.2, 1.4, 2.1, 0.5, 3.2, 4.0];
170 let nu_flat: &[f64] = unsafe { reinterpret_slice(vec.as_slice()) };
171 assert_eq!(*nu_flat, *flat.as_slice()); assert_eq!(nu_flat, flat.as_slice()); let nu_slice: &[[f64; 3]] = unsafe { reinterpret_slice(flat.as_slice()) };
175 assert_eq!(*nu_slice, *vec.as_slice()); assert_eq!(nu_slice, vec.as_slice()); }
178
179 #[test]
180 fn reinterpret_mut_slice_test() {
181 let vec: Vec<[f64; 3]> = vec![[0.5, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
182 let flat_mut = &mut [-0.5, -1.0, -1.0, 0.2, -0.6, -0.9, -0.5, 1.2, 1.0];
183
184 let nu_mut_slice: &mut [[f64; 3]] = unsafe { reinterpret_mut_slice(flat_mut) };
185 for v in nu_mut_slice.iter_mut() {
186 v[0] += 1.0;
187 v[1] += 2.0;
188 v[2] += 3.0;
189 }
190
191 assert_eq!(nu_mut_slice, vec.as_slice());
192 }
193
194 #[test]
195 fn reinterpret_vec_test() {
196 let exp_vec: Vec<[f64; 3]> = vec![[0.5, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
197 let vec = vec![-0.5, -1.0, -1.0, 0.2, -0.6, -0.9, -0.5, 1.2, 1.0];
198 let mut nu_vec: Vec<[f64; 3]> = unsafe { reinterpret_vec(vec.clone()) };
199 for v in nu_vec.iter_mut() {
200 v[0] += 1.0;
201 v[1] += 2.0;
202 v[2] += 3.0;
203 }
204
205 assert_eq!(nu_vec, exp_vec);
206 }
207
208 #[test]
210 fn zero_size_test() {
211 #[derive(Debug, Clone, PartialEq)]
212 struct Foo {
213 a: (),
214 b: (),
215 }
216
217 let exp_vec: Vec<Foo> = vec![Foo { a: (), b: () }, Foo { a: (), b: () }];
218 let mut mut_vec = vec![(), ()];
219 let vec = mut_vec.clone();
220 let mut_slice = mut_vec.as_mut_slice();
221 let slice = vec.as_slice();
222 let exp_slice = exp_vec.as_slice();
223
224 let nu_vec: Vec<Foo> = unsafe { reinterpret_vec(vec.clone()) };
226 assert_eq!(nu_vec, exp_vec);
227
228 let nu_slice: &[Foo] = unsafe { reinterpret_slice(slice) };
229 assert_eq!(nu_slice, exp_slice);
230
231 let nu_mut_slice: &mut [Foo] = unsafe { reinterpret_mut_slice(mut_slice) };
232 assert_eq!(nu_mut_slice, exp_slice);
233
234 let old_vec: Vec<()> = unsafe { reinterpret_vec(nu_vec.clone()) };
236 assert_eq!(vec, old_vec);
237
238 let old_slice: &[()] = unsafe { reinterpret_mut_slice(nu_mut_slice) };
239 assert_eq!(slice, old_slice);
240 }
241}