1#![cfg_attr(not(feature = "std"), no_std)]
6#![allow(clippy::missing_safety_doc)]
7
8use core::{fmt, mem, slice};
67
68#[cfg(feature = "std")]
69use std::error::Error as StdError;
70
71#[derive(Clone, Debug, PartialEq, Eq)]
73pub enum Error {
74 AlignmentMismatch {
78 dst_type: &'static str,
79 dst_minimum_alignment: usize,
80 },
81 LengthMismatch {
84 dst_type: &'static str,
85 src_slice_size: usize,
86 dst_type_size: usize,
87 },
88}
89
90impl fmt::Display for Error {
91 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
92 match self {
93 Error::AlignmentMismatch {
94 dst_type,
95 dst_minimum_alignment,
96 } => {
97 write!(
98 f,
99 "cannot cast a &[u8] into a &[{}]: the slice's address is not divisible by the minimum alignment ({}) of {}",
100 dst_type,
101 dst_minimum_alignment,
102 dst_type
103 )?;
104 }
105 Error::LengthMismatch {
106 dst_type,
107 src_slice_size,
108 dst_type_size,
109 } => {
110 write!(
111 f,
112 "cannot cast a &[u8] into a &[{}]: the size ({}) of the slice is not divisible by the size ({}) of {}",
113 dst_type,
114 src_slice_size,
115 dst_type_size,
116 dst_type
117 )?;
118 }
119 }
120
121 Ok(())
122 }
123}
124
125trait TypeName {
126 const TYPE_NAME: &'static str;
127}
128
129#[cfg(feature = "std")]
130impl StdError for Error {
131 fn description(&self) -> &str {
132 use self::Error::*;
133
134 match *self {
135 AlignmentMismatch { .. } => "Alignment Mismatch",
136 LengthMismatch { .. } => "Length Mismatch",
137 }
138 }
139}
140
141fn check_alignment<T, U>(data: &T) -> Result<usize, Error>
142where
143 U: TypeName,
144 T: AsRef<[u8]> + ?Sized,
145{
146 let alignment = mem::align_of::<U>();
147
148 if (data.as_ref().as_ptr() as usize) % alignment != 0 {
149 let err = Error::AlignmentMismatch {
150 dst_type: U::TYPE_NAME,
151 dst_minimum_alignment: alignment,
152 };
153 return Err(err);
154 }
155 Ok(alignment)
156}
157
158fn check_length<T, U>(data: &T) -> Result<usize, Error>
159where
160 U: TypeName,
161 T: AsRef<[u8]> + ?Sized,
162{
163 let size_out = mem::size_of::<U>();
164 if data.as_ref().len() % size_out != 0 {
165 let err = Error::LengthMismatch {
166 dst_type: U::TYPE_NAME,
167 src_slice_size: data.as_ref().len(),
168 dst_type_size: size_out,
169 };
170 return Err(err);
171 }
172 Ok(size_out)
173}
174
175fn check_constraints<U>(data: &[u8]) -> Result<usize, Error>
176where
177 U: TypeName,
178{
179 if data.is_empty() {
180 return Ok(0);
181 }
182
183 check_alignment::<[u8], U>(data)?;
184 let size_out = check_length::<[u8], U>(data)?;
185
186 Ok(data.len() / size_out)
187}
188
189macro_rules! impl_trait(
190 ($to:ty) => {
191 impl TypeName for $to {
192 const TYPE_NAME: &'static str = stringify!($to);
193 }
194
195 unsafe impl FromByteSlice for $to {
196 #[inline]
197 fn from_byte_slice<T: AsRef<[u8]> + ?Sized>(slice: &T) -> Result<&[$to], Error> {
198 let slice = slice.as_ref();
199 let len = check_constraints::<$to>(slice)?;
200
201 if len == 0 {
204 Ok(&[])
205 } else {
206 #[allow(clippy::cast_ptr_alignment)]
207 unsafe {
208 Ok(slice::from_raw_parts(slice.as_ptr() as *const $to, len))
209 }
210 }
211 }
212
213 #[inline]
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::<$to>(slice)?;
217
218 if len == 0 {
221 Ok(&mut [])
222 } else {
223 #[allow(clippy::cast_ptr_alignment)]
224 unsafe {
225 Ok(slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut $to, len))
226 }
227 }
228 }
229 }
230
231 unsafe impl ToByteSlice for $to {
232 #[inline]
233 fn to_byte_slice<T: AsRef<[$to]> + ?Sized>(slice: &T) -> &[u8] {
234 let slice = slice.as_ref();
235 let len = slice.len() * mem::size_of::<$to>();
236 unsafe {
237 slice::from_raw_parts(slice.as_ptr() as *const u8, len)
238 }
239 }
240 }
241
242 unsafe impl ToMutByteSlice for $to {
243 #[inline]
244 fn to_mut_byte_slice<T: AsMut<[$to]> + ?Sized>(slice: &mut T) -> &mut [u8] {
245 let slice = slice.as_mut();
246 let len = slice.len() * mem::size_of::<$to>();
247 unsafe {
248 slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, len)
249 }
250 }
251 }
252 };
253);
254
255macro_rules! impl_trait_array (
256 ($to:ty) => {
257 impl<const N: usize> TypeName for [$to; N] {
258 const TYPE_NAME: &'static str = stringify!([$to; N]);
259 }
260
261 unsafe impl<const N: usize> FromByteSlice for [$to; N] {
262 #[inline]
263 fn from_byte_slice<T: AsRef<[u8]> + ?Sized>(slice: &T) -> Result<&[[$to; N]], Error> {
264 let slice = slice.as_ref();
265 let len = check_constraints::<[$to; N]>(slice)?;
266
267 if len == 0 {
270 Ok(&[])
271 } else {
272 #[allow(clippy::cast_ptr_alignment)]
273 unsafe {
274 Ok(slice::from_raw_parts(slice.as_ptr() as *const [$to; N], len))
275 }
276 }
277 }
278
279 #[inline]
280 fn from_mut_byte_slice<T: AsMut<[u8]> + ?Sized>(slice: &mut T) -> Result<&mut [[$to; N]], Error> {
281 let slice = slice.as_mut();
282 let len = check_constraints::<[$to; N]>(slice)?;
283
284 if len == 0 {
287 Ok(&mut [])
288 } else {
289 #[allow(clippy::cast_ptr_alignment)]
290 unsafe {
291 Ok(slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut [$to; N], len))
292 }
293 }
294 }
295 }
296
297 unsafe impl<const N: usize> ToByteSlice for [$to; N] {
298 #[inline]
299 fn to_byte_slice<T: AsRef<[[$to; N]]> + ?Sized>(slice: &T) -> &[u8] {
300 let slice = slice.as_ref();
301 let len = slice.len() * mem::size_of::<[$to; N]>();
302 unsafe {
303 slice::from_raw_parts(slice.as_ptr() as *const u8, len)
304 }
305 }
306 }
307
308 unsafe impl<const N: usize> ToMutByteSlice for [$to; N] {
309 #[inline]
310 fn to_mut_byte_slice<T: AsMut<[[$to; N]]> + ?Sized>(slice: &mut T) -> &mut [u8] {
311 let slice = slice.as_mut();
312 let len = slice.len() * mem::size_of::<[$to; N]>();
313 unsafe {
314 slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, len)
315 }
316 }
317 }
318 };
319);
320
321pub unsafe trait FromByteSlice
328where
329 Self: Sized,
330{
331 fn from_byte_slice<T: AsRef<[u8]> + ?Sized>(slice: &T) -> Result<&[Self], Error>;
334 fn from_mut_byte_slice<T: AsMut<[u8]> + ?Sized>(slice: &mut T) -> Result<&mut [Self], Error>;
337}
338
339pub unsafe trait ToByteSlice
346where
347 Self: Sized,
348{
349 fn to_byte_slice<T: AsRef<[Self]> + ?Sized>(slice: &T) -> &[u8];
352}
353
354pub unsafe trait ToMutByteSlice
361where
362 Self: Sized,
363{
364 fn to_mut_byte_slice<T: AsMut<[Self]> + ?Sized>(slice: &mut T) -> &mut [u8];
367}
368
369pub trait AsSliceOf {
388 fn as_slice_of<T: FromByteSlice>(&self) -> Result<&[T], Error>;
389}
390
391impl<U: AsRef<[u8]> + ?Sized> AsSliceOf for U {
392 #[inline]
393 fn as_slice_of<T: FromByteSlice>(&self) -> Result<&[T], Error> {
394 FromByteSlice::from_byte_slice(self)
395 }
396}
397
398pub trait AsMutSliceOf {
418 fn as_mut_slice_of<T: FromByteSlice>(&mut self) -> Result<&mut [T], Error>;
419}
420
421impl<U: AsMut<[u8]> + ?Sized> AsMutSliceOf for U {
422 #[inline]
423 fn as_mut_slice_of<T: FromByteSlice>(&mut self) -> Result<&mut [T], Error> {
424 FromByteSlice::from_mut_byte_slice(self)
425 }
426}
427
428pub trait AsByteSlice<T> {
448 fn as_byte_slice(&self) -> &[u8];
449}
450
451impl<T: ToByteSlice, U: AsRef<[T]> + ?Sized> AsByteSlice<T> for U {
452 #[inline]
453 fn as_byte_slice(&self) -> &[u8] {
454 ToByteSlice::to_byte_slice(self)
455 }
456}
457
458pub trait AsMutByteSlice<T> {
478 fn as_mut_byte_slice(&mut self) -> &mut [u8];
479}
480
481impl<T: ToMutByteSlice, U: AsMut<[T]> + ?Sized> AsMutByteSlice<T> for U {
482 #[inline]
483 fn as_mut_byte_slice(&mut self) -> &mut [u8] {
484 ToMutByteSlice::to_mut_byte_slice(self)
485 }
486}
487
488impl_trait!(u8);
489impl_trait!(u16);
490impl_trait!(u32);
491impl_trait!(u64);
492impl_trait!(u128);
493impl_trait!(i8);
494impl_trait!(i16);
495impl_trait!(i32);
496impl_trait!(i64);
497impl_trait!(i128);
498impl_trait!(f32);
499impl_trait!(f64);
500impl_trait!(usize);
501impl_trait!(isize);
502
503impl_trait_array!(u8);
504impl_trait_array!(u16);
505impl_trait_array!(u32);
506impl_trait_array!(u64);
507impl_trait_array!(u128);
508impl_trait_array!(i8);
509impl_trait_array!(i16);
510impl_trait_array!(i32);
511impl_trait_array!(i64);
512impl_trait_array!(i128);
513impl_trait_array!(f32);
514impl_trait_array!(f64);
515impl_trait_array!(usize);
516impl_trait_array!(isize);
517
518impl TypeName for () {
519 const TYPE_NAME: &'static str = "()";
520}
521
522unsafe impl ToByteSlice for () {
523 #[inline]
524 fn to_byte_slice<T: AsRef<[()]> + ?Sized>(_: &T) -> &[u8] {
525 &[]
526 }
527}
528
529unsafe impl ToMutByteSlice for () {
530 #[inline]
531 fn to_mut_byte_slice<T: AsMut<[()]> + ?Sized>(_: &mut T) -> &mut [u8] {
532 &mut []
533 }
534}
535
536#[cfg(test)]
537mod tests {
538 use super::*;
539
540 #[test]
541 fn u8() {
542 let input: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
543
544 let output: &[u8] = input.as_slice_of::<u8>().unwrap();
545 assert_eq!(&input, output);
546
547 let output2: &[u8] = input.as_byte_slice();
548 assert_eq!(&input, output2);
549 }
550
551 #[test]
552 fn u16() {
553 let slice: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
554 let bytes = slice.as_byte_slice();
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::AlignmentMismatch {
565 dst_type: "u16",
566 dst_minimum_alignment: mem::align_of::<u16>()
567 })
568 );
569 assert_eq!(
570 (bytes[0..15]).as_slice_of::<u16>(),
571 Err(Error::LengthMismatch {
572 dst_type: "u16",
573 src_slice_size: 15,
574 dst_type_size: 2
575 })
576 );
577 assert_eq!(bytes.as_slice_of::<u16>(), Ok(slice.as_ref()));
578 }
579
580 #[cfg(feature = "std")]
581 #[test]
582 fn u16_error_string() {
583 let slice: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
584 let bytes = slice.as_byte_slice();
585
586 let error = (bytes[1..]).as_slice_of::<u16>().unwrap_err().to_string();
587 assert_eq!(
588 error,
589 "cannot cast a &[u8] into a &[u16]: the slice's address is not divisible by the minimum alignment (2) of u16",
590 );
591 let error = (bytes[0..15]).as_slice_of::<u16>().unwrap_err().to_string();
592 assert_eq!(
593 error,
594 "cannot cast a &[u8] into a &[u16]: the size (15) of the slice is not divisible by the size (2) of u16"
595 );
596 }
597
598 #[test]
599 fn u32() {
600 let slice: [u32; 4] = [0, 1, 2, 3];
601 let bytes = slice.as_byte_slice();
602
603 if cfg!(target_endian = "big") {
604 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3]);
605 } else {
606 assert_eq!(bytes, &[0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]);
607 }
608
609 assert_eq!(
610 (bytes[1..]).as_slice_of::<u32>(),
611 Err(Error::AlignmentMismatch {
612 dst_type: "u32",
613 dst_minimum_alignment: mem::align_of::<u32>()
614 })
615 );
616 assert_eq!(
617 (bytes[0..15]).as_slice_of::<u32>(),
618 Err(Error::LengthMismatch {
619 dst_type: "u32",
620 src_slice_size: 15,
621 dst_type_size: 4
622 })
623 );
624 assert_eq!(bytes.as_slice_of::<u32>(), Ok(slice.as_ref()));
625 }
626
627 #[test]
628 fn u64() {
629 let slice: [u64; 2] = [0, 1];
630 let bytes = slice.as_byte_slice();
631
632 if cfg!(target_endian = "big") {
633 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
634 } else {
635 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]);
636 }
637
638 assert_eq!(
639 (bytes[1..]).as_slice_of::<u64>(),
640 Err(Error::AlignmentMismatch {
641 dst_type: "u64",
642 dst_minimum_alignment: mem::align_of::<u64>()
643 })
644 );
645 assert_eq!(
646 (bytes[0..15]).as_slice_of::<u64>(),
647 Err(Error::LengthMismatch {
648 dst_type: "u64",
649 src_slice_size: 15,
650 dst_type_size: 8
651 })
652 );
653 assert_eq!(bytes.as_slice_of::<u64>(), Ok(slice.as_ref()));
654 }
655
656 #[test]
657 #[allow(clippy::collapsible_if)]
658 #[allow(clippy::collapsible_else_if)]
659 fn usize() {
660 let slice: [usize; 2] = [0, 1];
661 let bytes = slice.as_byte_slice();
662
663 if cfg!(target_endian = "big") {
664 if cfg!(target_pointer_width = "16") {
665 assert_eq!(bytes, &[0, 0, 0, 1]);
666 } else if cfg!(target_pointer_width = "32") {
667 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 1]);
668 } else if cfg!(target_pointer_width = "64") {
669 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
670 } else {
671 panic!("Unhandled target_endian/target_pointer_width configuration");
672 }
673 } else {
674 if cfg!(target_pointer_width = "16") {
675 assert_eq!(bytes, &[0, 0, 1, 0]);
676 } else if cfg!(target_pointer_width = "32") {
677 assert_eq!(bytes, &[0, 0, 0, 0, 1, 0, 0, 0]);
678 } else if cfg!(target_pointer_width = "64") {
679 assert_eq!(bytes, &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]);
680 } else {
681 panic!("Unhandled target_endian/target_pointer_width configuration");
682 }
683 }
684
685 assert_eq!(
686 (bytes[1..]).as_slice_of::<usize>(),
687 Err(Error::AlignmentMismatch {
688 dst_type: "usize",
689 dst_minimum_alignment: mem::align_of::<usize>()
690 })
691 );
692 assert_eq!(
693 (bytes[0..3]).as_slice_of::<usize>(),
694 Err(Error::LengthMismatch {
695 dst_type: "usize",
696 src_slice_size: 3,
697 dst_type_size: mem::size_of::<usize>()
698 })
699 );
700 assert_eq!(bytes.as_slice_of::<usize>(), Ok(slice.as_ref()));
701 }
702
703 #[test]
704 fn f32() {
705 let slice: [f32; 4] = [2.0, 1.0, 0.5, 0.25];
706 let bytes = slice.as_byte_slice();
707
708 if cfg!(target_endian = "big") {
709 assert_eq!(
710 bytes,
711 [
712 0x40, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3e,
713 0x80, 0x00, 0x00
714 ]
715 );
716 } else {
717 assert_eq!(
718 bytes,
719 [
720 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00,
721 0x00, 0x80, 0x3e
722 ]
723 );
724 };
725
726 assert_eq!(
727 (bytes[1..]).as_slice_of::<f32>(),
728 Err(Error::AlignmentMismatch {
729 dst_type: "f32",
730 dst_minimum_alignment: mem::align_of::<f32>()
731 })
732 );
733 assert_eq!(
734 (bytes[0..15]).as_slice_of::<f32>(),
735 Err(Error::LengthMismatch {
736 dst_type: "f32",
737 src_slice_size: 15,
738 dst_type_size: 4
739 })
740 );
741 assert_eq!(bytes.as_slice_of::<f32>(), Ok(slice.as_ref()));
742 }
743
744 #[test]
745 fn f64() {
746 let slice: [f64; 2] = [2.0, 0.5];
747 let bytes = slice.as_byte_slice();
748
749 if cfg!(target_endian = "big") {
750 assert_eq!(
751 bytes,
752 [
753 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00
755 ]
756 );
757 } else {
758 assert_eq!(
759 bytes,
760 [
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0xe0, 0x3f
763 ]
764 );
765 };
766
767 assert_eq!(
768 (bytes[1..]).as_slice_of::<f64>(),
769 Err(Error::AlignmentMismatch {
770 dst_type: "f64",
771 dst_minimum_alignment: mem::align_of::<f64>()
772 })
773 );
774 assert_eq!(
775 (bytes[0..15]).as_slice_of::<f64>(),
776 Err(Error::LengthMismatch {
777 dst_type: "f64",
778 src_slice_size: 15,
779 dst_type_size: mem::size_of::<f64>()
780 })
781 );
782 assert_eq!(bytes.as_slice_of::<f64>(), Ok(slice.as_ref()));
783 }
784
785 #[test]
786 fn u16_mut() {
787 let mut slice: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
788 let mut slice_2: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
789 let bytes = slice_2.as_mut_byte_slice();
790
791 if cfg!(target_endian = "big") {
792 assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
793 } else {
794 assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
795 }
796
797 assert_eq!(
798 (bytes[1..]).as_mut_slice_of::<u16>(),
799 Err(Error::AlignmentMismatch {
800 dst_type: "u16",
801 dst_minimum_alignment: mem::align_of::<u16>()
802 })
803 );
804 assert_eq!(
805 (bytes[0..15]).as_mut_slice_of::<u16>(),
806 Err(Error::LengthMismatch {
807 dst_type: "u16",
808 src_slice_size: 15,
809 dst_type_size: 2
810 })
811 );
812 assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(slice.as_mut()));
813 }
814
815 #[cfg(feature = "std")]
816 #[test]
817 fn u16_vec() {
818 let vec: Vec<u16> = vec![0, 1, 2, 3, 4, 5, 6, 7];
819 let bytes = vec.as_byte_slice();
820
821 if cfg!(target_endian = "big") {
822 assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
823 } else {
824 assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
825 }
826
827 assert_eq!(
828 (bytes[1..]).as_slice_of::<u16>(),
829 Err(Error::AlignmentMismatch {
830 dst_type: "u16",
831 dst_minimum_alignment: mem::align_of::<u16>()
832 })
833 );
834 assert_eq!(
835 (bytes[0..15]).as_slice_of::<u16>(),
836 Err(Error::LengthMismatch {
837 dst_type: "u16",
838 src_slice_size: 15,
839 dst_type_size: 2
840 })
841 );
842 assert_eq!(bytes.as_slice_of::<u16>(), Ok(vec.as_ref()));
843 }
844
845 #[cfg(feature = "std")]
846 #[test]
847 fn u16_mut_vec() {
848 let mut vec: Vec<u16> = vec![0, 1, 2, 3, 4, 5, 6, 7];
849 let mut vec_clone = vec.clone();
850 let bytes = vec_clone.as_mut_byte_slice();
851
852 if cfg!(target_endian = "big") {
853 assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
854 } else {
855 assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
856 }
857
858 assert_eq!(
859 (bytes[1..]).as_mut_slice_of::<u16>(),
860 Err(Error::AlignmentMismatch {
861 dst_type: "u16",
862 dst_minimum_alignment: mem::align_of::<u16>()
863 })
864 );
865 assert_eq!(
866 (bytes[0..15]).as_mut_slice_of::<u16>(),
867 Err(Error::LengthMismatch {
868 dst_type: "u16",
869 src_slice_size: 15,
870 dst_type_size: 2
871 })
872 );
873 assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(vec.as_mut()));
874 }
875
876 #[cfg(feature = "std")]
877 #[test]
878 fn u16_box_slice() {
879 let vec: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
880 let bytes = vec.as_byte_slice();
881
882 if cfg!(target_endian = "big") {
883 assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
884 } else {
885 assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
886 }
887
888 assert_eq!(
889 (bytes[1..]).as_slice_of::<u16>(),
890 Err(Error::AlignmentMismatch {
891 dst_type: "u16",
892 dst_minimum_alignment: mem::align_of::<u16>()
893 })
894 );
895 assert_eq!(
896 (bytes[0..15]).as_slice_of::<u16>(),
897 Err(Error::LengthMismatch {
898 dst_type: "u16",
899 src_slice_size: 15,
900 dst_type_size: 2
901 })
902 );
903 assert_eq!(bytes.as_slice_of::<u16>(), Ok(vec.as_ref()));
904 }
905
906 #[cfg(feature = "std")]
907 #[test]
908 fn u16_mut_box_slice() {
909 let mut vec: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
910 let mut vec_clone: Box<[u16]> = vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice();
911 let bytes = vec_clone.as_mut_byte_slice();
912
913 if cfg!(target_endian = "big") {
914 assert_eq!(bytes, &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7]);
915 } else {
916 assert_eq!(bytes, &[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0]);
917 }
918
919 assert_eq!(
920 (bytes[1..]).as_mut_slice_of::<u16>(),
921 Err(Error::AlignmentMismatch {
922 dst_type: "u16",
923 dst_minimum_alignment: mem::align_of::<u16>()
924 })
925 );
926 assert_eq!(
927 (bytes[0..15]).as_mut_slice_of::<u16>(),
928 Err(Error::LengthMismatch {
929 dst_type: "u16",
930 src_slice_size: 15,
931 dst_type_size: 2
932 })
933 );
934 assert_eq!(bytes.as_mut_slice_of::<u16>(), Ok(vec.as_mut()));
935 }
936
937 #[test]
938 fn u16_empty_to_byte_slice() {
939 let slice: [u16; 0] = [];
940 let bytes = slice.as_byte_slice();
941
942 assert_eq!(bytes, &[]);
943 }
944
945 #[test]
946 fn u16_empty_from_byte_slice() {
947 let bytes: [u8; 0] = [];
948 let slice = bytes.as_slice_of::<u16>().unwrap();
949 assert_eq!(slice, &[]);
950 }
951
952 #[test]
953 fn unit() {
954 let slice: [(); 4] = [(), (), (), ()];
955 let bytes = slice.as_byte_slice();
956
957 assert_eq!(bytes, &[]);
958 }
959
960 #[test]
961 fn u8_array() {
962 let input: &[[u8; 3]] = &[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]][..];
963
964 let bytes: &[u8] = input.as_byte_slice();
965 assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
966
967 let output = bytes.as_slice_of::<[u8; 3]>().unwrap();
968
969 assert_eq!(output, input);
970 }
971
972 #[test]
973 fn u16_array() {
974 let input: &[[u16; 3]] = &[[0, 1, 2], [3, 4, 5]][..];
975
976 let bytes: &[u8] = input.as_byte_slice();
977 if cfg!(target_endian = "big") {
978 assert_eq!(bytes, [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5]);
979 } else {
980 assert_eq!(bytes, [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]);
981 };
982
983 assert_eq!(
984 (bytes[1..]).as_slice_of::<[u16; 3]>(),
985 Err(Error::AlignmentMismatch {
986 dst_type: "[u16; N]",
987 dst_minimum_alignment: mem::align_of::<[u16; 3]>()
988 })
989 );
990 assert_eq!(
991 (bytes[0..4]).as_slice_of::<[u16; 3]>(),
992 Err(Error::LengthMismatch {
993 dst_type: "[u16; N]",
994 src_slice_size: 4,
995 dst_type_size: 6
996 })
997 );
998
999 let output = bytes.as_slice_of::<[u16; 3]>().unwrap();
1000 assert_eq!(output, input);
1001 }
1002}