use crate::{ComponentBytes, Error, Signature};
use core::{fmt, str};
pub(crate) struct ComponentFormatter<'a>(pub(crate) &'a ComponentBytes);
impl fmt::Debug for ComponentFormatter<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x")?;
for byte in self.0 {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl fmt::LowerHex for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for component in [&self.R, &self.s] {
for byte in component {
write!(f, "{:02x}", byte)?;
}
}
Ok(())
}
}
impl fmt::UpperHex for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for component in [&self.R, &self.s] {
for byte in component {
write!(f, "{:02X}", byte)?;
}
}
Ok(())
}
}
impl str::FromStr for Signature {
type Err = Error;
fn from_str(hex: &str) -> signature::Result<Self> {
if hex.as_bytes().len() != Signature::BYTE_SIZE * 2 {
return Err(Error::new());
}
let mut upper_case = None;
for &byte in hex.as_bytes() {
match byte {
b'0'..=b'9' => (),
b'a'..=b'z' => match upper_case {
Some(true) => return Err(Error::new()),
Some(false) => (),
None => upper_case = Some(false),
},
b'A'..=b'Z' => match upper_case {
Some(true) => (),
Some(false) => return Err(Error::new()),
None => upper_case = Some(true),
},
_ => return Err(Error::new()),
}
}
let mut result = [0u8; Self::BYTE_SIZE];
for (digit, byte) in hex.as_bytes().chunks_exact(2).zip(result.iter_mut()) {
*byte = str::from_utf8(digit)
.ok()
.and_then(|s| u8::from_str_radix(s, 16).ok())
.ok_or_else(Error::new)?;
}
Self::try_from(&result[..])
}
}