byte_slice_cast/
lib.rs

1// Copyright (C) 2017,2018 Sebastian Dröge <[email protected]>
2//
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5//! Safely cast bytes slices from/to slices of built-in fundamental numeric types.
6//!
7//! The provided traits here allow safe casting between byte slices and slices of fundamental
8//! numeric types, like integers and floating point numbers. During casting, checks are performed
9//! to ensure that the output slice is safe to use: the input slice must be properly aligned for
10//! the output type and contain an integer number of values.
11//!
12//! Instead of working only on slices, the traits work on `AsRef<[T]>` in the immutable case and on
13//! `AsMut<[T]>` for the mutable case. As such, it is possible to directly work on e.g. `Vec<T>`
14//! and `Box<[T]>` too.
15//!
16//! The content of the output slice will be bitwise equivalent to the input slice, as such extra
17//! care has to be taken with regard to endianness.
18//!
19//! # Example
20//! ```
21//! # extern crate byte_slice_cast;
22//! use byte_slice_cast::*;
23//!
24//! # fn main() {
25//! let slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];
26//! let converted_slice = slice.as_slice_of::<u16>().unwrap();
27//!
28//! if cfg!(target_endian = "big") {
29//!     assert_eq!(converted_slice, &[0x0102, 0x0304, 0x0506]);
30//! } else {
31//!     assert_eq!(converted_slice, &[0x0201, 0x0403, 0x0605]);
32//! }
33//!
34//! let converted_back_slice = converted_slice.as_byte_slice().unwrap();
35//! assert_eq!(converted_back_slice, &slice);
36//! # }
37//! ```
38//!
39//! # Example with mutable slices
40//! ```
41//! # extern crate byte_slice_cast;
42//! use byte_slice_cast::*;
43//!
44//! # fn main() {
45//! let mut slice = [0u8; 4];
46//! {
47//!     let mut converted_slice = slice.as_mut_slice_of::<u32>().unwrap();
48//!     converted_slice[0] = 0x12345678;
49//! }
50//!
51//! if cfg!(target_endian = "big") {
52//!     assert_eq!(&slice, &[0x12, 0x34, 0x56, 0x78]);
53//! } else {
54//!     assert_eq!(&slice, &[0x78, 0x56, 0x34, 0x12]);
55//! }
56//!
57//! # }
58//! ```
59
60use std::fmt;
61use std::mem;
62use std::slice;
63
64use std::error::Error as StdError;
65
66/// Possible errors during slice conversion.
67#[derive(Debug, PartialEq, Eq)]
68pub enum Error {
69    /// The input slice is not properly aligned for the
70    /// output data type. E.g. for an `u32` output slice
71    /// the memory must be 4-byte aligned.
72    WrongAlignment,
73    /// A non-integer number of values from the output
74    /// type would be in the output slice.
75    IncompleteNumberOfValues,
76}
77
78impl fmt::Display for Error {
79    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
80        f.write_str(self.description())
81    }
82}
83
84impl StdError for Error {
85    fn description(&self) -> &str {
86        use self::Error::*;
87
88        match *self {
89            WrongAlignment => "Wrong Alignment",
90            IncompleteNumberOfValues => "Incomplete Number of Values",
91        }
92    }
93}
94
95fn check_constraints<T, U>(data: &[T]) -> Result<usize, Error> {
96    let alignment = mem::align_of::<U>();
97
98    if (data.as_ptr() as usize) % alignment != 0 {
99        return Err(Error::WrongAlignment);
100    }
101
102    let size_in = mem::size_of::<T>();
103    let size_out = mem::size_of::<U>();
104    if (data.len() * size_in) % size_out != 0 {
105        return Err(Error::IncompleteNumberOfValues);
106    }
107
108    Ok((data.len() * size_in) / size_out)
109}
110
111/// Trait for converting from a byte slice to a slice of a fundamental, built-in numeric type.
112///
113/// Usually using the `AsSliceOf` and `AsMutSliceOf` traits is more convenient.
114///
115/// # Example
116/// ```
117/// # extern crate byte_slice_cast;
118/// use byte_slice_cast::*;
119///
120/// # fn main() {
121/// let slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];
122/// let converted_slice = <u16 as FromByteSlice>::from_byte_slice(&slice).unwrap();
123///
124/// if cfg!(target_endian = "big") {
125///     assert_eq!(converted_slice, &[0x0102, 0x0304, 0x0506]);
126/// } else {
127///     assert_eq!(converted_slice, &[0x0201, 0x0403, 0x0605]);
128/// }
129/// # }
130/// ```
131pub unsafe trait FromByteSlice
132where
133    Self: Sized,
134{
135    /// Convert from an immutable byte slice to a immutable slice of a fundamental, built-in
136    /// numeric type
137    fn from_byte_slice<T: AsRef<[u8]> + ?Sized>(&T) -> Result<&[Self], Error>;
138    /// Convert from an mutable byte slice to a mutable slice of a fundamental, built-in numeric
139    /// type
140    fn from_mut_byte_slice<T: AsMut<[u8]> + ?Sized>(&mut T) -> Result<&mut [Self], Error>;
141}
142
143/// Trait for converting from an immutable slice of a fundamental, built-in numeric type to an
144/// immutable byte slice.
145///
146/// Usually using the `AsByteSlice` trait is more convenient.
147///
148/// # Example
149/// ```
150/// # extern crate byte_slice_cast;
151/// use byte_slice_cast::*;
152///
153/// # fn main() {
154/// let slice: [u16; 3] = [0x0102, 0x0304, 0x0506];
155/// let converted_slice = ToByteSlice::to_byte_slice(&slice).unwrap();
156///
157/// if cfg!(target_endian = "big") {
158///     assert_eq!(converted_slice, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
159/// } else {
160///     assert_eq!(converted_slice, &[2u8, 1u8, 4u8, 3u8, 6u8, 5u8]);
161/// }
162/// # }
163/// ```
164pub unsafe trait ToByteSlice
165where
166    Self: Sized,
167{
168    /// Convert from an immutable slice of a fundamental, built-in numeric type to an immutable
169    /// byte slice
170    fn to_byte_slice<T: AsRef<[Self]> + ?Sized>(slice: &T) -> Result<&[u8], Error>;
171}
172
173/// Trait for converting from a mutable slice of a fundamental, built-in numeric type to a mutable
174/// byte slice.
175///
176/// Usually using the `AsMutByteSlice` trait is more convenient.
177///
178/// # Example
179/// ```
180/// # extern crate byte_slice_cast;
181/// use byte_slice_cast::*;
182///
183/// # fn main() {
184/// let mut slice: [u16; 3] = [0x0102, 0x0304, 0x0506];
185/// let converted_slice = ToMutByteSlice::to_mut_byte_slice(&mut slice).unwrap();
186///
187/// if cfg!(target_endian = "big") {
188///     assert_eq!(converted_slice, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
189/// } else {
190///     assert_eq!(converted_slice, &[2u8, 1u8, 4u8, 3u8, 6u8, 5u8]);
191/// }
192/// # }
193/// ```
194pub unsafe trait ToMutByteSlice
195where
196    Self: Sized,
197{
198    /// Convert from a mutable slice of a fundamental, built-in numeric type to a mutable byte
199    /// slice
200    fn to_mut_byte_slice<T: AsMut<[Self]> + ?Sized>(slice: &mut T) -> Result<&mut [u8], Error>;
201}
202
203macro_rules! impl_trait(
204    ($to:ty) => {
205        unsafe impl FromByteSlice for $to {
206            fn from_byte_slice<T: AsRef<[u8]> + ?Sized>(slice: &T) -> Result<&[$to], Error> {
207                let slice = slice.as_ref();
208                let len = check_constraints::<u8, $to>(slice)?;
209                unsafe {
210                    Ok(slice::from_raw_parts(slice.as_ptr() as *const $to, len))
211                }
212            }
213
214            fn from_mut_byte_slice<T: AsMut<[u8]> + ?Sized>(slice: &mut T) -> Result<&mut [$to], Error> {
215                let slice = slice.as_mut();
216                let len = check_constraints::<u8, $to>(slice)?;
217                unsafe {
218                    Ok(slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut $to, len))
219                }
220            }
221        }
222
223        unsafe impl ToByteSlice for $to {
224            fn to_byte_slice<T: AsRef<[$to]> + ?Sized>(slice: &T) -> Result<&[u8], Error> {
225                let slice = slice.as_ref();
226                let len = check_constraints::<$to, u8>(slice)?;
227                unsafe {
228                    Ok(slice::from_raw_parts(slice.as_ptr() as *const u8, len))
229                }
230            }
231        }
232
233        unsafe impl ToMutByteSlice for $to {
234            fn to_mut_byte_slice<T: AsMut<[$to]> + ?Sized>(slice: &mut T) -> Result<&mut [u8], Error> {
235                let slice = slice.as_mut();
236                let len = check_constraints::<$to, u8>(slice)?;
237                unsafe {
238                    Ok(slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, len))
239                }
240            }
241        }
242    };
243);
244
245impl_trait!(u8);
246impl_trait!(u16);
247impl_trait!(u32);
248impl_trait!(u64);
249impl_trait!(u128);
250impl_trait!(i8);
251impl_trait!(i16);
252impl_trait!(i32);
253impl_trait!(i64);
254impl_trait!(i128);
255impl_trait!(f32);
256impl_trait!(f64);
257
258/// Trait for converting from a byte slice to a slice of a fundamental, built-in numeric type.
259///
260/// This trait is usually more convenient to use than `FromByteSlice`.
261///
262/// # Example
263/// ```
264/// # extern crate byte_slice_cast;
265/// use byte_slice_cast::*;
266///
267/// # fn main() {
268/// let slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];
269/// let converted_slice = slice.as_slice_of::<u16>().unwrap();
270///
271/// if cfg!(target_endian = "big") {
272///     assert_eq!(converted_slice, &[0x0102, 0x0304, 0x0506]);
273/// } else {
274///     assert_eq!(converted_slice, &[0x0201, 0x0403, 0x0605]);
275/// }
276/// # }
277/// ```
278pub trait AsSliceOf {
279    fn as_slice_of<T: FromByteSlice>(&self) -> Result<&[T], Error>;
280}
281
282impl<U: AsRef<[u8]> + ?Sized> AsSliceOf for U {
283    fn as_slice_of<T: FromByteSlice>(&self) -> Result<&[T], Error> {
284        FromByteSlice::from_byte_slice(self)
285    }
286}
287
288/// Trait for converting from a mutable byte slice to a mutable slice of a fundamental, built-in
289/// numeric type.
290///
291/// This trait is usually more convenient to use than `FromByteSlice`.
292///
293/// # Example
294/// ```
295/// # extern crate byte_slice_cast;
296/// use byte_slice_cast::*;
297///
298/// # fn main() {
299/// let mut slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];
300/// let converted_slice = slice.as_mut_slice_of::<u16>().unwrap();
301///
302/// if cfg!(target_endian = "big") {
303///     assert_eq!(converted_slice, &[0x0102, 0x0304, 0x0506]);
304/// } else {
305///     assert_eq!(converted_slice, &[0x0201, 0x0403, 0x0605]);
306/// }
307/// # }
308/// ```
309pub trait AsMutSliceOf {
310    fn as_mut_slice_of<T: FromByteSlice>(&mut self) -> Result<&mut [T], Error>;
311}
312
313impl<U: AsMut<[u8]> + ?Sized> AsMutSliceOf for U {
314    fn as_mut_slice_of<T: FromByteSlice>(&mut self) -> Result<&mut [T], Error> {
315        FromByteSlice::from_mut_byte_slice(self)
316    }
317}
318
319/// Trait for converting from an immutable slice of a fundamental, built-in numeric type to an
320/// immutable byte slice.
321///
322/// This trait is usually more convenient to use than `ToByteSlice`.
323///
324/// # Example
325/// ```
326/// # extern crate byte_slice_cast;
327/// use byte_slice_cast::*;
328///
329/// # fn main() {
330/// let slice: [u16; 3] = [0x0102, 0x0304, 0x0506];
331/// let converted_slice = slice.as_byte_slice().unwrap();
332///
333/// if cfg!(target_endian = "big") {
334///     assert_eq!(converted_slice, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
335/// } else {
336///     assert_eq!(converted_slice, &[2u8, 1u8, 4u8, 3u8, 6u8, 5u8]);
337/// }
338/// # }
339/// ```
340pub trait AsByteSlice<T> {
341    fn as_byte_slice(&self) -> Result<&[u8], Error>;
342}
343
344impl<T: ToByteSlice, U: AsRef<[T]> + ?Sized> AsByteSlice<T> for U {
345    fn as_byte_slice(&self) -> Result<&[u8], Error> {
346        ToByteSlice::to_byte_slice(self)
347    }
348}
349
350/// Trait for converting from a mutable slice of a fundamental, built-in numeric type to a mutable
351/// byte slice. This trait is usually more convenient to use than `ToMutByteSlice`.
352///
353/// # Example
354/// ```
355/// # extern crate byte_slice_cast;
356/// use byte_slice_cast::*;
357///
358/// # fn main() {
359/// let mut slice: [u16; 3] = [0x0102, 0x0304, 0x0506];
360/// let converted_slice = slice.as_mut_byte_slice().unwrap();
361///
362/// if cfg!(target_endian = "big") {
363///     assert_eq!(converted_slice, &mut [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
364/// } else {
365///     assert_eq!(converted_slice, &mut [2u8, 1u8, 4u8, 3u8, 6u8, 5u8]);
366/// }
367/// # }
368/// ```
369pub trait AsMutByteSlice<T> {
370    fn as_mut_byte_slice(&mut self) -> Result<&mut [u8], Error>;
371}
372
373impl<T: ToMutByteSlice, U: AsMut<[T]> + ?Sized> AsMutByteSlice<T> for U {
374    fn as_mut_byte_slice(&mut self) -> Result<&mut [u8], Error> {
375        ToMutByteSlice::to_mut_byte_slice(self)
376    }
377}
378
379#[cfg(test)]
380mod tests {
381    use super::*;
382
383    #[test]
384    fn u8() {
385        let input: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
386
387        let output: &[u8] = input.as_slice_of::<u8>().unwrap();
388        assert_eq!(&input, output);
389
390        let output2: &[u8] = input.as_byte_slice().unwrap();
391        assert_eq!(&input, output2);
392    }
393
394    #[test]
395    fn u16() {
396        let slice: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
397        let bytes = slice.as_byte_slice().unwrap();
398
399        if cfg!(target_endian = "big") {
400            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
401        } else {
402            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
403        }
404
405        assert_eq!(
406            (&bytes[1..]).as_slice_of::<u16>(),
407            Err(Error::WrongAlignment)
408        );
409        assert_eq!(
410            (&bytes[0..15]).as_slice_of::<u16>(),
411            Err(Error::IncompleteNumberOfValues)
412        );
413        assert_eq!(bytes.as_slice_of::<u16>(), Ok(slice.as_ref()));
414    }
415
416    #[test]
417    fn u32() {
418        let slice: [u32; 4] = [0, 1, 2, 3];
419        let bytes = slice.as_byte_slice().unwrap();
420
421        if cfg!(target_endian = "big") {
422            assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3]);
423        } else {
424            assert_eq!(bytes, &[0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]);
425        }
426
427        assert_eq!(
428            (&bytes[1..]).as_slice_of::<u32>(),
429            Err(Error::WrongAlignment)
430        );
431        assert_eq!(
432            (&bytes[0..15]).as_slice_of::<u32>(),
433            Err(Error::IncompleteNumberOfValues)
434        );
435        assert_eq!(bytes.as_slice_of::<u32>(), Ok(slice.as_ref()));
436    }
437
438    #[test]
439    fn u64() {
440        let slice: [u64; 2] = [0, 1];
441        let bytes = slice.as_byte_slice().unwrap();
442
443        if cfg!(target_endian = "big") {
444            assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
445        } else {
446            assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]);
447        }
448
449        assert_eq!(
450            (&bytes[1..]).as_slice_of::<u64>(),
451            Err(Error::WrongAlignment)
452        );
453        assert_eq!(
454            (&bytes[0..15]).as_slice_of::<u64>(),
455            Err(Error::IncompleteNumberOfValues)
456        );
457        assert_eq!(bytes.as_slice_of::<u64>(), Ok(slice.as_ref()));
458    }
459
460    #[test]
461    fn f32() {
462        let slice: [f32; 4] = [2.0, 1.0, 0.5, 0.25];
463        let bytes = slice.as_byte_slice().unwrap();
464
465        if cfg!(target_endian = "big") {
466            assert_eq!(
467                bytes,
468                [
469                    0x40, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3e,
470                    0x80, 0x00, 0x00
471                ]
472            );
473        } else {
474            assert_eq!(
475                bytes,
476                [
477                    0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00,
478                    0x00, 0x80, 0x3e
479                ]
480            );
481        };
482
483        assert_eq!(
484            (&bytes[1..]).as_slice_of::<f32>(),
485            Err(Error::WrongAlignment)
486        );
487        assert_eq!(
488            (&bytes[0..15]).as_slice_of::<f32>(),
489            Err(Error::IncompleteNumberOfValues)
490        );
491        assert_eq!(bytes.as_slice_of::<f32>(), Ok(slice.as_ref()));
492    }
493
494    #[test]
495    fn f64() {
496        let slice: [f64; 2] = [2.0, 0.5];
497        let bytes = slice.as_byte_slice().unwrap();
498
499        if cfg!(target_endian = "big") {
500            assert_eq!(
501                bytes,
502                [
503                    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00,
504                    0x00, 0x00, 0x00
505                ]
506            );
507        } else {
508            assert_eq!(
509                bytes,
510                [
511                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
512                    0x00, 0xe0, 0x3f
513                ]
514            );
515        };
516
517        assert_eq!(
518            (&bytes[1..]).as_slice_of::<f64>(),
519            Err(Error::WrongAlignment)
520        );
521        assert_eq!(
522            (&bytes[0..15]).as_slice_of::<f64>(),
523            Err(Error::IncompleteNumberOfValues)
524        );
525        assert_eq!(bytes.as_slice_of::<f64>(), Ok(slice.as_ref()));
526    }
527
528    #[test]
529    fn u16_mut() {
530        let mut slice: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
531        let mut slice_2: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
532        let bytes = slice_2.as_mut_byte_slice().unwrap();
533
534        if cfg!(target_endian = "big") {
535            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
536        } else {
537            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
538        }
539
540        assert_eq!(
541            (&mut bytes[1..]).as_mut_slice_of::<u16>(),
542            Err(Error::WrongAlignment)
543        );
544        assert_eq!(
545            (&mut bytes[0..15]).as_mut_slice_of::<u16>(),
546            Err(Error::IncompleteNumberOfValues)
547        );
548        assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(slice.as_mut()));
549    }
550
551    #[test]
552    fn u16_vec() {
553        let vec: Vec<u16> = vec![0, 1, 2, 3, 4, 5, 6, 7];
554        let bytes = vec.as_byte_slice().unwrap();
555
556        if cfg!(target_endian = "big") {
557            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
558        } else {
559            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
560        }
561
562        assert_eq!(
563            (&bytes[1..]).as_slice_of::<u16>(),
564            Err(Error::WrongAlignment)
565        );
566        assert_eq!(
567            (&bytes[0..15]).as_slice_of::<u16>(),
568            Err(Error::IncompleteNumberOfValues)
569        );
570        assert_eq!(bytes.as_slice_of::<u16>(), Ok(vec.as_ref()));
571    }
572
573    #[test]
574    fn u16_mut_vec() {
575        let mut vec: Vec<u16> = vec![0, 1, 2, 3, 4, 5, 6, 7];
576        let mut vec_clone = vec.clone();
577        let bytes = vec_clone.as_mut_byte_slice().unwrap();
578
579        if cfg!(target_endian = "big") {
580            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
581        } else {
582            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
583        }
584
585        assert_eq!(
586            (&mut bytes[1..]).as_mut_slice_of::<u16>(),
587            Err(Error::WrongAlignment)
588        );
589        assert_eq!(
590            (&mut bytes[0..15]).as_mut_slice_of::<u16>(),
591            Err(Error::IncompleteNumberOfValues)
592        );
593        assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(vec.as_mut()));
594    }
595
596    #[test]
597    fn u16_box_slice() {
598        let vec: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
599        let bytes = vec.as_byte_slice().unwrap();
600
601        if cfg!(target_endian = "big") {
602            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
603        } else {
604            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
605        }
606
607        assert_eq!(
608            (&bytes[1..]).as_slice_of::<u16>(),
609            Err(Error::WrongAlignment)
610        );
611        assert_eq!(
612            (&bytes[0..15]).as_slice_of::<u16>(),
613            Err(Error::IncompleteNumberOfValues)
614        );
615        assert_eq!(bytes.as_slice_of::<u16>(), Ok(vec.as_ref()));
616    }
617
618    #[test]
619    fn u16_mut_box_slice() {
620        let mut vec: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
621        let mut vec_clone: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
622        let bytes = vec_clone.as_mut_byte_slice().unwrap();
623
624        if cfg!(target_endian = "big") {
625            assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
626        } else {
627            assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
628        }
629
630        assert_eq!(
631            (&mut bytes[1..]).as_mut_slice_of::<u16>(),
632            Err(Error::WrongAlignment)
633        );
634        assert_eq!(
635            (&mut bytes[0..15]).as_mut_slice_of::<u16>(),
636            Err(Error::IncompleteNumberOfValues)
637        );
638        assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(vec.as_mut()));
639    }
640}