#![doc = include_str!("../doc/view.md")]
use core::slice;
use crate::{
	array::BitArray,
	order::BitOrder,
	ptr::BitSpanError,
	slice::BitSlice,
	store::BitStore,
};
#[doc = include_str!("../doc/view/BitView.md")]
pub trait BitView {
	type Store: BitStore;
	fn view_bits<O>(&self) -> &BitSlice<Self::Store, O>
	where O: BitOrder;
	fn try_view_bits<O>(
		&self,
	) -> Result<&BitSlice<Self::Store, O>, BitSpanError<Self::Store>>
	where O: BitOrder;
	fn view_bits_mut<O>(&mut self) -> &mut BitSlice<Self::Store, O>
	where O: BitOrder;
	fn try_view_bits_mut<O>(
		&mut self,
	) -> Result<&mut BitSlice<Self::Store, O>, BitSpanError<Self::Store>>
	where O: BitOrder;
}
#[cfg(not(tarpaulin_include))]
impl<T> BitView for T
where T: BitStore
{
	type Store = Self;
	fn view_bits<O>(&self) -> &BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_element(self)
	}
	fn try_view_bits<O>(&self) -> Result<&BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		Ok(BitSlice::from_element(self))
	}
	fn view_bits_mut<O>(&mut self) -> &mut BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_element_mut(self)
	}
	fn try_view_bits_mut<O>(
		&mut self,
	) -> Result<&mut BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		Ok(BitSlice::from_element_mut(self))
	}
}
#[cfg(not(tarpaulin_include))]
impl<T> BitView for [T]
where T: BitStore
{
	type Store = T;
	#[inline]
	fn view_bits<O>(&self) -> &BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_slice(self)
	}
	#[inline]
	fn try_view_bits<O>(&self) -> Result<&BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		BitSlice::try_from_slice(self)
	}
	#[inline]
	fn view_bits_mut<O>(&mut self) -> &mut BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_slice_mut(self)
	}
	#[inline]
	fn try_view_bits_mut<O>(
		&mut self,
	) -> Result<&mut BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		BitSlice::try_from_slice_mut(self)
	}
}
#[cfg(not(tarpaulin_include))]
impl<T, const N: usize> BitView for [T; N]
where T: BitStore
{
	type Store = T;
	#[inline]
	fn view_bits<O>(&self) -> &BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_slice(self)
	}
	#[inline]
	fn try_view_bits<O>(&self) -> Result<&BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		BitSlice::try_from_slice(self)
	}
	#[inline]
	fn view_bits_mut<O>(&mut self) -> &mut BitSlice<T, O>
	where O: BitOrder {
		BitSlice::from_slice_mut(self)
	}
	#[inline]
	fn try_view_bits_mut<O>(
		&mut self,
	) -> Result<&mut BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		BitSlice::try_from_slice_mut(self)
	}
}
pub trait BitViewSized: BitView + Sized {
	const ZERO: Self;
	#[inline]
	fn into_bitarray<O>(self) -> BitArray<Self, O>
	where O: BitOrder {
		BitArray::new(self)
	}
	fn as_raw_slice(&self) -> &[Self::Store];
	fn as_raw_mut_slice(&mut self) -> &mut [Self::Store];
}
impl<T> BitViewSized for T
where T: BitStore
{
	const ZERO: Self = <T as BitStore>::ZERO;
	#[inline]
	fn as_raw_slice(&self) -> &[Self::Store] {
		slice::from_ref(self)
	}
	#[inline]
	fn as_raw_mut_slice(&mut self) -> &mut [Self::Store] {
		slice::from_mut(self)
	}
}
impl<T, const N: usize> BitViewSized for [T; N]
where T: BitStore
{
	const ZERO: Self = [T::ZERO; N];
	#[inline]
	fn as_raw_slice(&self) -> &[Self::Store] {
		&self[..]
	}
	#[inline]
	fn as_raw_mut_slice(&mut self) -> &mut [Self::Store] {
		&mut self[..]
	}
}
#[doc = include_str!("../doc/view/AsBits.md")]
pub trait AsBits<T>
where T: BitStore
{
	fn as_bits<O>(&self) -> &BitSlice<T, O>
	where O: BitOrder;
	fn try_as_bits<O>(&self) -> Result<&BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder;
}
#[doc = include_str!("../doc/view/AsMutBits.md")]
pub trait AsMutBits<T>
where T: BitStore
{
	fn as_mut_bits<O>(&mut self) -> &mut BitSlice<T, O>
	where O: BitOrder;
	fn try_as_mut_bits<O>(
		&mut self,
	) -> Result<&mut BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder;
}
#[cfg(not(tarpaulin_include))]
impl<A, T> AsBits<T> for A
where
	A: AsRef<[T]>,
	T: BitStore,
{
	#[inline]
	fn as_bits<O>(&self) -> &BitSlice<T, O>
	where O: BitOrder {
		self.as_ref().view_bits::<O>()
	}
	#[inline]
	fn try_as_bits<O>(&self) -> Result<&BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		self.as_ref().try_view_bits::<O>()
	}
}
#[cfg(not(tarpaulin_include))]
impl<A, T> AsMutBits<T> for A
where
	A: AsMut<[T]>,
	T: BitStore,
{
	#[inline]
	fn as_mut_bits<O>(&mut self) -> &mut BitSlice<T, O>
	where O: BitOrder {
		self.as_mut().view_bits_mut::<O>()
	}
	#[inline]
	fn try_as_mut_bits<O>(
		&mut self,
	) -> Result<&mut BitSlice<T, O>, BitSpanError<T>>
	where O: BitOrder {
		self.as_mut().try_view_bits_mut::<O>()
	}
}
#[cfg(test)]
mod tests {
	use static_assertions::*;
	use super::*;
	use crate::prelude::*;
	#[test]
	fn implementations() {
		let mut byte = 0u8;
		let mut bytes = [0u8; 2];
		assert!(byte.view_bits::<LocalBits>().not_any());
		assert!(byte.view_bits_mut::<LocalBits>().not_any());
		assert!(bytes.view_bits::<LocalBits>().not_any());
		assert!(bytes.view_bits_mut::<LocalBits>().not_any());
		assert!(bytes[..].view_bits::<LocalBits>().not_any());
		assert!(bytes[..].view_bits_mut::<LocalBits>().not_any());
		let mut blank: [u8; 0] = [];
		assert!(blank.view_bits::<LocalBits>().is_empty());
		assert!(blank.view_bits_mut::<LocalBits>().is_empty());
		assert_eq!([0u32; 2].as_bits::<LocalBits>().len(), 64);
		assert_eq!([0u32; 2].as_mut_bits::<LocalBits>().len(), 64);
		assert_eq!(0usize.as_raw_slice().len(), 1);
		assert_eq!(0usize.as_raw_mut_slice().len(), 1);
		assert_eq!(0u32.into_bitarray::<LocalBits>().len(), 32);
		assert_impl_all!(
			[usize; 10]: AsBits<usize>,
			AsMutBits<usize>,
			BitViewSized,
			BitView,
		);
	}
}