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
//! Hex encoding with `serde`.
//!
//! The functions in this module de/serialize as hex _only_ when the serializer is human readable.
//!
//! # Examples
//!
//! ```
//! # #[cfg(feature = "std")] {
//! use hex_conservative as hex;
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Debug, Serialize, Deserialize)]
//! struct Foo {
//!     #[serde(with = "hex::serde")]
//!     bar: Vec<u8>,
//! }
//! # }
//! ```

use core::fmt;
use core::marker::PhantomData;

use serde::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use crate::prelude::*;

/// Serializes `data` as a hex string using lowercase characters.
///
/// We only serialize as hex if the serializer is human readable, if not we call through to the
/// `Serialize` implementation for `data`.
pub fn serialize<S, T>(data: T, s: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
    T: Serialize + DisplayHex,
{
    serialize_lower(data, s)
}

/// Serializes `data` as a hex string using lowercase characters.
///
/// We only serialize as hex if the serializer is human readable, if not we call through to the
/// `Serialize` implementation for `data`.
pub fn serialize_lower<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
    T: Serialize + DisplayHex,
{
    // Don't do anything special when not human readable.
    if !serializer.is_human_readable() {
        serde::Serialize::serialize(&data, serializer)
    } else {
        serializer.collect_str(&format_args!("{:x}", data.as_hex()))
    }
}

/// Serializes `data` as hex string using uppercase characters.
///
/// We only serialize as hex if the serializer is human readable, if not we call through to the
/// `Serialize` implementation for `data`.
pub fn serialize_upper<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
    T: Serialize + DisplayHex,
{
    // Don't do anything special when not human readable.
    if !serializer.is_human_readable() {
        serde::Serialize::serialize(&data, serializer)
    } else {
        serializer.collect_str(&format_args!("{:X}", data.as_hex()))
    }
}

/// Deserializes a hex string into raw bytes.
///
/// Allows upper, lower, and mixed case characters (e.g. `a5b3c1`, `A5B3C1` and `A5b3C1`).
///
/// We only deserialize from hex if the serializer is human readable, if not we call through to the
/// `Deserialize` implementation for `T`.
pub fn deserialize<'de, D, T>(d: D) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: Deserialize<'de> + FromHex,
{
    struct HexVisitor<T>(PhantomData<T>);

    impl<'de, T> Visitor<'de> for HexVisitor<T>
    where
        T: FromHex,
    {
        type Value = T;

        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.write_str("an ASCII hex string")
        }

        fn visit_str<E: Error>(self, data: &str) -> Result<Self::Value, E> {
            FromHex::from_hex(data).map_err(Error::custom)
        }
    }

    // Don't do anything special when not human readable.
    if !d.is_human_readable() {
        serde::Deserialize::deserialize(d)
    } else {
        d.deserialize_map(HexVisitor(PhantomData))
    }
}