#[macro_export]
macro_rules! const_assert {
    ($x:expr $(,)?) => {
        #[allow(unknown_lints, eq_op)]
        const _: [(); 0 - !{
            const ASSERT: bool = $x;
            ASSERT
        } as usize] = [];
    };
}

/// short for `include!(concat!(env!("OUT_DIR"), $path))`
#[macro_export]
macro_rules! include_out {
	($path:literal) => {
		include!(concat!(env!("OUT_DIR"), $path))
	};
}

macro_rules! impl_byteorder {
    ( $name:ident $( < $( $life:lifetime )? $( const $p:tt : $pt:ty )? > )? no_write) => {
		impl $( < $($life)? $(const $p : $pt)? > )? $crate::bytes::ByteOrder for $name $( < $($life)? $($p)? > )? {
			impl_byteorder!(@CREATE_READS);
			impl_byteorder!(@CREATE_NO_WRITES);
        }
    };

	( $name:ident $( < $( $life:lifetime )? $( const $p:tt : $pt:ty )? > )? ) => {
		impl $( < $($life)? $(const $p : $pt)? > )? $crate::bytes::ByteOrder for $name $( < $($life)? $($p)? > )? {
			impl_byteorder!(@CREATE_READS);
			impl_byteorder!(@CREATE_WRITES);
        }
    };

	(@CREATE_READS) => {
		fn read(&self, off: usize) -> u8 {
			assert!(self.len() > off);
			unsafe { *self.as_ptr().add(off) }
		}

		unsafe fn read_unchecked(&self, off: usize) -> u8 {
			*self.as_ptr().add(off)
		}

		fn read_le<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { T::read_le(self.as_ptr().add(off) as *const T) }
		}

		unsafe fn read_le_unchecked<T: MemValue>(&self, off: usize) -> T {
			T::read_le(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_le_aligned<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			T::read_le_aligned(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_le_aligned_unchecked<T: MemValue>(&self, off: usize) -> T {
			T::read_le_aligned(self.as_ptr().add(off) as *const T)
		}

		fn read_be<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { T::read_be(self.as_ptr().add(off) as *const T) }
		}

		unsafe fn read_be_unchecked<T: MemValue>(&self, off: usize) -> T {
			T::read_be(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_be_aligned<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			T::read_be_aligned(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_be_aligned_unchecked<T: MemValue>(&self, off: usize) -> T {
			T::read_be_aligned(self.as_ptr().add(off) as *const T)
		}

		fn read_ne<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { T::read_ne(self.as_ptr().add(off) as *const T) }
		}

		unsafe fn read_ne_unchecked<T: MemValue>(&self, off: usize) -> T {
			T::read_ne(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_ne_aligned<T: MemValue>(&self, off: usize) -> T {
			T::read_ne_aligned(self.as_ptr().add(off) as *const T)
		}

		unsafe fn read_ne_aligned_unchecked<T: MemValue>(&self, off: usize) -> T {
			assert!(self.len() >= off + mem::size_of::<T>());
			T::read_ne_aligned(self.as_ptr().add(off) as *const T)
		}
	};

	(@CREATE_WRITES) => {
		fn write(&mut self, off: usize, value: u8) {
			assert!(self.len() > off);
			unsafe {
				*self.as_mut_ptr().add(off) = value;
			}
		}

		unsafe fn write_unchecked(&mut self, off: usize, value: u8) {
			*self.as_mut_ptr().add(off) = value;
		}

		fn write_le<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_le(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_le_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_le(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_le_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_le_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_le_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_le_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		fn write_be<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_be(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_be_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_be(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_be_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_be_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_be_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_be_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		fn write_ne<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_ne(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_ne_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_ne(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_ne_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_ne_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_ne_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_ne_aligned(self.as_mut_ptr().add(off) as *mut T)
		}
	};

	(@CREATE_WRITES) => {
		fn write(&mut self, off: usize, value: u8) {
			assert!(self.len() > off);
			unsafe {
				*self.as_mut_ptr().add(off) = value;
			}
		}

		unsafe fn write_unchecked(&mut self, off: usize, value: u8) {
			*self.as_mut_ptr().add(off) = value;
		}

		fn write_le<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_le(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_le_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_le(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_le_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_le_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_le_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_le_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		fn write_be<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_be(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_be_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_be(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_be_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_be_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_be_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_be_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		fn write_ne<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			unsafe { value.write_ne(self.as_mut_ptr().add(off) as *mut T) }
		}

		unsafe fn write_ne_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_ne(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_ne_aligned<T: MemValue>(&mut self, off: usize, value: T) {
			assert!(self.len() >= off + mem::size_of::<T>());
			value.write_ne_aligned(self.as_mut_ptr().add(off) as *mut T)
		}

		unsafe fn write_ne_aligned_unchecked<T: MemValue>(&mut self, off: usize, value: T) {
			value.write_ne_aligned(self.as_mut_ptr().add(off) as *mut T)
		}
	};

	(@CREATE_NO_WRITES) => {
		fn write(&mut self, _: usize, _: u8) {
			unimplemented!();
		}

		unsafe fn write_unchecked(&mut self, _: usize, _: u8) {
			unimplemented!();
		}

		fn write_le<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_le_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_le_aligned<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_le_aligned_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		fn write_be<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_be_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_be_aligned<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_be_aligned_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		fn write_ne<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_ne_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_ne_aligned<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}

		unsafe fn write_ne_aligned_unchecked<T: MemValue>(&mut self, _: usize, _: T) {
			unimplemented!();
		}
	};
}

pub(crate) use impl_byteorder;
