// Copyright 2016 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::error; #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] pub struct BitLength(usize); // Lengths measured in bits, where all arithmetic is guaranteed not to // overflow. impl BitLength { #[inline] pub const fn from_usize_bits(bits: usize) -> Self { Self(bits) } #[inline] pub fn from_usize_bytes(bytes: usize) -> Result { let bits = bytes.checked_mul(8).ok_or(error::Unspecified)?; Ok(Self::from_usize_bits(bits)) } #[cfg(feature = "alloc")] #[inline] pub fn half_rounded_up(&self) -> Self { let round_up = self.0 & 1; Self((self.0 / 2) + round_up) } #[inline] pub fn as_usize_bits(&self) -> usize { self.0 } #[cfg(feature = "alloc")] #[inline] pub fn as_usize_bytes_rounded_up(&self) -> usize { // Equivalent to (self.0 + 7) / 8, except with no potential for // overflow and without branches. // Branchless round_up = if self.0 & 0b111 != 0 { 1 } else { 0 }; let round_up = ((self.0 >> 2) | (self.0 >> 1) | self.0) & 1; (self.0 / 8) + round_up } #[cfg(feature = "alloc")] #[inline] pub fn try_sub_1(self) -> Result { let sum = self.0.checked_sub(1).ok_or(error::Unspecified)?; Ok(BitLength(sum)) } }