#![cfg_attr(do_doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(rustdoc::redundant_explicit_links)]
#[cfg(feature = "futures")]
#[cfg_attr(do_doc_cfg, doc(cfg(feature = "futures")))]
pub mod futures;
#[cfg(feature = "std")]
#[cfg_attr(do_doc_cfg, doc(cfg(feature = "std")))]
pub mod io;
#[cfg(feature = "tokio")]
#[cfg_attr(do_doc_cfg, doc(cfg(feature = "tokio")))]
pub mod tokio;
pub trait BitEndian<const N: usize> {
fn to_le_bytes(self) -> [u8; N];
fn to_be_bytes(self) -> [u8; N];
fn to_ne_bytes(self) -> [u8; N];
fn to_bytes_endian(self, endian: Endian) -> [u8; N]
where
Self: Sized,
{
match endian {
Endian::Little => self.to_le_bytes(),
Endian::Big | Endian::Network => self.to_be_bytes(),
Endian::Native => self.to_ne_bytes(),
}
}
fn from_le_bytes(bytes: [u8; N]) -> Self;
fn from_be_bytes(bytes: [u8; N]) -> Self;
fn from_ne_bytes(bytes: [u8; N]) -> Self;
fn from_bytes_endian(bytes: [u8; N], endian: Endian) -> Self
where
Self: Sized,
{
match endian {
Endian::Little => Self::from_le_bytes(bytes),
Endian::Big | Endian::Network => Self::from_be_bytes(bytes),
Endian::Native => Self::from_ne_bytes(bytes),
}
}
}
macro_rules! bit_endian {
($($width:literal { $($ty:ty),* $(,)? }),* $(,)?) => {
$( // each width
$( // each type
impl BitEndian<$width> for $ty {
fn to_le_bytes(self) -> [u8; $width] {
<$ty>::to_le_bytes(self)
}
fn to_be_bytes(self) -> [u8; $width] {
<$ty>::to_be_bytes(self)
}
fn to_ne_bytes(self) -> [u8; $width] {
<$ty>::to_ne_bytes(self)
}
fn from_le_bytes(bytes: [u8; $width]) -> Self {
<$ty>::from_le_bytes(bytes)
}
fn from_be_bytes(bytes: [u8; $width]) -> Self {
<$ty>::from_be_bytes(bytes)
}
fn from_ne_bytes(bytes: [u8; $width]) -> Self {
<$ty>::from_ne_bytes(bytes)
}
}
)* )* };
}
bit_endian!(
1 { u8, i8 },
2 { u16, i16 },
4 { u32, i32, f32 },
8 { u64, i64, f64 },
16 { u128, i128 },
);
#[cfg(target_pointer_width = "8")]
bit_endian!(1 { usize, isize });
#[cfg(target_pointer_width = "16")]
bit_endian!(2 { usize, isize });
#[cfg(target_pointer_width = "32")]
bit_endian!(4 { usize, isize });
#[cfg(target_pointer_width = "64")]
bit_endian!(8 { usize, isize });
#[cfg(target_pointer_width = "128")]
bit_endian!(16 { usize, isize });
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum Endian {
Little,
Big,
Network,
#[default]
Native,
}
impl Endian {
pub fn canonical(self) -> Self {
match self {
Endian::Little => Endian::Little,
Endian::Big | Endian::Network => Endian::Big,
#[cfg(target_endian = "big")]
Endian::Native => Endian::Big,
#[cfg(target_endian = "little")]
Endian::Native => Endian::Little,
}
}
pub fn is_big(&self) -> bool {
matches!(self.canonical(), Endian::Big)
}
pub fn is_little(&self) -> bool {
matches!(self.canonical(), Endian::Little)
}
}
#[cfg(test)]
mod tests {
#[test]
fn readme() {
assert!(
std::process::Command::new("cargo")
.args(["rdme", "--check"])
.output()
.expect("couldn't run `cargo rdme`")
.status
.success(),
"README.md is out of date - bless the new version by running `cargo rdme`"
)
}
}