#![warn(missing_docs)]
extern crate array_init;
extern crate serde;
extern crate smallvec;
#[macro_use]
pub mod macros;
pub mod config;
pub mod types;
pub mod utils;
pub use config::*;
pub use types::{Error, ParseHexError};
use serde::{Deserialize, Deserializer, Serializer};
use smallvec::SmallVec;
use std::iter::FromIterator;
use std::{error, io};
pub trait SerHex<C>: Sized
where
C: HexConf,
{
type Error: error::Error;
fn into_hex_raw<D>(&self, dst: D) -> Result<(), Self::Error>
where
D: io::Write;
fn from_hex_raw<S>(src: S) -> Result<Self, Self::Error>
where
S: AsRef<[u8]>;
fn into_hex(&self) -> Result<String, Self::Error> {
let mut dst: Vec<u8> = Vec::with_capacity(32);
self.into_hex_raw(&mut dst)?;
Ok(String::from_utf8(dst).expect("invalid UTF-8 bytes in parsing"))
}
fn from_hex<S>(src: S) -> Result<Self, Self::Error>
where
S: AsRef<[u8]>,
{
Self::from_hex_raw(src)
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::Error;
let mut dst = SmallVec::<[u8; 64]>::new();
self.into_hex_raw(&mut dst).map_err(S::Error::custom)?;
debug_assert!(::std::str::from_utf8(dst.as_ref()).is_ok());
let s = unsafe { ::std::str::from_utf8_unchecked(dst.as_ref()) };
serializer.serialize_str(s)
}
fn deserialize<'de, D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
let buff: &[u8] = Deserialize::deserialize(deserializer)?;
let rslt = Self::from_hex_raw(buff).map_err(D::Error::custom)?;
Ok(rslt)
}
}
pub trait SerHexOpt<C>: Sized + SerHex<C>
where
C: HexConf,
{
fn serialize<S>(option: &Option<Self>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::Error;
if let Some(ref src) = *option {
let mut dst = SmallVec::<[u8; 64]>::new();
Self::into_hex_raw(src, &mut dst).map_err(S::Error::custom)?;
debug_assert!(::std::str::from_utf8(dst.as_ref()).is_ok());
let s = unsafe { ::std::str::from_utf8_unchecked(dst.as_ref()) };
serializer.serialize_some(s)
} else {
serializer.serialize_none()
}
}
fn deserialize<'de, D>(deserializer: D) -> Result<Option<Self>, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
let option: Option<&[u8]> = Deserialize::deserialize(deserializer)?;
if let Some(ref buff) = option {
let rslt = Self::from_hex_raw(buff).map_err(D::Error::custom)?;
Ok(Some(rslt))
} else {
Ok(None)
}
}
}
impl<T, C> SerHexOpt<C> for T
where
T: Sized + SerHex<C>,
C: HexConf,
{
}
pub trait SerHexSeq<C>: Sized + SerHex<Strict> + SerHex<StrictCap>
where
C: HexConf,
{
fn size() -> usize;
fn serialize<'a, S, T>(sequence: T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: IntoIterator<Item = &'a Self>,
Self: 'a,
{
use serde::ser::Error;
let mut dst = SmallVec::<[u8; 128]>::new();
if <C as HexConf>::withpfx() {
dst.extend_from_slice(b"0x");
}
if <C as HexConf>::withcap() {
for elem in sequence.into_iter() {
<Self as SerHex<StrictCap>>::into_hex_raw(elem, &mut dst)
.map_err(S::Error::custom)?;
}
} else {
for elem in sequence.into_iter() {
<Self as SerHex<Strict>>::into_hex_raw(elem, &mut dst).map_err(S::Error::custom)?;
}
}
let s = unsafe { ::std::str::from_utf8_unchecked(dst.as_ref()) };
serializer.serialize_str(s)
}
fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: FromIterator<Self>,
{
use serde::de::Error;
let raw: &[u8] = Deserialize::deserialize(deserializer)?;
let src = if raw.starts_with(b"0x") {
&raw[2..]
} else {
&raw[..]
};
let hexsize = Self::size() * 2;
if src.len() % hexsize == 0 {
let mut buff = Vec::with_capacity(src.len() / hexsize);
for chunk in src.chunks(hexsize) {
let elem =
<Self as SerHex<Strict>>::from_hex_raw(chunk).map_err(D::Error::custom)?;
buff.push(elem);
}
Ok(buff.into_iter().collect())
} else {
Err(D::Error::custom("bad hexadecimal sequence size"))
}
}
}
impl_serhex_uint!(u8, 1);
impl_serhex_uint!(u16, 2);
impl_serhex_uint!(u32, 4);
impl_serhex_uint!(u64, 8);
impl_serhex_strict_array!(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
);