summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_with/src/hex.rs
blob: 1937e3539429b119d344c30498eb0d57816c5afa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! De/Serialization of hexadecimal encoded bytes
//!
//! This modules is only available when using the `hex` feature of the crate.
//!
//! Please check the documentation on the [`Hex`] type for details.

use crate::{
    de::DeserializeAs,
    formats::{Format, Lowercase, Uppercase},
    ser::SerializeAs,
};
use alloc::{borrow::Cow, format, vec::Vec};
use core::{
    convert::{TryFrom, TryInto},
    marker::PhantomData,
};
use serde::{de::Error, Deserialize, Deserializer, Serializer};

/// Serialize bytes as a hex string
///
/// The type serializes a sequence of bytes as a hexadecimal string.
/// It works on any type implementing `AsRef<[u8]>` for serialization and `TryFrom<Vec<u8>>` for deserialization.
///
/// The format type parameter specifies if the hex string should use lower- or uppercase characters.
/// Valid options are the types [`Lowercase`] and [`Uppercase`].
/// Deserialization always supports lower- and uppercase characters, even mixed in one string.
///
/// # Example
///
/// ```rust
/// # #[cfg(feature = "macros")] {
/// # use serde::{Deserialize, Serialize};
/// # use serde_json::json;
/// # use serde_with::serde_as;
/// #
/// #[serde_as]
/// # #[derive(Debug, PartialEq, Eq)]
/// #[derive(Deserialize, Serialize)]
/// struct BytesLowercase(
///     // Equivalent to serde_with::hex::Hex<serde_with::formats::Lowercase>
///     #[serde_as(as = "serde_with::hex::Hex")]
///     Vec<u8>
/// );
///
/// #[serde_as]
/// # #[derive(Debug, PartialEq, Eq)]
/// #[derive(Deserialize, Serialize)]
/// struct BytesUppercase(
///     #[serde_as(as = "serde_with::hex::Hex<serde_with::formats::Uppercase>")]
///     Vec<u8>
/// );
///
/// let b = b"Hello World!";
///
/// // Hex with lowercase letters
/// assert_eq!(
///     json!("48656c6c6f20576f726c6421"),
///     serde_json::to_value(BytesLowercase(b.to_vec())).unwrap()
/// );
/// // Hex with uppercase letters
/// assert_eq!(
///     json!("48656C6C6F20576F726C6421"),
///     serde_json::to_value(BytesUppercase(b.to_vec())).unwrap()
/// );
///
/// // Serialization always work from lower- and uppercase characters, even mixed case.
/// assert_eq!(
///     BytesLowercase(vec![0x00, 0xaa, 0xbc, 0x99, 0xff]),
///     serde_json::from_value(json!("00aAbc99FF")).unwrap()
/// );
/// assert_eq!(
///     BytesUppercase(vec![0x00, 0xaa, 0xbc, 0x99, 0xff]),
///     serde_json::from_value(json!("00aAbc99FF")).unwrap()
/// );
///
/// #[serde_as]
/// # #[derive(Debug, PartialEq, Eq)]
/// #[derive(Deserialize, Serialize)]
/// struct ByteArray(
///     // Equivalent to serde_with::hex::Hex<serde_with::formats::Lowercase>
///     #[serde_as(as = "serde_with::hex::Hex")]
///     [u8; 12]
/// );
///
/// let b = b"Hello World!";
///
/// assert_eq!(
///     json!("48656c6c6f20576f726c6421"),
///     serde_json::to_value(ByteArray(b.clone())).unwrap()
/// );
///
/// // Serialization always work from lower- and uppercase characters, even mixed case.
/// assert_eq!(
///     ByteArray([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xaa, 0xbc, 0x99, 0xff]),
///     serde_json::from_value(json!("0011223344556677aAbc99FF")).unwrap()
/// );
///
/// // Remember that the conversion may fail. (The following errors are specific to fixed-size arrays)
/// let error_result: Result<ByteArray, _> = serde_json::from_value(json!("42")); // Too short
/// error_result.unwrap_err();
///
/// let error_result: Result<ByteArray, _> =
///     serde_json::from_value(json!("000000000000000000000000000000")); // Too long
/// error_result.unwrap_err();
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct Hex<FORMAT: Format = Lowercase>(PhantomData<FORMAT>);

impl<T> SerializeAs<T> for Hex<Lowercase>
where
    T: AsRef<[u8]>,
{
    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&hex::encode(source))
    }
}

impl<T> SerializeAs<T> for Hex<Uppercase>
where
    T: AsRef<[u8]>,
{
    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&hex::encode_upper(source))
    }
}

impl<'de, T, FORMAT> DeserializeAs<'de, T> for Hex<FORMAT>
where
    T: TryFrom<Vec<u8>>,
    FORMAT: Format,
{
    fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
    where
        D: Deserializer<'de>,
    {
        <Cow<'de, str> as Deserialize<'de>>::deserialize(deserializer)
            .and_then(|s| hex::decode(&*s).map_err(Error::custom))
            .and_then(|vec: Vec<u8>| {
                let length = vec.len();
                vec.try_into().map_err(|_e: T::Error| {
                    Error::custom(format!(
                        "Can't convert a Byte Vector of length {} to the output type.",
                        length
                    ))
                })
            })
    }
}