miden_formatting/
hex.rs

1//! This module provides various utilties for formatting values as hexadecimal bytes.
2
3use alloc::string::String;
4use core::fmt;
5
6/// This trait represents a value that can be converted to a string of hexadecimal digits which
7/// represent the raw byte encoding of that value.
8///
9/// This trait should only be implemented for types which can be decoded from the resulting string
10/// of hexadecimal digits. It is not a strict requirement, but one that ensures that the
11/// implementation is sane.
12pub trait ToHex {
13    /// Convert this value to a [String] containing the hexadecimal digits that correspond to the
14    /// byte representation of this value.
15    ///
16    /// The resulting string should _not_ have a leading `0x` prefix. Use [ToHex::to_hex_with_prefix]
17    /// if the prefix is needed.
18    fn to_hex(&self) -> String;
19    /// Same as [ToHex::to_hex], but ensures the output contains a leading `0x` prefix.
20    fn to_hex_with_prefix(&self) -> String;
21}
22
23impl ToHex for [u8] {
24    fn to_hex(&self) -> String {
25        format!("{:x}", DisplayHex(self))
26    }
27
28    fn to_hex_with_prefix(&self) -> String {
29        format!("{:#x}", DisplayHex(self))
30    }
31}
32
33impl<'a> ToHex for DisplayHex<'a> {
34    fn to_hex(&self) -> String {
35        format!("{:x}", self)
36    }
37
38    fn to_hex_with_prefix(&self) -> String {
39        format!("{:#x}", self)
40    }
41}
42
43/// Construct a [String] containing the hexadecimal representation of `bytes`
44#[inline]
45pub fn to_hex(bytes: impl AsRef<[u8]>) -> String {
46    bytes.as_ref().to_hex()
47}
48
49/// A display helper for formatting a slice of bytes as hex
50/// with different options using Rust's builtin format language
51pub struct DisplayHex<'a>(pub &'a [u8]);
52
53impl<'a> DisplayHex<'a> {
54    /// Display the underlying bytes of `item` as hexadecimal digits
55    #[inline]
56    pub fn new<'b: 'a, T>(item: &'b T) -> Self
57    where
58        T: AsRef<[u8]>,
59    {
60        Self(item.as_ref())
61    }
62}
63
64impl<'a> fmt::Display for DisplayHex<'a> {
65    #[inline]
66    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67        fmt::LowerHex::fmt(self, f)
68    }
69}
70
71impl<'a> fmt::LowerHex for DisplayHex<'a> {
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        if f.alternate() {
74            f.write_str("0x")?;
75        }
76        for byte in self.0.iter() {
77            write!(f, "{byte:02x}")?;
78        }
79        Ok(())
80    }
81}
82
83impl<'a> crate::prettier::PrettyPrint for DisplayHex<'a> {
84    fn render(&self) -> crate::prettier::Document {
85        crate::prettier::text(format!("{:#x}", self))
86    }
87}