use core::fmt;
use core::str::FromStr;
use hex_conservative::{DisplayHex, FromHex, HexToArrayError, HexToBytesError};
fn main() {
let s = "deadbeefcafebabedeadbeefcafebabedeadbeefcafebabedeadbeefcafebabe";
println!("Parse from hex: {}", s);
let hexy = ALittleBitHexy::from_hex(s).expect("the correct number of valid hex digits");
println!("Display ALittleBitHexy as string: {}", hexy);
println!("Display ALittleBitHexy as a hex: {:x}", hexy.as_hex());
#[cfg(feature = "alloc")]
{
let hex = hexy.to_lower_hex_string();
let from_hex = ALittleBitHexy::from_hex(&hex).expect("failed to parse hex");
assert_eq!(from_hex, hexy);
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ALittleBitHexy {
data: [u8; 32],
x: usize,
}
impl ALittleBitHexy {
pub fn new(x: usize) -> Self { Self { x, data: [0_u8; 32] } }
}
impl fmt::Debug for ALittleBitHexy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Formatter::debug_struct(f, "ALittleBitHexy")
.field("data", &self.data.as_hex())
.field("x", &self.x)
.finish()
}
}
impl fmt::Display for ALittleBitHexy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Some application specific format:{}", self.x)
}
}
impl FromStr for ALittleBitHexy {
type Err = Error;
fn from_str(_: &str) -> Result<Self, Self::Err> {
todo!("Parse a string as formatted by `Display`")
}
}
impl FromHex for ALittleBitHexy {
type Err = HexToArrayError;
fn from_byte_iter<I>(iter: I) -> Result<Self, Self::Err>
where
I: Iterator<Item = Result<u8, HexToBytesError>> + ExactSizeIterator + DoubleEndedIterator,
{
let data = <[u8; 32] as FromHex>::from_byte_iter(iter)?;
Ok(ALittleBitHexy { data, x: 0 })
}
}
impl<'a> DisplayHex for &'a ALittleBitHexy {
type Display = DisplayALittleBitHexy<'a>;
fn as_hex(self) -> Self::Display { DisplayALittleBitHexy { data: &self.data } }
fn hex_reserve_suggestion(self) -> usize {
self.data.len().checked_mul(2).expect("the string wouldn't fit into address space")
}
}
pub struct DisplayALittleBitHexy<'a> {
data: &'a [u8],
}
impl<'a> fmt::Display for DisplayALittleBitHexy<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
}
impl<'a> fmt::Debug for DisplayALittleBitHexy<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
}
impl<'a> fmt::LowerHex for DisplayALittleBitHexy<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(&self.data.as_hex(), f)
}
}
impl<'a> fmt::UpperHex for DisplayALittleBitHexy<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::UpperHex::fmt(&self.data.as_hex(), f)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Error {
Conversion(HexToBytesError),
Array(HexToArrayError),
InvalidStringFormat,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match *self {
Conversion(ref e) => write!(f, "conversion error: {:?}", e),
Array(ref e) => write!(f, "array error: {:?}", e),
InvalidStringFormat => write!(f, "invalid string format"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use Error::*;
match *self {
Conversion(ref e) => Some(e),
Array(ref e) => Some(e),
InvalidStringFormat => None,
}
}
}
impl From<HexToBytesError> for Error {
fn from(e: HexToBytesError) -> Self { Self::Conversion(e) }
}
impl From<HexToArrayError> for Error {
fn from(e: HexToArrayError) -> Self { Self::Array(e) }
}