/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crc32c-0.6.8/src/util.rs
Line | Count | Source |
1 | | use std::ptr::NonNull; |
2 | | use std::{cmp, slice}; |
3 | | |
4 | | /// A newtype wrapper for a little endian `u64`. |
5 | | /// |
6 | | /// It is safe to transmute between a `u64` and `U64Le`. |
7 | | #[repr(transparent)] |
8 | | #[derive(Clone, Copy)] |
9 | | pub(crate) struct U64Le(u64); |
10 | | |
11 | | impl U64Le { |
12 | | /// Returns a `u64` with correct endianness for the target. |
13 | | /// |
14 | | /// On little endian targets, this is a no-op. |
15 | | #[allow(clippy::inline_always)] |
16 | | #[inline(always)] |
17 | 0 | pub const fn get(self) -> u64 { |
18 | 0 | u64::from_le(self.0) |
19 | 0 | } |
20 | | } |
21 | | |
22 | | /// Splits a buffer into three subslices: |
23 | | /// - the first one is up to the first 8-byte aligned address. |
24 | | /// - the second one is 8-byte aligned and its length is a multiple of 8. |
25 | | /// - the third one is 8-byte aligned but its length is less than 8. |
26 | 0 | pub(crate) fn split(buffer: &[u8]) -> (&[u8], &[U64Le], &[u8]) { |
27 | 0 | let (start, mid) = { |
28 | 0 | let split_index = { |
29 | 0 | let addr = buffer.as_ptr() as usize; |
30 | 0 |
|
31 | 0 | // Align to multiples of 8. |
32 | 0 | let aligned_addr = (addr + 7) & (!7); |
33 | 0 |
|
34 | 0 | // Index of the next aligned element. |
35 | 0 | let next_i = aligned_addr - addr; |
36 | 0 |
|
37 | 0 | // Buffer might be too small. |
38 | 0 | cmp::min(next_i, buffer.len()) |
39 | 0 | }; |
40 | 0 |
|
41 | 0 | buffer.split_at(split_index) |
42 | 0 | }; |
43 | | |
44 | 0 | let (mid, end) = { |
45 | 0 | // Round length down to multiples of 8. |
46 | 0 | let split_index = mid.len() & (!7); |
47 | 0 |
|
48 | 0 | mid.split_at(split_index) |
49 | 0 | }; |
50 | | |
51 | 0 | let mid = unsafe { |
52 | 0 | let length = mid.len() / 8; |
53 | 0 | let ptr = if length == 0 { |
54 | 0 | // `slice::from_raw_parts` requires that pointers be nonnull and |
55 | 0 | // aligned even for zero-length slices. |
56 | 0 | NonNull::<U64Le>::dangling().as_ptr() |
57 | 0 | } else { |
58 | | #[allow(clippy::cast_ptr_alignment)] |
59 | 0 | mid.as_ptr().cast::<U64Le>() |
60 | | }; |
61 | | |
62 | 0 | slice::from_raw_parts(ptr, length) |
63 | | }; |
64 | | |
65 | 0 | (start, mid, end) |
66 | 0 | } |