bitvec/slice/
ops.rs

1#![doc = include_str!("../../doc/slice/ops.md")]
2
3use core::ops::{
4	BitAnd,
5	BitAndAssign,
6	BitOr,
7	BitOrAssign,
8	BitXor,
9	BitXorAssign,
10	Index,
11	IndexMut,
12	Not,
13	Range,
14	RangeFrom,
15	RangeFull,
16	RangeInclusive,
17	RangeTo,
18	RangeToInclusive,
19};
20
21use super::{
22	BitSlice,
23	BitSliceIndex,
24};
25use crate::{
26	domain::Domain,
27	order::{
28		BitOrder,
29		Lsb0,
30		Msb0,
31	},
32	store::BitStore,
33};
34
35impl<T1, T2, O1, O2> BitAndAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
36where
37	T1: BitStore,
38	T2: BitStore,
39	O1: BitOrder,
40	O2: BitOrder,
41{
42	#[inline]
43	#[doc = include_str!("../../doc/slice/bitop_assign.md")]
44	fn bitand_assign(&mut self, rhs: &BitSlice<T2, O2>) {
45		if let (Some(this), Some(that)) =
46			(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
47		{
48			return this.sp_bitop_assign(that, BitAnd::bitand, BitAnd::bitand);
49		}
50		if let (Some(this), Some(that)) =
51			(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
52		{
53			return this.sp_bitop_assign(that, BitAnd::bitand, BitAnd::bitand);
54		}
55		for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
56		{
57			unsafe {
58				this.write(this.read() & that.read());
59			}
60		}
61		if let Some(rem) = self.get_mut(rhs.len() ..) {
62			rem.fill(false);
63		}
64	}
65}
66
67impl<T1, T2, O1, O2> BitOrAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
68where
69	T1: BitStore,
70	T2: BitStore,
71	O1: BitOrder,
72	O2: BitOrder,
73{
74	#[inline]
75	#[doc = include_str!("../../doc/slice/bitop_assign.md")]
76	fn bitor_assign(&mut self, rhs: &BitSlice<T2, O2>) {
77		if let (Some(this), Some(that)) =
78			(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
79		{
80			return this.sp_bitop_assign(that, BitOr::bitor, BitOr::bitor);
81		}
82		if let (Some(this), Some(that)) =
83			(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
84		{
85			return this.sp_bitop_assign(that, BitOr::bitor, BitOr::bitor);
86		}
87		for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
88		{
89			unsafe {
90				this.write(this.read() | that.read());
91			}
92		}
93	}
94}
95
96impl<T1, T2, O1, O2> BitXorAssign<&BitSlice<T2, O2>> for BitSlice<T1, O1>
97where
98	T1: BitStore,
99	T2: BitStore,
100	O1: BitOrder,
101	O2: BitOrder,
102{
103	#[inline]
104	#[doc = include_str!("../../doc/slice/bitop_assign.md")]
105	fn bitxor_assign(&mut self, rhs: &BitSlice<T2, O2>) {
106		if let (Some(this), Some(that)) =
107			(self.coerce_mut::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
108		{
109			return this.sp_bitop_assign(that, BitXor::bitxor, BitXor::bitxor);
110		}
111		if let (Some(this), Some(that)) =
112			(self.coerce_mut::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
113		{
114			return this.sp_bitop_assign(that, BitXor::bitxor, BitXor::bitxor);
115		}
116		for (this, that) in self.as_mut_bitptr_range().zip(rhs.as_bitptr_range())
117		{
118			unsafe {
119				this.write(this.read() ^ that.read());
120			}
121		}
122	}
123}
124
125impl<T, O> Index<usize> for BitSlice<T, O>
126where
127	T: BitStore,
128	O: BitOrder,
129{
130	type Output = bool;
131
132	/// Looks up a single bit by its semantic index.
133	///
134	/// ## Examples
135	///
136	/// ```rust
137	/// use bitvec::prelude::*;
138	///
139	/// let bits = bits![u8, Msb0; 0, 1, 0];
140	/// assert!(!bits[0]); // -----^  |  |
141	/// assert!( bits[1]); // --------^  |
142	/// assert!(!bits[2]); // -----------^
143	/// ```
144	///
145	/// If the index is greater than or equal to the length, indexing will
146	/// panic.
147	///
148	/// The below test will panic when accessing index 1, as only index 0 is
149	/// valid.
150	///
151	/// ```rust,should_panic
152	/// use bitvec::prelude::*;
153	///
154	/// let bits = bits![0,  ];
155	/// bits[1]; // --------^
156	/// ```
157	#[inline]
158	fn index(&self, index: usize) -> &Self::Output {
159		match *index.index(self) {
160			true => &true,
161			false => &false,
162		}
163	}
164}
165
166/// Implements `Index` and `IndexMut` with the given type.
167macro_rules! index {
168	($($t:ty),+ $(,)?) => { $(
169		impl<T, O> Index<$t> for BitSlice<T, O>
170		where
171			O: BitOrder,
172			T: BitStore,
173		{
174			type Output = Self;
175
176			#[inline]
177			#[track_caller]
178			fn index(&self, index: $t) -> &Self::Output {
179				index.index(self)
180			}
181		}
182
183		impl<T, O> IndexMut<$t> for BitSlice<T, O>
184		where
185			O: BitOrder,
186			T: BitStore,
187		{
188			#[inline]
189			#[track_caller]
190			fn index_mut(&mut self, index: $t) -> &mut Self::Output {
191				index.index_mut(self)
192			}
193		}
194	)+ };
195}
196
197index! {
198	Range<usize>,
199	RangeFrom<usize>,
200	RangeFull,
201	RangeInclusive<usize>,
202	RangeTo<usize>,
203	RangeToInclusive<usize>,
204}
205
206/** Inverts each bit in the bit-slice.
207
208Unlike the `&`, `|`, and `^` operators, this implementation is guaranteed to
209update each memory element only once, and is not required to traverse every live
210bit in the underlying region.
211**/
212impl<'a, T, O> Not for &'a mut BitSlice<T, O>
213where
214	T: BitStore,
215	O: BitOrder,
216{
217	type Output = Self;
218
219	#[inline]
220	fn not(self) -> Self::Output {
221		match self.domain_mut() {
222			Domain::Enclave(mut elem) => {
223				elem.invert();
224			},
225			Domain::Region { head, body, tail } => {
226				if let Some(mut elem) = head {
227					elem.invert();
228				}
229				for elem in body {
230					elem.store_value(!elem.load_value());
231				}
232				if let Some(mut elem) = tail {
233					elem.invert();
234				}
235			},
236		}
237		self
238	}
239}