// compile-flags: -Zmiri-symbolic-alignment-check fn test_align_offset() { let d = Box::new([0u32; 4]); // Get u8 pointer to base let raw = d.as_ptr() as *const u8; assert_eq!(raw.align_offset(2), 0); assert_eq!(raw.align_offset(4), 0); assert_eq!(raw.align_offset(8), usize::MAX); // requested alignment higher than allocation alignment assert_eq!(raw.wrapping_offset(1).align_offset(2), 1); assert_eq!(raw.wrapping_offset(1).align_offset(4), 3); assert_eq!(raw.wrapping_offset(1).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment assert_eq!(raw.wrapping_offset(2).align_offset(2), 0); assert_eq!(raw.wrapping_offset(2).align_offset(4), 2); assert_eq!(raw.wrapping_offset(2).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment } fn test_align_to() { const N: usize = 4; let d = Box::new([0u32; N]); // Get u8 slice covering the entire thing let s = unsafe { std::slice::from_raw_parts(d.as_ptr() as *const u8, 4 * N) }; let raw = s.as_ptr(); { let (l, m, r) = unsafe { s.align_to::() }; assert_eq!(l.len(), 0); assert_eq!(r.len(), 0); assert_eq!(m.len(), N); assert_eq!(raw, m.as_ptr() as *const u8); } { let (l, m, r) = unsafe { s[1..].align_to::() }; assert_eq!(l.len(), 3); assert_eq!(m.len(), N-1); assert_eq!(r.len(), 0); assert_eq!(raw.wrapping_offset(4), m.as_ptr() as *const u8); } { let (l, m, r) = unsafe { s[..4*N - 1].align_to::() }; assert_eq!(l.len(), 0); assert_eq!(m.len(), N-1); assert_eq!(r.len(), 3); assert_eq!(raw, m.as_ptr() as *const u8); } { let (l, m, r) = unsafe { s[1..4*N - 1].align_to::() }; assert_eq!(l.len(), 3); assert_eq!(m.len(), N-2); assert_eq!(r.len(), 3); assert_eq!(raw.wrapping_offset(4), m.as_ptr() as *const u8); } { #[repr(align(8))] struct Align8(u64); let (l, m, r) = unsafe { s.align_to::() }; // requested alignment higher than allocation alignment assert_eq!(l.len(), 4*N); assert_eq!(r.len(), 0); assert_eq!(m.len(), 0); } } fn test_from_utf8() { const N: usize = 10; let vec = vec![0x4141414141414141u64; N]; let content = unsafe { std::slice::from_raw_parts(vec.as_ptr() as *const u8, 8 * N) }; println!("{:?}", std::str::from_utf8(content).unwrap()); } fn test_u64_array() { #[derive(Default)] #[repr(align(8))] struct AlignToU64(T); const BYTE_LEN: usize = std::mem::size_of::<[u64; 4]>(); type Data = AlignToU64<[u8; BYTE_LEN]>; fn example(data: &Data) { let (head, u64_arrays, tail) = unsafe { data.0.align_to::<[u64; 4]>() }; assert!(head.is_empty(), "buffer was not aligned for 64-bit numbers"); assert_eq!(u64_arrays.len(), 1, "buffer was not long enough"); assert!(tail.is_empty(), "buffer was too long"); let u64_array = &u64_arrays[0]; let _val = u64_array[0]; // make sure we can actually load this } example(&Data::default()); } fn main() { test_align_offset(); test_align_to(); test_from_utf8(); test_u64_array(); }