1use crate::{ComponentBytes, Error, Signature};
5use core::{fmt, str};
6
7pub(crate) struct ComponentFormatter<'a>(pub(crate) &'a ComponentBytes);
9
10impl fmt::Debug for ComponentFormatter<'_> {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "0x")?;
13
14 for byte in self.0 {
15 write!(f, "{:02x}", byte)?;
16 }
17
18 Ok(())
19 }
20}
21
22impl fmt::LowerHex for Signature {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 for component in [&self.R, &self.s] {
25 for byte in component {
26 write!(f, "{:02x}", byte)?;
27 }
28 }
29 Ok(())
30 }
31}
32
33impl fmt::UpperHex for Signature {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 for component in [&self.R, &self.s] {
36 for byte in component {
37 write!(f, "{:02X}", byte)?;
38 }
39 }
40 Ok(())
41 }
42}
43
44impl str::FromStr for Signature {
50 type Err = Error;
51
52 fn from_str(hex: &str) -> signature::Result<Self> {
53 if hex.as_bytes().len() != Signature::BYTE_SIZE * 2 {
54 return Err(Error::new());
55 }
56
57 let mut upper_case = None;
58
59 for &byte in hex.as_bytes() {
61 match byte {
62 b'0'..=b'9' => (),
63 b'a'..=b'z' => match upper_case {
64 Some(true) => return Err(Error::new()),
65 Some(false) => (),
66 None => upper_case = Some(false),
67 },
68 b'A'..=b'Z' => match upper_case {
69 Some(true) => (),
70 Some(false) => return Err(Error::new()),
71 None => upper_case = Some(true),
72 },
73 _ => return Err(Error::new()),
74 }
75 }
76
77 let mut result = [0u8; Self::BYTE_SIZE];
78 for (digit, byte) in hex.as_bytes().chunks_exact(2).zip(result.iter_mut()) {
79 *byte = str::from_utf8(digit)
80 .ok()
81 .and_then(|s| u8::from_str_radix(s, 16).ok())
82 .ok_or_else(Error::new)?;
83 }
84
85 Self::try_from(&result[..])
86 }
87}