/rust/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.8/src/bits.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2016 Brian Smith. |
2 | | // |
3 | | // Permission to use, copy, modify, and/or distribute this software for any |
4 | | // purpose with or without fee is hereby granted, provided that the above |
5 | | // copyright notice and this permission notice appear in all copies. |
6 | | // |
7 | | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
8 | | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
10 | | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | | |
15 | | //! Bit lengths. |
16 | | |
17 | | use crate::{error, polyfill}; |
18 | | |
19 | | /// The length of something, in bits. |
20 | | /// |
21 | | /// This can represent a bit length that isn't a whole number of bytes. |
22 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] |
23 | | #[repr(transparent)] |
24 | | pub struct BitLength<T = usize>(T); |
25 | | |
26 | | pub(crate) trait FromUsizeBytes: Sized { |
27 | | /// Constructs a `BitLength` from the given length in bytes. |
28 | | /// |
29 | | /// Fails if `bytes * 8` is too large for a `T`. |
30 | | fn from_usize_bytes(bytes: usize) -> Result<Self, error::Unspecified>; |
31 | | } |
32 | | |
33 | | impl FromUsizeBytes for BitLength<usize> { |
34 | | #[inline] |
35 | 0 | fn from_usize_bytes(bytes: usize) -> Result<Self, error::Unspecified> { |
36 | 0 | let bits = bytes.checked_shl(3).ok_or(error::Unspecified)?; |
37 | 0 | Ok(Self(bits)) |
38 | 0 | } |
39 | | } |
40 | | |
41 | | impl FromUsizeBytes for BitLength<u64> { |
42 | | #[inline] |
43 | 0 | fn from_usize_bytes(bytes: usize) -> Result<Self, error::Unspecified> { |
44 | 0 | let bytes = polyfill::u64_from_usize(bytes); |
45 | 0 | let bits = bytes.checked_shl(3).ok_or(error::Unspecified)?; |
46 | 0 | Ok(Self(bits)) |
47 | 0 | } |
48 | | } |
49 | | |
50 | | impl<T: Copy> BitLength<T> { |
51 | | /// The number of bits this bit length represents, as a `usize`. |
52 | | #[inline] |
53 | 0 | pub fn as_bits(self) -> T { |
54 | 0 | self.0 |
55 | 0 | } Unexecuted instantiation: <ring::bits::BitLength<u64>>::as_bits Unexecuted instantiation: <ring::bits::BitLength>::as_bits |
56 | | } |
57 | | |
58 | | // Lengths measured in bits, where all arithmetic is guaranteed not to |
59 | | // overflow. |
60 | | impl BitLength<usize> { |
61 | | /// Constructs a `BitLength` from the given length in bits. |
62 | | #[inline] |
63 | 0 | pub const fn from_usize_bits(bits: usize) -> Self { |
64 | 0 | Self(bits) |
65 | 0 | } |
66 | | |
67 | | #[cfg(feature = "alloc")] |
68 | | #[inline] |
69 | 0 | pub(crate) fn half_rounded_up(&self) -> Self { |
70 | 0 | let round_up = self.0 & 1; |
71 | 0 | Self((self.0 / 2) + round_up) |
72 | 0 | } |
73 | | |
74 | | /// The bit length, rounded up to a whole number of bytes. |
75 | | #[cfg(any(target_arch = "aarch64", feature = "alloc"))] |
76 | | #[inline] |
77 | 0 | pub fn as_usize_bytes_rounded_up(&self) -> usize { |
78 | 0 | // Equivalent to (self.0 + 7) / 8, except with no potential for |
79 | 0 | // overflow and without branches. |
80 | 0 |
|
81 | 0 | // Branchless round_up = if self.0 & 0b111 != 0 { 1 } else { 0 }; |
82 | 0 | let round_up = ((self.0 >> 2) | (self.0 >> 1) | self.0) & 1; |
83 | 0 |
|
84 | 0 | (self.0 / 8) + round_up |
85 | 0 | } |
86 | | |
87 | | #[cfg(feature = "alloc")] |
88 | | #[inline] |
89 | 0 | pub(crate) fn try_sub_1(self) -> Result<Self, error::Unspecified> { |
90 | 0 | let sum = self.0.checked_sub(1).ok_or(error::Unspecified)?; |
91 | 0 | Ok(Self(sum)) |
92 | 0 | } |
93 | | } |