macro_rules! impl_serhex_uint {
($type: ty, $bytes: expr) => {
impl_serhex_seq!($type, $bytes);
impl<C> $crate::SerHex<C> for $type
where
C: $crate::HexConf,
{
type Error = $crate::types::Error;
fn into_hex_raw<D>(&self, mut dst: D) -> ::std::result::Result<(), Self::Error>
where
D: ::std::io::Write,
{
let bytes: [u8; $bytes] = unsafe { ::std::mem::transmute(self.to_be()) };
into_hex_bytearray!(bytes, dst, $bytes)?;
Ok(())
}
fn from_hex_raw<S>(src: S) -> ::std::result::Result<Self, Self::Error>
where
S: AsRef<[u8]>,
{
let rslt: ::std::result::Result<[u8; $bytes], Self::Error> =
from_hex_bytearray!(src, $bytes);
match rslt {
Ok(buf) => {
let val: $type = unsafe { ::std::mem::transmute(buf) };
Ok(Self::from_be(val))
}
Err(e) => Err(e),
}
}
}
};
}
macro_rules! impl_serhex_seq_array {
($conf:ty,$len:expr) => {
impl<T, E> $crate::SerHexSeq<$conf> for [T; $len]
where
E: From<$crate::types::Error> + ::std::error::Error,
T: $crate::SerHexSeq<$conf>
+ $crate::SerHex<$crate::Strict, Error = E>
+ $crate::SerHex<$crate::StrictPfx, Error = E>
+ $crate::SerHex<$crate::StrictCap, Error = E>
+ $crate::SerHex<$crate::StrictCapPfx, Error = E>,
{
fn size() -> usize {
<T as $crate::SerHexSeq<$conf>>::size() * $len
}
}
};
}
macro_rules! impl_serhex_strictconf_array {
($conf:ty,$len:expr) => {
impl_serhex_seq_array!($conf, $len);
impl<T, E> $crate::SerHex<$conf> for [T; $len]
where
E: From<$crate::types::Error> + ::std::error::Error,
T: $crate::SerHex<$crate::Strict, Error = E>
+ $crate::SerHex<$crate::StrictPfx, Error = E>
+ $crate::SerHex<$crate::StrictCap, Error = E>
+ $crate::SerHex<$crate::StrictCapPfx, Error = E>,
{
type Error = E;
fn into_hex_raw<D>(&self, mut dst: D) -> Result<(), Self::Error>
where
D: io::Write,
{
let src: &[T] = self.as_ref();
debug_assert!(src.len() == $len);
let mut items = src.iter();
match items.next() {
Some(itm) => <T as $crate::SerHex<$conf>>::into_hex_raw(itm, &mut dst)?,
None => {
debug_assert!($len == 0);
return Ok(());
}
}
if <$conf as $crate::HexConf>::withcap() {
for itm in items {
<T as SerHex<$crate::StrictCap>>::into_hex_raw(&itm, &mut dst)?;
}
} else {
for itm in items {
<T as SerHex<$crate::Strict>>::into_hex_raw(&itm, &mut dst)?;
}
}
Ok(())
}
fn from_hex_raw<S>(src: S) -> Result<Self, Self::Error>
where
S: AsRef<[u8]>,
{
let raw: &[u8] = src.as_ref();
let hex = if <$conf as $crate::HexConf>::withpfx() {
let pfx = "0x".as_bytes();
if raw.starts_with(pfx) {
&raw[2..]
} else {
raw
}
} else {
raw
};
let chunks = hex.chunks(hex.len() / $len);
let values =
chunks.filter_map(
|chunk| match <T as $crate::SerHex<$crate::Strict>>::from_hex(chunk) {
Ok(val) => Some(val),
Err(_) => None,
},
);
match array_init::from_iter(values) {
Some(rslt) => Ok(rslt),
None => {
let chunks = hex.chunks(hex.len() / $len);
let mut errors = chunks.filter_map(|chunk| {
match <T as $crate::SerHex<$crate::Strict>>::from_hex(chunk) {
Ok(_) => None,
Err(e) => Some(e),
}
});
if let Some(err) = errors.next() {
Err(err.into())
} else {
let expect = $len;
let actual = hex.len() / $len;
let inner = $crate::types::ParseHexError::Size { expect, actual };
let error = $crate::types::Error::from(inner);
Err(error.into())
}
}
}
}
}
};
}
macro_rules! impl_serhex_strict_array {
( $($len: expr),+ ) => {
$(
impl_serhex_strictconf_array!($crate::Strict,$len);
impl_serhex_strictconf_array!($crate::StrictPfx,$len);
impl_serhex_strictconf_array!($crate::StrictCap,$len);
impl_serhex_strictconf_array!($crate::StrictCapPfx,$len);
)+
}
}