#![allow(clippy::many_single_char_names)]
use core::mem::{size_of};
use super::{Extract, ExtractResult, Span, Stream};
#[inline]
pub fn be_u16(bytes: &[u8]) -> u16 {
assert!(bytes.len() >= 2);
let a = u16::from(bytes[0]) << 8;
let b = u16::from(bytes[1]);
a + b
}
#[inline]
pub fn be_u32(bytes: &[u8]) -> u32 {
assert!(bytes.len() >= 4);
let a = u32::from(bytes[0]) << 24;
let b = u32::from(bytes[1]) << 16;
let c = u32::from(bytes[2]) << 8;
let d = u32::from(bytes[3]);
a + b + c + d
}
#[inline]
pub fn be_u64(bytes: &[u8]) -> u64 {
assert!(bytes.len() >= 8);
let a = u64::from(bytes[0]) << 56;
let b = u64::from(bytes[1]) << 48;
let c = u64::from(bytes[2]) << 40;
let d = u64::from(bytes[3]) << 32;
let e = u64::from(bytes[4]) << 24;
let f = u64::from(bytes[5]) << 16;
let g = u64::from(bytes[6]) << 8;
let h = u64::from(bytes[7]);
a + b + c + d + e + f + g + h
}
#[inline]
pub fn be_i16(bytes: &[u8]) -> i16 {
be_u16(bytes) as i16
}
#[inline]
pub fn be_i32(bytes: &[u8]) -> i32 {
be_u32(bytes) as i32
}
#[inline]
pub fn be_i64(bytes: &[u8]) -> i64 {
be_u64(bytes) as i64
}
#[inline]
pub fn le_u16(bytes: &[u8]) -> u16 {
assert!(bytes.len() >= 2);
let a = u16::from(bytes[0]);
let b = u16::from(bytes[1]) << 8;
a + b
}
#[inline]
pub fn le_u32(bytes: &[u8]) -> u32 {
assert!(bytes.len() >= 4);
let a = u32::from(bytes[0]);
let b = u32::from(bytes[1]) << 8;
let c = u32::from(bytes[2]) << 16;
let d = u32::from(bytes[3]) << 24;
a + b + c + d
}
#[inline]
pub fn le_u64(bytes: &[u8]) -> u64 {
assert!(bytes.len() >= 8);
let a = u64::from(bytes[0]);
let b = u64::from(bytes[1]) << 8;
let c = u64::from(bytes[2]) << 16;
let d = u64::from(bytes[3]) << 24;
let e = u64::from(bytes[4]) << 32;
let f = u64::from(bytes[5]) << 40;
let g = u64::from(bytes[6]) << 48;
let h = u64::from(bytes[7]) << 56;
a + b + c + d + e + f + g + h
}
#[inline]
pub fn le_i16(bytes: &[u8]) -> i16 {
le_u16(bytes) as i16
}
#[inline]
pub fn le_i32(bytes: &[u8]) -> i32 {
le_u32(bytes) as i32
}
#[inline]
pub fn le_i64(bytes: &[u8]) -> i64 {
le_u64(bytes) as i64
}
#[inline]
pub fn be_f32(bytes: &[u8]) -> f32 {
f32::from_bits(be_u32(bytes))
}
#[inline]
pub fn be_f64(bytes: &[u8]) -> f64 {
f64::from_bits(be_u64(bytes))
}
#[inline]
pub fn le_f32(bytes: &[u8]) -> f32 {
f32::from_bits(le_u32(bytes))
}
#[inline]
pub fn le_f64(bytes: &[u8]) -> f64 {
f64::from_bits(le_u64(bytes))
}
impl<'s> Extract<'s, ()> for u8 {
#[inline]
fn extract(stream: &mut Stream<'s>, _: ()) -> ExtractResult<'s, Self> {
stream.extract(1).map(|i: &'s [u8]| i[0])
}
}
impl<'s> Span for u8 {
const SPAN: usize = 1;
}
impl<'s> Extract<'s, ()> for i8 {
#[inline]
fn extract(stream: &mut Stream<'s>, _: ()) -> ExtractResult<'s, Self> {
stream.extract(()).map(|i: u8| i as i8)
}
}
impl<'s> Span for i8 {
const SPAN: usize = 1;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Endianness {
Big,
Little,
}
macro_rules! extract {
($type:ty, $big:ident, $little:ident) => {
impl<'s> Extract<'s, ()> for $type {
#[inline]
fn extract(
stream: &mut Stream<'s>, _: ()
) -> ExtractResult<'s, Self> {
stream.extract(size_of::<$type>()).map($big)
}
}
impl<'s> Extract<'s, Endianness> for $type {
#[inline]
fn extract(
stream: &mut Stream<'s>, endianness: Endianness
) -> ExtractResult<'s, Self> {
let slice = stream.extract(size_of::<$type>())?;
match endianness {
Endianness::Big => Ok($big(slice)),
Endianness::Little => Ok($little(slice)),
}
}
}
impl Span for $type {
const SPAN: usize = size_of::<$type>();
}
};
}
extract!(u16, be_u16, le_u16);
extract!(u32, be_u32, le_u32);
extract!(u64, be_u64, le_u64);
extract!(i16, be_i16, le_i16);
extract!(i32, be_i32, le_i32);
extract!(i64, be_i64, le_i64);
extract!(f32, be_f32, le_f32);
extract!(f64, be_f64, le_f64);
#[cfg(test)]
mod test {
use super::*;
use super::Endianness::*;
use super::super::ExtractError::*;
#[test]
fn test_extract_u16() {
let mut stream = Stream(&[1, 2, 3, 4]);
assert_eq!(stream.extract::<u16, _>(()), Ok(0x0102));
assert_eq!(stream.extract::<u16, _>(()), Ok(0x0304));
assert_eq!(stream.extract::<u16, _>(()), Err(Insufficient(2)));
let mut stream = Stream(&[1, 2, 3, 4]);
assert_eq!(stream.extract::<u16, _>(Big), Ok(0x0102));
assert_eq!(stream.extract::<u16, _>(Big), Ok(0x0304));
assert_eq!(stream.extract::<u16, _>(Big), Err(Insufficient(2)));
let mut stream = Stream(&[1, 2, 3, 4]);
assert_eq!(stream.extract::<u16, _>(Little), Ok(0x0201));
assert_eq!(stream.extract::<u16, _>(Little), Ok(0x0403));
assert_eq!(stream.extract::<u16, _>(Little), Err(Insufficient(2)));
}
}