bitvec/array/
traits.rs

1//! Additional trait implementations on bit-arrays.
2
3use core::{
4	borrow::{
5		Borrow,
6		BorrowMut,
7	},
8	cmp,
9	convert::TryFrom,
10	fmt::{
11		self,
12		Debug,
13		Display,
14		Formatter,
15	},
16	hash::{
17		Hash,
18		Hasher,
19	},
20	marker::Unpin,
21};
22
23use tap::TryConv;
24
25use super::BitArray;
26use crate::{
27	index::BitIdx,
28	mem,
29	order::BitOrder,
30	slice::BitSlice,
31	store::BitStore,
32	view::BitViewSized,
33};
34
35#[cfg(not(tarpaulin_include))]
36impl<A, O> Borrow<BitSlice<A::Store, O>> for BitArray<A, O>
37where
38	A: BitViewSized,
39	O: BitOrder,
40{
41	#[inline]
42	fn borrow(&self) -> &BitSlice<A::Store, O> {
43		self.as_bitslice()
44	}
45}
46
47#[cfg(not(tarpaulin_include))]
48impl<A, O> BorrowMut<BitSlice<A::Store, O>> for BitArray<A, O>
49where
50	A: BitViewSized,
51	O: BitOrder,
52{
53	#[inline]
54	fn borrow_mut(&mut self) -> &mut BitSlice<A::Store, O> {
55		self.as_mut_bitslice()
56	}
57}
58
59impl<A, O> Clone for BitArray<A, O>
60where
61	A: BitViewSized,
62	O: BitOrder,
63{
64	#[inline]
65	fn clone(&self) -> Self {
66		let mut out = Self::ZERO;
67		for (dst, src) in
68			out.as_raw_mut_slice().iter_mut().zip(self.as_raw_slice())
69		{
70			dst.store_value(src.load_value());
71		}
72		out
73	}
74}
75
76impl<A, O> Eq for BitArray<A, O>
77where
78	A: BitViewSized,
79	O: BitOrder,
80{
81}
82
83#[cfg(not(tarpaulin_include))]
84impl<A, O> Ord for BitArray<A, O>
85where
86	A: BitViewSized,
87	O: BitOrder,
88{
89	#[inline]
90	fn cmp(&self, other: &Self) -> cmp::Ordering {
91		self.as_bitslice().cmp(other.as_bitslice())
92	}
93}
94
95#[cfg(not(tarpaulin_include))]
96impl<O1, A, O2, T> PartialEq<BitArray<A, O2>> for BitSlice<T, O1>
97where
98	O1: BitOrder,
99	O2: BitOrder,
100	A: BitViewSized,
101	T: BitStore,
102{
103	#[inline]
104	fn eq(&self, other: &BitArray<A, O2>) -> bool {
105		self == other.as_bitslice()
106	}
107}
108
109#[cfg(not(tarpaulin_include))]
110impl<A, O, Rhs> PartialEq<Rhs> for BitArray<A, O>
111where
112	A: BitViewSized,
113	O: BitOrder,
114	Rhs: ?Sized,
115	BitSlice<A::Store, O>: PartialEq<Rhs>,
116{
117	#[inline]
118	fn eq(&self, other: &Rhs) -> bool {
119		self.as_bitslice() == other
120	}
121}
122
123#[cfg(not(tarpaulin_include))]
124impl<A, T, O> PartialOrd<BitArray<A, O>> for BitSlice<T, O>
125where
126	A: BitViewSized,
127	T: BitStore,
128	O: BitOrder,
129{
130	#[inline]
131	fn partial_cmp(&self, other: &BitArray<A, O>) -> Option<cmp::Ordering> {
132		self.partial_cmp(other.as_bitslice())
133	}
134}
135
136#[cfg(not(tarpaulin_include))]
137impl<A, O, Rhs> PartialOrd<Rhs> for BitArray<A, O>
138where
139	A: BitViewSized,
140	O: BitOrder,
141	Rhs: ?Sized,
142	BitSlice<A::Store, O>: PartialOrd<Rhs>,
143{
144	#[inline]
145	fn partial_cmp(&self, other: &Rhs) -> Option<cmp::Ordering> {
146		self.as_bitslice().partial_cmp(other)
147	}
148}
149
150#[cfg(not(tarpaulin_include))]
151impl<A, O> AsRef<BitSlice<A::Store, O>> for BitArray<A, O>
152where
153	A: BitViewSized,
154	O: BitOrder,
155{
156	#[inline]
157	fn as_ref(&self) -> &BitSlice<A::Store, O> {
158		self.as_bitslice()
159	}
160}
161
162#[cfg(not(tarpaulin_include))]
163impl<A, O> AsMut<BitSlice<A::Store, O>> for BitArray<A, O>
164where
165	A: BitViewSized,
166	O: BitOrder,
167{
168	#[inline]
169	fn as_mut(&mut self) -> &mut BitSlice<A::Store, O> {
170		self.as_mut_bitslice()
171	}
172}
173
174#[cfg(not(tarpaulin_include))]
175impl<A, O> From<A> for BitArray<A, O>
176where
177	A: BitViewSized,
178	O: BitOrder,
179{
180	#[inline]
181	fn from(data: A) -> Self {
182		Self::new(data)
183	}
184}
185
186impl<A, O> TryFrom<&BitSlice<A::Store, O>> for BitArray<A, O>
187where
188	A: BitViewSized,
189	O: BitOrder,
190{
191	type Error = TryFromBitSliceError;
192
193	#[inline]
194	fn try_from(src: &BitSlice<A::Store, O>) -> Result<Self, Self::Error> {
195		src.try_conv::<&Self>().map(|this| this.clone())
196	}
197}
198
199impl<A, O> TryFrom<&BitSlice<A::Store, O>> for &BitArray<A, O>
200where
201	A: BitViewSized,
202	O: BitOrder,
203{
204	type Error = TryFromBitSliceError;
205
206	#[inline]
207	fn try_from(src: &BitSlice<A::Store, O>) -> Result<Self, Self::Error> {
208		TryFromBitSliceError::new::<A, O>(src).map(|()| unsafe {
209			&*src
210				.as_bitspan()
211				.address()
212				.to_const()
213				.cast::<BitArray<A, O>>()
214		})
215	}
216}
217
218impl<A, O> TryFrom<&mut BitSlice<A::Store, O>> for &mut BitArray<A, O>
219where
220	A: BitViewSized,
221	O: BitOrder,
222{
223	type Error = TryFromBitSliceError;
224
225	#[inline]
226	fn try_from(src: &mut BitSlice<A::Store, O>) -> Result<Self, Self::Error> {
227		TryFromBitSliceError::new::<A, O>(src).map(|()| unsafe {
228			&mut *src
229				.as_mut_bitspan()
230				.address()
231				.to_mut()
232				.cast::<BitArray<A, O>>()
233		})
234	}
235}
236
237impl<A, O> Default for BitArray<A, O>
238where
239	A: BitViewSized,
240	O: BitOrder,
241{
242	#[inline]
243	fn default() -> Self {
244		Self::ZERO
245	}
246}
247
248impl<A, O> Debug for BitArray<A, O>
249where
250	A: BitViewSized,
251	O: BitOrder,
252{
253	#[inline]
254	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
255		self.as_bitspan().render(fmt, "Array", None)?;
256		fmt.write_str(" ")?;
257		Display::fmt(self, fmt)
258	}
259}
260
261easy_fmt! {
262	impl Binary
263	impl Display
264	impl LowerHex
265	impl Octal
266	impl UpperHex
267	for BitArray
268}
269
270#[cfg(not(tarpaulin_include))]
271impl<A, O> Hash for BitArray<A, O>
272where
273	A: BitViewSized,
274	O: BitOrder,
275{
276	#[inline]
277	fn hash<H>(&self, hasher: &mut H)
278	where H: Hasher {
279		self.as_bitslice().hash(hasher);
280	}
281}
282
283impl<A, O> Copy for BitArray<A, O>
284where
285	O: BitOrder,
286	A: BitViewSized + Copy,
287{
288}
289
290impl<A, O> Unpin for BitArray<A, O>
291where
292	A: BitViewSized,
293	O: BitOrder,
294{
295}
296
297#[repr(transparent)]
298#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
299#[doc = include_str!("../../doc/array/TryFromBitSliceError.md")]
300pub struct TryFromBitSliceError(InnerError);
301
302impl TryFromBitSliceError {
303	/// Checks whether a bit-slice can be viewed as a bit-array.
304	#[inline]
305	fn new<A, O>(bits: &BitSlice<A::Store, O>) -> Result<(), Self>
306	where
307		O: BitOrder,
308		A: BitViewSized,
309	{
310		InnerError::new::<A, O>(bits).map_err(Self)
311	}
312}
313
314impl Debug for TryFromBitSliceError {
315	#[inline]
316	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
317		fmt.write_str("TryFromBitSliceError::")?;
318		match self.0 {
319			InnerError::UnequalLen { actual, expected } => {
320				write!(fmt, "UnequalLen({} != {})", actual, expected)
321			},
322			InnerError::Misaligned => fmt.write_str("Misaligned"),
323		}
324	}
325}
326
327#[cfg(not(tarpaulin_include))]
328impl Display for TryFromBitSliceError {
329	#[inline]
330	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
331		match self.0 {
332			InnerError::UnequalLen { actual, expected } => write!(
333				fmt,
334				"bit-slice with length {} cannot be viewed as bit-array with \
335				 length {}",
336				actual, expected,
337			),
338			InnerError::Misaligned => fmt.write_str(
339				"a bit-slice must begin at the front edge of a storage element \
340				 in order to be viewed as a bit-array",
341			),
342		}
343	}
344}
345
346#[cfg(feature = "std")]
347impl std::error::Error for TryFromBitSliceError {}
348
349/// Opaque error type for bit-slice to bit-array view conversions.
350#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
351enum InnerError {
352	/// A bit-slice did not match the length of the destination bit-array.
353	UnequalLen {
354		/// The length of the bit-slice that produced this error.
355		actual:   usize,
356		/// The length of the destination bit-array type.
357		expected: usize,
358	},
359	/// A bit-slice did not begin at `BitIdx::MIN`.
360	Misaligned,
361}
362
363impl InnerError {
364	/// Checks whether a bit-slice is suitable to view as a bit-array.
365	#[inline]
366	fn new<A, O>(bits: &BitSlice<A::Store, O>) -> Result<(), Self>
367	where
368		O: BitOrder,
369		A: BitViewSized,
370	{
371		let bitspan = bits.as_bitspan();
372		let actual = bitspan.len();
373		let expected = mem::bits_of::<A>();
374		if actual != expected {
375			return Err(Self::UnequalLen { actual, expected });
376		}
377		if bitspan.head() != BitIdx::<<A::Store as BitStore>::Mem>::MIN {
378			return Err(Self::Misaligned);
379		}
380		Ok(())
381	}
382}