Initial commit
This commit is contained in:
commit
053ecf1fdf
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "order"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[features]
|
||||
nightly = []
|
||||
|
||||
[dependencies]
|
|
@ -0,0 +1,167 @@
|
|||
//! Provides traits for types that can be represented as both big and little-endian byte arrays.
|
||||
//! Types that have a "canonical" byte array representation are not appropriate implementors of
|
||||
//! [`ByteOrdered`].
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
mod private {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
/// Order of bits or bytes.
|
||||
pub trait Order {
|
||||
fn from_bytes<T: ByteOrdered>(bytes: [u8; T::BYTES]) -> T;
|
||||
fn to_bytes<T: ByteOrdered>(value: T) -> [u8; T::BYTES];
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Big;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Little;
|
||||
|
||||
impl Order for Big {
|
||||
#[inline(always)]
|
||||
fn from_bytes<T: ByteOrdered>(bytes: [u8; T::BYTES]) -> T {
|
||||
T::from_be_bytes(bytes)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_bytes<T: ByteOrdered>(value: T) -> [u8; T::BYTES] {
|
||||
value.to_be_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Order for Little {
|
||||
#[inline(always)]
|
||||
fn from_bytes<T: ByteOrdered>(bytes: [u8; T::BYTES]) -> T {
|
||||
T::from_le_bytes(bytes)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_bytes<T: ByteOrdered>(value: T) -> [u8; T::BYTES] {
|
||||
value.to_le_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ByteOrdered: Copy {
|
||||
/// Length of the type in bytes.
|
||||
const BYTES: usize;
|
||||
|
||||
#[inline(always)]
|
||||
fn to_bytes<O: Order>(self) -> [u8; Self::BYTES] {
|
||||
O::to_bytes(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn from_bytes<O: Order>(bytes: [u8; Self::BYTES]) -> Self {
|
||||
O::from_bytes(bytes)
|
||||
}
|
||||
|
||||
fn to_be_bytes(self) -> [u8; Self::BYTES];
|
||||
|
||||
fn from_be_bytes(bytes: [u8; Self::BYTES]) -> Self;
|
||||
|
||||
fn to_le_bytes(self) -> [u8; Self::BYTES];
|
||||
|
||||
fn from_le_bytes(bytes: [u8; Self::BYTES]) -> Self;
|
||||
}
|
||||
|
||||
// TODO: file a bug report "Use-sites of this trait as a bound are required to also duplicate the
|
||||
// where clause"
|
||||
pub trait ByteOrderedA: ByteOrdered
|
||||
where
|
||||
[(); <Self as ByteOrdered>::BYTES]:,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> ByteOrderedA for T
|
||||
where
|
||||
T: ByteOrdered,
|
||||
[(); T::BYTES]:,
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! num_impl {
|
||||
($ty:ty) => {
|
||||
impl ByteOrdered for $ty {
|
||||
const BYTES: usize = std::mem::size_of::<$ty>();
|
||||
|
||||
#[inline(always)]
|
||||
fn to_be_bytes(self) -> [u8; Self::BYTES] {
|
||||
<$ty>::to_be_bytes(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn from_be_bytes(bytes: [u8; Self::BYTES]) -> Self {
|
||||
<$ty>::from_be_bytes(bytes)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_le_bytes(self) -> [u8; Self::BYTES] {
|
||||
<$ty>::to_le_bytes(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn from_le_bytes(bytes: [u8; Self::BYTES]) -> Self {
|
||||
<$ty>::from_le_bytes(bytes)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
num_impl!(u8);
|
||||
num_impl!(u16);
|
||||
num_impl!(u32);
|
||||
num_impl!(u64);
|
||||
num_impl!(u128);
|
||||
|
||||
num_impl!(i8);
|
||||
num_impl!(i16);
|
||||
num_impl!(i32);
|
||||
num_impl!(i64);
|
||||
num_impl!(i128);
|
||||
|
||||
num_impl!(f32);
|
||||
num_impl!(f64);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_be_bytes() {
|
||||
const CASES: &[(u32, [u8; 4])] = &[
|
||||
(0x420, [0x00, 0x00, 0x04, 0x20]),
|
||||
(0x69, [0x00, 0x00, 0x00, 0x69]),
|
||||
(u32::MAX, [0xFF, 0xFF, 0xFF, 0xFF]),
|
||||
(32, [0, 0, 0, 32]),
|
||||
];
|
||||
|
||||
for (n, bytes) in CASES {
|
||||
assert_eq!(n.to_be_bytes(), *bytes);
|
||||
assert_eq!(n.to_bytes::<Big>(), *bytes);
|
||||
assert_eq!(Big::to_bytes(*n), *bytes);
|
||||
|
||||
assert_eq!(u32::from_be_bytes(*bytes), *n);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_le_bytes() {
|
||||
const CASES: &[(u32, [u8; 4])] = &[
|
||||
(0x420, [0x20, 0x04, 0x00, 0x00]),
|
||||
(0x69, [0x69, 0x00, 0x00, 0x00]),
|
||||
(u32::MAX, [0xFF, 0xFF, 0xFF, 0xFF]),
|
||||
(32, [32, 0, 0, 0]),
|
||||
];
|
||||
|
||||
for (n, bytes) in CASES {
|
||||
assert_eq!(n.to_le_bytes(), *bytes);
|
||||
assert_eq!(n.to_bytes::<Little>(), *bytes);
|
||||
assert_eq!(Little::to_bytes(*n), *bytes);
|
||||
|
||||
assert_eq!(u32::from_le_bytes(*bytes), *n);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue