Skip to main content

hexy/
hexy.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Demonstrate hexadecimal encoding and decoding for a type with a natural hex representation.
4//!
5//! For a type where hex is supported but is not the natural representation see `./custom.rs`.
6//! To wrap an array see the `./wrap_array.rs` example.
7
8use std::fmt;
9use std::str::FromStr;
10
11use hex_conservative::{
12    self as hex, fmt_hex_exact, Case, DecodeFixedLengthBytesError, DisplayHex as _,
13};
14
15fn main() {
16    let s = "deadbeefcafebabedeadbeefcafebabedeadbeefcafebabedeadbeefcafebabe";
17    println!("Parse hex from string:  {}", s);
18
19    let hexy = s.parse::<Hexy>().expect("the correct number of valid hex digits");
20    let display = format!("{}", hexy);
21    println!("Display Hexy as string: {}", display);
22
23    assert_eq!(display, s);
24}
25
26/// A struct that always uses hex when in string form.
27pub struct Hexy {
28    // Some opaque data.
29    data: [u8; 32],
30}
31
32impl Hexy {
33    /// Demonstrates getting internal opaque data as a byte slice.
34    pub fn as_bytes(&self) -> &[u8] { &self.data }
35}
36
37impl fmt::Debug for Hexy {
38    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
39        fmt::Formatter::debug_struct(f, "Hexy").field("data", &self.data.as_hex()).finish()
40    }
41}
42
43// We implement `Display`/`FromStr` using `LowerHex`/`FromHex` respectively, if hex was not the
44// natural representation for this type this would not be the case.
45
46impl fmt::Display for Hexy {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
48}
49
50impl FromStr for Hexy {
51    type Err = DecodeFixedLengthBytesError;
52
53    fn from_str(s: &str) -> Result<Self, Self::Err> {
54        // Errors if the input is invalid
55        let a = hex::decode_to_array::<32>(s)?;
56        Ok(Hexy { data: a })
57    }
58}
59
60// Implement conversion to hex by first converting our type to a byte slice.
61
62impl fmt::LowerHex for Hexy {
63    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64        // This is equivalent to but more performant than:
65        // fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
66        fmt_hex_exact!(f, 32, self.as_bytes(), Case::Lower)
67    }
68}
69
70impl fmt::UpperHex for Hexy {
71    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72        // This is equivalent to but more performant than:
73        // fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
74        fmt_hex_exact!(f, 32, self.as_bytes(), Case::Upper)
75    }
76}