1 //! Trait implementations on `BitArray`.
2 
3 use crate::{
4 	array::BitArray,
5 	index::BitIdx,
6 	order::BitOrder,
7 	slice::BitSlice,
8 	store::BitStore,
9 	view::BitView,
10 };
11 
12 use core::{
13 	borrow::{
14 		Borrow,
15 		BorrowMut,
16 	},
17 	cmp,
18 	convert::TryFrom,
19 	fmt::{
20 		self,
21 		Binary,
22 		Debug,
23 		Display,
24 		Formatter,
25 		LowerHex,
26 		Octal,
27 		UpperHex,
28 	},
29 	hash::{
30 		Hash,
31 		Hasher,
32 	},
33 };
34 
35 #[cfg(not(tarpaulin_include))]
36 impl<O, V> Borrow<BitSlice<O, V::Store>> for BitArray<O, V>
37 where
38 	O: BitOrder,
39 	V: BitView + Sized,
40 {
41 	#[inline(always)]
borrow(&self) -> &BitSlice<O, V::Store>42 	fn borrow(&self) -> &BitSlice<O, V::Store> {
43 		self.as_bitslice()
44 	}
45 }
46 
47 #[cfg(not(tarpaulin_include))]
48 impl<O, V> BorrowMut<BitSlice<O, V::Store>> for BitArray<O, V>
49 where
50 	O: BitOrder,
51 	V: BitView + Sized,
52 {
53 	#[inline(always)]
borrow_mut(&mut self) -> &mut BitSlice<O, V::Store>54 	fn borrow_mut(&mut self) -> &mut BitSlice<O, V::Store> {
55 		self.as_mut_bitslice()
56 	}
57 }
58 
59 impl<O, V> Eq for BitArray<O, V>
60 where
61 	O: BitOrder,
62 	V: BitView + Sized,
63 {
64 }
65 
66 #[cfg(not(tarpaulin_include))]
67 impl<O, V> Ord for BitArray<O, V>
68 where
69 	O: BitOrder,
70 	V: BitView + Sized,
71 {
72 	#[inline]
cmp(&self, other: &Self) -> cmp::Ordering73 	fn cmp(&self, other: &Self) -> cmp::Ordering {
74 		self.as_bitslice().cmp(other.as_bitslice())
75 	}
76 }
77 
78 #[cfg(not(tarpaulin_include))]
79 impl<O, V, T> PartialEq<BitArray<O, V>> for BitSlice<O, T>
80 where
81 	O: BitOrder,
82 	V: BitView + Sized,
83 	T: BitStore,
84 {
85 	#[inline]
eq(&self, other: &BitArray<O, V>) -> bool86 	fn eq(&self, other: &BitArray<O, V>) -> bool {
87 		self == other.as_bitslice()
88 	}
89 }
90 
91 #[cfg(not(tarpaulin_include))]
92 impl<O, V, Rhs> PartialEq<Rhs> for BitArray<O, V>
93 where
94 	O: BitOrder,
95 	V: BitView + Sized,
96 	Rhs: ?Sized,
97 	BitSlice<O, V::Store>: PartialEq<Rhs>,
98 {
99 	#[inline]
eq(&self, other: &Rhs) -> bool100 	fn eq(&self, other: &Rhs) -> bool {
101 		self.as_bitslice() == other
102 	}
103 }
104 
105 #[cfg(not(tarpaulin_include))]
106 impl<O, V, T> PartialOrd<BitArray<O, V>> for BitSlice<O, T>
107 where
108 	O: BitOrder,
109 	V: BitView + Sized,
110 	T: BitStore,
111 {
112 	#[inline]
partial_cmp(&self, other: &BitArray<O, V>) -> Option<cmp::Ordering>113 	fn partial_cmp(&self, other: &BitArray<O, V>) -> Option<cmp::Ordering> {
114 		self.partial_cmp(other.as_bitslice())
115 	}
116 }
117 
118 #[cfg(not(tarpaulin_include))]
119 impl<O, V, Rhs> PartialOrd<Rhs> for BitArray<O, V>
120 where
121 	O: BitOrder,
122 	V: BitView + Sized,
123 	Rhs: ?Sized,
124 	BitSlice<O, V::Store>: PartialOrd<Rhs>,
125 {
126 	#[inline]
partial_cmp(&self, other: &Rhs) -> Option<cmp::Ordering>127 	fn partial_cmp(&self, other: &Rhs) -> Option<cmp::Ordering> {
128 		self.as_bitslice().partial_cmp(other)
129 	}
130 }
131 
132 #[cfg(not(tarpaulin_include))]
133 impl<O, V> AsRef<BitSlice<O, V::Store>> for BitArray<O, V>
134 where
135 	O: BitOrder,
136 	V: BitView + Sized,
137 {
138 	#[inline(always)]
as_ref(&self) -> &BitSlice<O, V::Store>139 	fn as_ref(&self) -> &BitSlice<O, V::Store> {
140 		self.as_bitslice()
141 	}
142 }
143 
144 #[cfg(not(tarpaulin_include))]
145 impl<O, V> AsMut<BitSlice<O, V::Store>> for BitArray<O, V>
146 where
147 	O: BitOrder,
148 	V: BitView + Sized,
149 {
150 	#[inline(always)]
as_mut(&mut self) -> &mut BitSlice<O, V::Store>151 	fn as_mut(&mut self) -> &mut BitSlice<O, V::Store> {
152 		self.as_mut_bitslice()
153 	}
154 }
155 
156 #[cfg(not(tarpaulin_include))]
157 impl<O, V> From<V> for BitArray<O, V>
158 where
159 	O: BitOrder,
160 	V: BitView + Sized,
161 {
162 	#[inline(always)]
from(data: V) -> Self163 	fn from(data: V) -> Self {
164 		Self::new(data)
165 	}
166 }
167 
168 impl<O1, O2, T, V> TryFrom<&'_ BitSlice<O2, T>> for BitArray<O1, V>
169 where
170 	O1: BitOrder,
171 	O2: BitOrder,
172 	T: BitStore,
173 	V: BitView + Sized,
174 {
175 	type Error = TryFromBitSliceError;
176 
177 	#[inline]
try_from(src: &BitSlice<O2, T>) -> Result<Self, Self::Error>178 	fn try_from(src: &BitSlice<O2, T>) -> Result<Self, Self::Error> {
179 		if src.len() != V::const_bits() {
180 			return Self::Error::err();
181 		}
182 		let mut out = Self::zeroed();
183 		out.clone_from_bitslice(src);
184 		Ok(out)
185 	}
186 }
187 
188 impl<'a, O, V> TryFrom<&'a BitSlice<O, V::Store>> for &'a BitArray<O, V>
189 where
190 	O: BitOrder,
191 	V: BitView + Sized,
192 {
193 	type Error = TryFromBitSliceError;
194 
195 	#[inline]
try_from(src: &'a BitSlice<O, V::Store>) -> Result<Self, Self::Error>196 	fn try_from(src: &'a BitSlice<O, V::Store>) -> Result<Self, Self::Error> {
197 		let bitptr = src.bitptr();
198 		//  This pointer cast can only happen if the slice is exactly as long as
199 		//  the array, and is aligned to the front of the element.
200 		if src.len() != V::const_bits() || bitptr.head() != BitIdx::ZERO {
201 			return Self::Error::err();
202 		}
203 		Ok(unsafe { &*(bitptr.pointer().to_const() as *const BitArray<O, V>) })
204 	}
205 }
206 
207 impl<'a, O, V> TryFrom<&'a mut BitSlice<O, V::Store>> for &'a mut BitArray<O, V>
208 where
209 	O: BitOrder,
210 	V: BitView + Sized,
211 {
212 	type Error = TryFromBitSliceError;
213 
214 	#[inline]
try_from( src: &'a mut BitSlice<O, V::Store>, ) -> Result<Self, Self::Error>215 	fn try_from(
216 		src: &'a mut BitSlice<O, V::Store>,
217 	) -> Result<Self, Self::Error> {
218 		let bitptr = src.bitptr();
219 		if src.len() != V::const_bits() || bitptr.head() != BitIdx::ZERO {
220 			return Self::Error::err();
221 		}
222 		Ok(unsafe { &mut *(bitptr.pointer().to_mut() as *mut BitArray<O, V>) })
223 	}
224 }
225 
226 #[cfg(not(tarpaulin_include))]
227 impl<O, V> Default for BitArray<O, V>
228 where
229 	O: BitOrder,
230 	V: BitView + Sized,
231 {
232 	#[inline(always)]
default() -> Self233 	fn default() -> Self {
234 		Self::zeroed()
235 	}
236 }
237 
238 #[cfg(not(tarpaulin_include))]
239 impl<O, V> Binary for BitArray<O, V>
240 where
241 	O: BitOrder,
242 	V: BitView + Sized,
243 {
244 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result245 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
246 		Binary::fmt(self.as_bitslice(), fmt)
247 	}
248 }
249 
250 impl<O, V> Debug for BitArray<O, V>
251 where
252 	O: BitOrder,
253 	V: BitView + Sized,
254 {
255 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result256 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
257 		if fmt.alternate() {
258 			self.bitptr().render(
259 				fmt,
260 				"Array",
261 				Some(core::any::type_name::<O>()),
262 				None,
263 			)?;
264 			fmt.write_str(" ")?;
265 		}
266 		Binary::fmt(self, fmt)
267 	}
268 }
269 
270 #[cfg(not(tarpaulin_include))]
271 impl<O, V> Display for BitArray<O, V>
272 where
273 	O: BitOrder,
274 	V: BitView + Sized,
275 {
276 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result277 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
278 		Binary::fmt(self.as_bitslice(), fmt)
279 	}
280 }
281 
282 #[cfg(not(tarpaulin_include))]
283 impl<O, V> LowerHex for BitArray<O, V>
284 where
285 	O: BitOrder,
286 	V: BitView + Sized,
287 {
288 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result289 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
290 		LowerHex::fmt(self.as_bitslice(), fmt)
291 	}
292 }
293 
294 #[cfg(not(tarpaulin_include))]
295 impl<O, V> Octal for BitArray<O, V>
296 where
297 	O: BitOrder,
298 	V: BitView + Sized,
299 {
300 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result301 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
302 		Octal::fmt(self.as_bitslice(), fmt)
303 	}
304 }
305 
306 #[cfg(not(tarpaulin_include))]
307 impl<O, V> UpperHex for BitArray<O, V>
308 where
309 	O: BitOrder,
310 	V: BitView + Sized,
311 {
312 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result313 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
314 		UpperHex::fmt(self.as_bitslice(), fmt)
315 	}
316 }
317 
318 #[cfg(not(tarpaulin_include))]
319 impl<O, V> Hash for BitArray<O, V>
320 where
321 	O: BitOrder,
322 	V: BitView + Sized,
323 {
324 	#[inline]
hash<H>(&self, hasher: &mut H) where H: Hasher325 	fn hash<H>(&self, hasher: &mut H)
326 	where H: Hasher {
327 		self.as_bitslice().hash(hasher)
328 	}
329 }
330 
331 #[cfg(not(tarpaulin_include))]
332 impl<'a, O, V> IntoIterator for &'a BitArray<O, V>
333 where
334 	O: 'a + BitOrder,
335 	V: 'a + BitView + Sized,
336 {
337 	type IntoIter = <&'a BitSlice<O, V::Store> as IntoIterator>::IntoIter;
338 	type Item = <&'a BitSlice<O, V::Store> as IntoIterator>::Item;
339 
340 	#[inline]
into_iter(self) -> Self::IntoIter341 	fn into_iter(self) -> Self::IntoIter {
342 		self.as_bitslice().into_iter()
343 	}
344 }
345 
346 #[cfg(not(tarpaulin_include))]
347 impl<'a, O, V> IntoIterator for &'a mut BitArray<O, V>
348 where
349 	O: 'a + BitOrder,
350 	V: 'a + BitView + Sized,
351 {
352 	type IntoIter = <&'a mut BitSlice<O, V::Store> as IntoIterator>::IntoIter;
353 	type Item = <&'a mut BitSlice<O, V::Store> as IntoIterator>::Item;
354 
355 	#[inline]
into_iter(self) -> Self::IntoIter356 	fn into_iter(self) -> Self::IntoIter {
357 		self.as_mut_bitslice().into_iter()
358 	}
359 }
360 
361 impl<O, V> Unpin for BitArray<O, V>
362 where
363 	O: BitOrder,
364 	V: BitView + Sized,
365 {
366 }
367 
368 /// The error type returned when a conversion from a bitslice to a bitarray
369 /// fails.
370 #[derive(Clone, Copy, Debug)]
371 pub struct TryFromBitSliceError;
372 
373 #[cfg(not(tarpaulin_include))]
374 impl TryFromBitSliceError {
375 	#[inline(always)]
err<T>() -> Result<T, Self>376 	fn err<T>() -> Result<T, Self> {
377 		Err(Self)
378 	}
379 }
380 
381 #[cfg(not(tarpaulin_include))]
382 impl Display for TryFromBitSliceError {
383 	#[inline]
fmt(&self, fmt: &mut Formatter) -> fmt::Result384 	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
385 		fmt.write_str("could not convert bitslice to bitarray")
386 	}
387 }
388 
389 #[cfg(feature = "std")]
390 impl std::error::Error for TryFromBitSliceError {
391 }
392 
393 #[cfg(test)]
394 mod tests {
395 	use crate::prelude::*;
396 	use core::convert::TryInto;
397 
398 	#[test]
convert()399 	fn convert() {
400 		let arr: BitArray<Lsb0, _> = 2u8.into();
401 		assert!(arr.any());
402 
403 		let bits = bits![1; 128];
404 		let arr: BitArray<Msb0, [u16; 8]> = bits.try_into().unwrap();
405 		assert!(arr.all());
406 
407 		let bits = bits![Lsb0, u32; 0; 64];
408 		let arr: &BitArray<Lsb0, [u32; 2]> = bits.try_into().unwrap();
409 		assert!(arr.not_any());
410 
411 		let bits = bits![mut Msb0, u16; 0; 64];
412 		let arr: &mut BitArray<Msb0, [u16; 4]> = bits.try_into().unwrap();
413 		assert!(arr.not_any());
414 
415 		let bits = bits![mut 0; 4];
416 		let bit_arr: Result<&BitArray<LocalBits, usize>, _> =
417 			(&*bits).try_into();
418 		assert!(bit_arr.is_err());
419 		let bit_arr: Result<&mut BitArray<LocalBits, usize>, _> =
420 			bits.try_into();
421 		assert!(bit_arr.is_err());
422 	}
423 
424 	#[test]
425 	#[cfg(feature = "std")]
format()426 	fn format() {
427 		let render = format!("{:#?}", bitarr![Msb0, u8; 0, 1, 0, 0]);
428 		assert!(
429 			render.starts_with("BitArray<bitvec::order::Msb0, u8> {"),
430 			"{}",
431 			render
432 		);
433 		assert!(
434 			render.ends_with(
435 				"    head: 000,\n    bits: 8,\n} [\n    0b01000000,\n]"
436 			),
437 			"{}",
438 			render
439 		);
440 	}
441 }
442