#![doc = include_str!("../../doc/slice/ops.md")]
use core::ops::{
BitAnd,
BitAndAssign,
BitOr,
BitOrAssign,
BitXor,
BitXorAssign,
Index,
IndexMut,
Not,
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
};
use super::{
BitSlice,
BitSliceIndex,
};
use crate::{
domain::Domain,
order::{
BitOrder,
Lsb0,
Msb0,
},
store::BitStore,
};
impl<T1, T2, O1, O2> BitAndAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
where
T1: BitStore,
T2: BitStore,
O1: BitOrder,
O2: BitOrder,
{
#[inline]
#[doc = include_str!("../../doc/slice/bitop_assign.md")]
fn bitand_assign(&mut self, rhs: &BitSlice<T2, O2>) {
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
{
return this.sp_bitop_assign(that, BitAnd::bitand, BitAnd::bitand);
}
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
{
return this.sp_bitop_assign(that, BitAnd::bitand, BitAnd::bitand);
}
for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
{
unsafe {
this.write(this.read() & that.read());
}
}
if let Some(rem) = self.get_mut(rhs.len() ..) {
rem.fill(false);
}
}
}
impl<T1, T2, O1, O2> BitOrAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
where
T1: BitStore,
T2: BitStore,
O1: BitOrder,
O2: BitOrder,
{
#[inline]
#[doc = include_str!("../../doc/slice/bitop_assign.md")]
fn bitor_assign(&mut self, rhs: &BitSlice<T2, O2>) {
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
{
return this.sp_bitop_assign(that, BitOr::bitor, BitOr::bitor);
}
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
{
return this.sp_bitop_assign(that, BitOr::bitor, BitOr::bitor);
}
for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
{
unsafe {
this.write(this.read() | that.read());
}
}
}
}
impl<T1, T2, O1, O2> BitXorAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
where
T1: BitStore,
T2: BitStore,
O1: BitOrder,
O2: BitOrder,
{
#[inline]
#[doc = include_str!("../../doc/slice/bitop_assign.md")]
fn bitxor_assign(&mut self, rhs: &BitSlice<T2, O2>) {
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
{
return this.sp_bitop_assign(that, BitXor::bitxor, BitXor::bitxor);
}
if let (Some(this), Some(that)) =
(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
{
return this.sp_bitop_assign(that, BitXor::bitxor, BitXor::bitxor);
}
for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
{
unsafe {
this.write(this.read() ^ that.read());
}
}
}
}
impl<T, O> Index<usize> for BitSlice<T, O>
where
T: BitStore,
O: BitOrder,
{
type Output = bool;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match *index.index(self) {
true => &true,
false => &false,
}
}
}
macro_rules! index {
($($t:ty),+ $(,)?) => { $(
impl<T, O> Index<$t> for BitSlice<T, O>
where
O: BitOrder,
T: BitStore,
{
type Output = Self;
#[inline]
#[track_caller]
fn index(&self, index: $t) -> &Self::Output {
index.index(self)
}
}
impl<T, O> IndexMut<$t> for BitSlice<T, O>
where
O: BitOrder,
T: BitStore,
{
#[inline]
#[track_caller]
fn index_mut(&mut self, index: $t) -> &mut Self::Output {
index.index_mut(self)
}
}
)+ };
}
index! {
Range<usize>,
RangeFrom<usize>,
RangeFull,
RangeInclusive<usize>,
RangeTo<usize>,
RangeToInclusive<usize>,
}
impl<'a, T, O> Not for &'a mut BitSlice<T, O>
where
T: BitStore,
O: BitOrder,
{
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
match self.domain_mut() {
Domain::Enclave(mut elem) => {
elem.invert();
},
Domain::Region { head, body, tail } => {
if let Some(mut elem) = head {
elem.invert();
}
for elem in body {
elem.store_value(!elem.load_value());
}
if let Some(mut elem) = tail {
elem.invert();
}
},
}
self
}
}