cuprate_hex/
vec.rs

1//! Hexadecimal serde wrappers for [`Vec<u8>`].
2//!
3//! This module provides transparent wrapper types for
4//! arrays that (de)serialize from hexadecimal input/output.
5
6use std::{
7    borrow::Borrow,
8    ops::{Deref, DerefMut},
9};
10
11use hex::FromHexError;
12use serde::{Deserialize, Deserializer, Serialize};
13
14/// Wrapper type for a byte [`Vec`] that (de)serializes from/to hexadecimal strings.
15///
16/// ```rust
17/// # use cuprate_hex::HexVec;
18/// let hash = [1; 32];
19/// let hex_vec = HexVec::from(hash);
20/// let expected_json = r#""0101010101010101010101010101010101010101010101010101010101010101""#;
21///
22/// let to_string = serde_json::to_string(&hex_vec).unwrap();
23/// assert_eq!(to_string, expected_json);
24///
25/// let from_str = serde_json::from_str::<HexVec>(expected_json).unwrap();
26/// assert_eq!(hex_vec, from_str);
27///
28/// //------
29///
30/// let vec = vec![hex_vec; 2];
31/// let expected_json = r#"["0101010101010101010101010101010101010101010101010101010101010101","0101010101010101010101010101010101010101010101010101010101010101"]"#;
32///
33/// let to_string = serde_json::to_string(&vec).unwrap();
34/// assert_eq!(to_string, expected_json);
35///
36/// let from_str = serde_json::from_str::<Vec<HexVec>>(expected_json).unwrap();
37/// assert_eq!(vec, from_str);
38/// ```
39#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
40#[serde(transparent)]
41#[repr(transparent)]
42pub struct HexVec(#[serde(with = "hex::serde")] pub Vec<u8>);
43
44impl HexVec {
45    /// [`Vec::new`].
46    pub const fn new() -> Self {
47        Self(Vec::new())
48    }
49
50    /// Returns an empty [`Self`] if `array` is all `0`s.
51    ///
52    /// ```rust
53    /// # use cuprate_hex::HexVec;
54    /// assert_eq!(HexVec::empty_if_zeroed([1; 32]).0, [1; 32]);
55    /// assert_eq!(HexVec::empty_if_zeroed([0; 32]), HexVec(vec![]));
56    /// assert!(HexVec::empty_if_zeroed([0; 32]).is_empty());
57    /// ```
58    pub fn empty_if_zeroed<const N: usize>(array: [u8; N]) -> Self {
59        if array == [0; N] {
60            Self(Vec::new())
61        } else {
62            Self(array.to_vec())
63        }
64    }
65}
66
67impl<'de> Deserialize<'de> for HexVec {
68    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69    where
70        D: Deserializer<'de>,
71    {
72        Ok(Self(hex::serde::deserialize(deserializer)?))
73    }
74}
75
76impl Deref for HexVec {
77    type Target = Vec<u8>;
78    fn deref(&self) -> &Self::Target {
79        &self.0
80    }
81}
82
83impl DerefMut for HexVec {
84    fn deref_mut(&mut self) -> &mut Self::Target {
85        &mut self.0
86    }
87}
88
89impl Borrow<Vec<u8>> for HexVec {
90    fn borrow(&self) -> &Vec<u8> {
91        &self.0
92    }
93}
94
95impl AsRef<Vec<u8>> for HexVec {
96    fn as_ref(&self) -> &Vec<u8> {
97        &self.0
98    }
99}
100
101impl From<HexVec> for Vec<u8> {
102    fn from(hex: HexVec) -> Self {
103        hex.0
104    }
105}
106
107impl From<Vec<u8>> for HexVec {
108    fn from(value: Vec<u8>) -> Self {
109        Self(value)
110    }
111}
112
113impl<const N: usize> From<[u8; N]> for HexVec {
114    fn from(value: [u8; N]) -> Self {
115        Self(value.to_vec())
116    }
117}
118
119impl TryFrom<String> for HexVec {
120    type Error = FromHexError;
121    fn try_from(value: String) -> Result<Self, Self::Error> {
122        hex::decode(value).map(Self)
123    }
124}
125
126impl TryFrom<&str> for HexVec {
127    type Error = FromHexError;
128    fn try_from(value: &str) -> Result<Self, Self::Error> {
129        hex::decode(value).map(Self)
130    }
131}
132
133impl<const N: usize> TryFrom<HexVec> for [u8; N] {
134    type Error = FromHexError;
135    fn try_from(value: HexVec) -> Result<Self, Self::Error> {
136        Self::try_from(value.0).map_err(|_| FromHexError::InvalidStringLength)
137    }
138}
139
140#[cfg(test)]
141mod test {
142    use super::*;
143
144    #[test]
145    fn asdf() {
146        let hash = vec![0; 32];
147        let hex_vec = HexVec(hash);
148        let expected_json = r#""0000000000000000000000000000000000000000000000000000000000000000""#;
149
150        let to_string = serde_json::to_string(&hex_vec).unwrap();
151        assert_eq!(to_string, expected_json);
152
153        let from_str = serde_json::from_str::<HexVec>(expected_json).unwrap();
154        assert_eq!(hex_vec, from_str);
155    }
156}