hex_conservative/
serde.rs

1//! Hex encoding with `serde`.
2//!
3//! The functions in this module de/serialize as hex _only_ when the serializer is human readable.
4//!
5//! # Examples
6//!
7//! ```
8//! # #[cfg(feature = "std")] {
9//! use hex_conservative as hex;
10//! use serde::{Serialize, Deserialize};
11//!
12//! #[derive(Debug, Serialize, Deserialize)]
13//! struct Foo {
14//!     #[serde(with = "hex::serde")]
15//!     bar: Vec<u8>,
16//! }
17//! # }
18//! ```
19
20use core::fmt;
21use core::marker::PhantomData;
22
23use serde::de::{Error, Visitor};
24use serde::{Deserialize, Deserializer, Serialize, Serializer};
25
26use crate::prelude::*;
27
28/// Serializes `data` as a hex string using lowercase characters.
29///
30/// We only serialize as hex if the serializer is human readable, if not we call through to the
31/// `Serialize` implementation for `data`.
32pub fn serialize<S, T>(data: T, s: S) -> Result<S::Ok, S::Error>
33where
34    S: Serializer,
35    T: Serialize + DisplayHex,
36{
37    serialize_lower(data, s)
38}
39
40/// Serializes `data` as a hex string using lowercase characters.
41///
42/// We only serialize as hex if the serializer is human readable, if not we call through to the
43/// `Serialize` implementation for `data`.
44pub fn serialize_lower<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
45where
46    S: Serializer,
47    T: Serialize + DisplayHex,
48{
49    // Don't do anything special when not human readable.
50    if !serializer.is_human_readable() {
51        serde::Serialize::serialize(&data, serializer)
52    } else {
53        serializer.collect_str(&format_args!("{:x}", data.as_hex()))
54    }
55}
56
57/// Serializes `data` as hex string using uppercase characters.
58///
59/// We only serialize as hex if the serializer is human readable, if not we call through to the
60/// `Serialize` implementation for `data`.
61pub fn serialize_upper<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
62where
63    S: Serializer,
64    T: Serialize + DisplayHex,
65{
66    // Don't do anything special when not human readable.
67    if !serializer.is_human_readable() {
68        serde::Serialize::serialize(&data, serializer)
69    } else {
70        serializer.collect_str(&format_args!("{:X}", data.as_hex()))
71    }
72}
73
74/// Byte slice wrapper to serialize as a hex string in lowercase characters.
75pub struct SerializeBytesAsHex<'a>(pub &'a [u8]);
76
77impl<'a> serde::Serialize for SerializeBytesAsHex<'a> {
78    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79    where
80        S: serde::Serializer,
81    {
82        serialize_lower(self.0, serializer)
83    }
84}
85
86/// Byte slice wrapper to serialize as a hex string in lowercase characters.
87pub struct SerializeBytesAsHexLower<'a>(pub &'a [u8]);
88
89impl<'a> serde::Serialize for SerializeBytesAsHexLower<'a> {
90    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91    where
92        S: serde::Serializer,
93    {
94        serialize_lower(self.0, serializer)
95    }
96}
97
98/// Byte slice wrapper to serialize as a hex string in uppercase characters.
99pub struct SerializeBytesAsHexUpper<'a>(pub &'a [u8]);
100
101impl<'a> serde::Serialize for SerializeBytesAsHexUpper<'a> {
102    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103    where
104        S: serde::Serializer,
105    {
106        serialize_upper(self.0, serializer)
107    }
108}
109
110/// Deserializes a hex string into raw bytes.
111///
112/// Allows upper, lower, and mixed case characters (e.g. `a5b3c1`, `A5B3C1` and `A5b3C1`).
113///
114/// We only deserialize from hex if the serializer is human readable, if not we call through to the
115/// `Deserialize` implementation for `T`.
116pub fn deserialize<'de, D, T>(d: D) -> Result<T, D::Error>
117where
118    D: Deserializer<'de>,
119    T: Deserialize<'de> + FromHex,
120{
121    struct HexVisitor<T>(PhantomData<T>);
122
123    impl<'de, T> Visitor<'de> for HexVisitor<T>
124    where
125        T: FromHex,
126    {
127        type Value = T;
128
129        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
130            f.write_str("an ASCII hex string")
131        }
132
133        fn visit_str<E: Error>(self, data: &str) -> Result<Self::Value, E> {
134            FromHex::from_hex(data).map_err(Error::custom)
135        }
136    }
137
138    // Don't do anything special when not human readable.
139    if !d.is_human_readable() {
140        serde::Deserialize::deserialize(d)
141    } else {
142        d.deserialize_map(HexVisitor(PhantomData))
143    }
144}