use crate::{
access::BitAccess,
order::BitOrder,
slice::BitSlice,
store::BitStore,
};
use core::{
cmp::Ordering,
fmt::{
self,
Binary,
Debug,
Display,
Formatter,
LowerHex,
Octal,
UpperHex,
},
hash::{
Hash,
Hasher,
},
hint::unreachable_unchecked,
str,
};
use either::Either;
#[cfg(feature = "alloc")]
use {
crate::vec::BitVec,
alloc::borrow::ToOwned,
};
#[cfg(feature = "alloc")]
impl<O, T> ToOwned for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Owned = BitVec<O, T>;
fn to_owned(&self) -> Self::Owned {
BitVec::from_bitslice(self)
}
}
impl<O, T> Eq for BitSlice<O, T>
where O: BitOrder, T: BitStore {}
impl<O, T> Ord for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn cmp(&self, rhs: &Self) -> Ordering {
self.partial_cmp(rhs)
.unwrap_or_else(|| unsafe { unreachable_unchecked() })
}
}
impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn eq(&self, rhs: &BitSlice<C, D>) -> bool {
if self.len() != rhs.len() {
return false;
}
self.iter().zip(rhs.iter()).all(|(l, r)| l == r)
}
}
impl<A, B, C, D> PartialEq<BitSlice<C, D>> for &BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn eq(&self, rhs: &BitSlice<C, D>) -> bool {
(*self).eq(rhs)
}
}
impl<A, B, C, D> PartialEq<&BitSlice<C, D>> for BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn eq(&self, rhs: &&BitSlice<C, D>) -> bool {
self.eq(*rhs)
}
}
impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> {
for (l, r) in self.iter().zip(rhs.iter()) {
match (l, r) {
(true, false) => return Some(Ordering::Greater),
(false, true) => return Some(Ordering::Less),
_ => continue,
}
}
self.len().partial_cmp(&rhs.len())
}
}
impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for &BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> {
(*self).partial_cmp(rhs)
}
}
impl<A, B, C, D> PartialOrd<&BitSlice<C, D>> for BitSlice<A, B>
where A: BitOrder, B: BitStore, C: BitOrder, D: BitStore {
fn partial_cmp(&self, rhs: &&BitSlice<C, D>) -> Option<Ordering> {
self.partial_cmp(*rhs)
}
}
impl<O, T> AsMut<[T]> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<O, T> AsRef<[T]> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<'a, O, T> From<&'a T> for &'a BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn from(src: &'a T) -> Self {
BitSlice::<O, T>::from_element(src)
}
}
impl<'a, O, T> From<&'a [T]> for &'a BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn from(src: &'a [T]) -> Self {
BitSlice::<O, T>::from_slice(src)
}
}
impl<'a, O, T> From<&'a mut T> for &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn from(src: &'a mut T) -> Self {
BitSlice::<O, T>::from_element_mut(src)
}
}
impl<'a, O, T> From<&'a mut [T]> for &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn from(src: &'a mut [T]) -> Self {
BitSlice::<O, T>::from_slice_mut(src)
}
}
impl<'a, O, T> Default for &'a BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn default() -> Self {
BitSlice::empty()
}
}
impl<'a, O, T> Default for &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
fn default() -> Self {
BitSlice::empty_mut()
}
}
macro_rules! fmt {
( $trait:ident, $base:expr, $pfx:expr, $blksz:expr ) => {
impl<O, T> $trait for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
let start = if fmt.alternate() { 0 } else { 2 };
let mut dbg = fmt.debug_list();
let mut w: [u8; (64 / $blksz) + 2] = [b'0'; (64 / $blksz) + 2];
w[1] = $pfx;
let mut writer = |bits: &Self| {
let mut end = 2;
for (idx, chunk) in bits.chunks($blksz).enumerate() {
let mut val = 0u8;
for bit in chunk {
val <<= 1;
val |= *bit as u8;
}
w[2 + idx] = match val {
v @ 0 ..= 9 => b'0' + v,
v @ 10 ..= 16 => $base + (v - 10),
_ => unsafe { unreachable_unchecked() },
};
end += 1;
}
dbg.entry(&RenderPart(unsafe {
str::from_utf8_unchecked(&w[start .. end])
}));
};
match self.bitptr().domain().splat() {
Either::Right(_) => {
writer(self);
},
Either::Left((h, b, t)) => {
if let Some((h, head)) = h {
writer(&Self::from_element(&head.load())[*h as usize ..]);
}
if let Some(body) = b {
for elt in body.iter().map(BitAccess::load) {
writer(Self::from_element(&elt));
}
}
if let Some((tail, t)) = t {
writer(&Self::from_element(&tail.load())[.. *t as usize]);
}
},
}
dbg.finish()
}
}
};
}
impl<O, T> Debug for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.write_str("BitSlice<")?;
fmt.write_str(O::TYPENAME)?;
fmt.write_str(", ")?;
fmt.write_str(T::TYPENAME)?;
fmt.write_str("> ")?;
Binary::fmt(self, fmt)
}
}
impl<O, T> Display for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
Binary::fmt(self, fmt)
}
}
fmt![Binary, b'0', b'b', 1];
fmt![Octal, b'0', b'o', 3];
fmt![LowerHex, b'a', b'x', 4];
fmt![UpperHex, b'A', b'x', 4];
struct RenderPart<'a>(&'a str);
impl Debug for RenderPart<'_> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.write_str(&self.0)
}
}
impl<O, T> Hash for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn hash<H>(&self, hasher: &mut H)
where H: Hasher {
for bit in self {
hasher.write_u8(*bit as u8);
}
}
}
#[cfg(feature = "atomic")]
unsafe impl<O, T> Send for BitSlice<O, T>
where O: BitOrder, T: BitStore {}
#[cfg(feature = "atomic")]
unsafe impl<O, T> Sync for BitSlice<O, T>
where O: BitOrder, T: BitStore {}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use crate::{
order::Msb0,
slice::AsBits,
};
#[cfg(not(feature = "std"))]
use alloc::format;
#[test]
fn binary() {
let data = [0u8, 0x0F, !0];
let bits = data.bits::<Msb0>();
assert_eq!(format!("{:b}", &bits[.. 0]), "[]");
assert_eq!(format!("{:#b}", &bits[.. 0]), "[]");
assert_eq!(format!("{:b}", &bits[9 .. 15]), "[000111]");
assert_eq!(format!("{:#b}", &bits[9 .. 15]),
"[
0b000111,
]");
assert_eq!(format!("{:b}", &bits[4 .. 20]), "[0000, 00001111, 1111]");
assert_eq!(format!("{:#b}", &bits[4 .. 20]),
"[
0b0000,
0b00001111,
0b1111,
]");
assert_eq!(format!("{:b}", &bits[4 ..]), "[0000, 00001111, 11111111]");
assert_eq!(format!("{:#b}", &bits[4 ..]),
"[
0b0000,
0b00001111,
0b11111111,
]");
assert_eq!(format!("{:b}", &bits[.. 20]), "[00000000, 00001111, 1111]");
assert_eq!(format!("{:#b}", &bits[.. 20]),
"[
0b00000000,
0b00001111,
0b1111,
]");
assert_eq!(format!("{:b}", bits), "[00000000, 00001111, 11111111]");
assert_eq!(format!("{:#b}", bits),
"[
0b00000000,
0b00001111,
0b11111111,
]");
}
#[test]
fn octal() {
let data = [0u8, 0x0F, !0];
let bits = data.bits::<Msb0>();
assert_eq!(format!("{:o}", &bits[.. 0]), "[]");
assert_eq!(format!("{:#o}", &bits[.. 0]), "[]");
assert_eq!(format!("{:o}", &bits[9 .. 15]), "[07]");
assert_eq!(format!("{:#o}", &bits[9 .. 15]),
"[
0o07,
]");
assert_eq!(format!("{:o}", &bits[4 .. 20]), "[00, 033, 71]");
assert_eq!(format!("{:#o}", &bits[4 .. 20]),
"[
0o00,
0o033,
0o71,
]");
assert_eq!(format!("{:o}", &bits[4 ..]), "[00, 033, 773]");
assert_eq!(format!("{:#o}", &bits[4 ..]),
"[
0o00,
0o033,
0o773,
]");
assert_eq!(format!("{:o}", &bits[.. 20]), "[000, 033, 71]");
assert_eq!(format!("{:#o}", &bits[.. 20]),
"[
0o000,
0o033,
0o71,
]");
assert_eq!(format!("{:o}", bits), "[000, 033, 773]");
assert_eq!(format!("{:#o}", bits),
"[
0o000,
0o033,
0o773,
]");
}
#[test]
fn hex_lower() {
let data = [0u8, 0x0F, !0];
let bits = data.bits::<Msb0>();
assert_eq!(format!("{:x}", &bits[.. 0]), "[]");
assert_eq!(format!("{:#x}", &bits[.. 0]), "[]");
assert_eq!(format!("{:x}", &bits[9 .. 15]), "[13]");
assert_eq!(format!("{:#x}", &bits[9 .. 15]),
"[
0x13,
]");
assert_eq!(format!("{:x}", &bits[4 .. 20]), "[0, 0f, f]");
assert_eq!(format!("{:#x}", &bits[4 .. 20]),
"[
0x0,
0x0f,
0xf,
]");
assert_eq!(format!("{:x}", &bits[4 ..]), "[0, 0f, ff]");
assert_eq!(format!("{:#x}", &bits[4 ..]),
"[
0x0,
0x0f,
0xff,
]");
assert_eq!(format!("{:x}", &bits[.. 20]), "[00, 0f, f]");
assert_eq!(format!("{:#x}", &bits[.. 20]),
"[
0x00,
0x0f,
0xf,
]");
assert_eq!(format!("{:x}", bits), "[00, 0f, ff]");
assert_eq!(format!("{:#x}", bits),
"[
0x00,
0x0f,
0xff,
]");
}
#[test]
fn hex_upper() {
let data = [0u8, 0x0F, !0];
let bits = data.bits::<Msb0>();
assert_eq!(format!("{:X}", &bits[.. 0]), "[]");
assert_eq!(format!("{:#X}", &bits[.. 0]), "[]");
assert_eq!(format!("{:X}", &bits[9 .. 15]), "[13]");
assert_eq!(format!("{:#X}", &bits[9 .. 15]),
"[
0x13,
]");
assert_eq!(format!("{:X}", &bits[4 .. 20]), "[0, 0F, F]");
assert_eq!(format!("{:#X}", &bits[4 .. 20]),
"[
0x0,
0x0F,
0xF,
]");
assert_eq!(format!("{:X}", &bits[4 ..]), "[0, 0F, FF]");
assert_eq!(format!("{:#X}", &bits[4 ..]),
"[
0x0,
0x0F,
0xFF,
]");
assert_eq!(format!("{:X}", &bits[.. 20]), "[00, 0F, F]");
assert_eq!(format!("{:#X}", &bits[.. 20]),
"[
0x00,
0x0F,
0xF,
]");
assert_eq!(format!("{:X}", bits), "[00, 0F, FF]");
assert_eq!(format!("{:#X}", bits),
"[
0x00,
0x0F,
0xFF,
]");
}
}