Skip to main content

serdect/
slice.rs

1//! Serialization primitives for slices.
2
3use core::fmt;
4use core::marker::PhantomData;
5
6use serde::{Deserializer, Serializer};
7
8use crate::common::{self, LengthCheck, SliceVisitor, StrIntoBufVisitor};
9
10#[cfg(feature = "alloc")]
11use ::{
12    alloc::vec::Vec,
13    serde::{Deserialize, Serialize},
14};
15
16#[cfg(feature = "alloc")]
17use crate::common::{StrIntoVecVisitor, VecVisitor};
18
19#[cfg(feature = "zeroize")]
20use zeroize::Zeroize;
21
22/// Serialize the given type as lower case hex when using human-readable
23/// formats or binary if the format is binary.
24pub fn serialize_hex_lower_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
25where
26    S: Serializer,
27    T: AsRef<[u8]>,
28{
29    common::serialize_hex_lower_or_bin(value, serializer)
30}
31
32/// Serialize the given type as upper case hex when using human-readable
33/// formats or binary if the format is binary.
34pub fn serialize_hex_upper_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
35where
36    S: Serializer,
37    T: AsRef<[u8]>,
38{
39    common::serialize_hex_upper_or_bin(value, serializer)
40}
41
42struct UpperBound;
43
44impl LengthCheck for UpperBound {
45    fn length_check(buffer_length: usize, data_length: usize) -> bool {
46        buffer_length >= data_length
47    }
48    fn expecting(
49        formatter: &mut fmt::Formatter<'_>,
50        data_type: &str,
51        data_length: usize,
52    ) -> fmt::Result {
53        write!(
54            formatter,
55            "{data_type} with a maximum length of {data_length}"
56        )
57    }
58}
59
60/// Deserialize from hex when using human-readable formats or binary if the
61/// format is binary. Fails if the `buffer` is smaller then the resulting
62/// slice.
63pub fn deserialize_hex_or_bin<'de, D>(buffer: &mut [u8], deserializer: D) -> Result<&[u8], D::Error>
64where
65    D: Deserializer<'de>,
66{
67    if deserializer.is_human_readable() {
68        deserializer.deserialize_str(StrIntoBufVisitor::<UpperBound>(buffer, PhantomData))
69    } else {
70        deserializer.deserialize_byte_buf(SliceVisitor::<UpperBound>(buffer, PhantomData))
71    }
72}
73
74/// Deserialize from hex when using human-readable formats or binary if the
75/// format is binary.
76#[cfg(feature = "alloc")]
77pub fn deserialize_hex_or_bin_vec<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
78where
79    D: Deserializer<'de>,
80{
81    if deserializer.is_human_readable() {
82        deserializer.deserialize_str(StrIntoVecVisitor)
83    } else {
84        deserializer.deserialize_byte_buf(VecVisitor)
85    }
86}
87
88/// [`HexOrBin`] serializer which uses lower case.
89#[cfg(feature = "alloc")]
90pub type HexLowerOrBin = HexOrBin<false>;
91
92/// [`HexOrBin`] serializer which uses upper case.
93#[cfg(feature = "alloc")]
94pub type HexUpperOrBin = HexOrBin<true>;
95
96/// Serializer/deserializer newtype which encodes bytes as either binary or hex.
97///
98/// Use hexadecimal with human-readable formats, or raw binary with binary formats.
99#[cfg(feature = "alloc")]
100#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
101pub struct HexOrBin<const UPPERCASE: bool>(pub Vec<u8>);
102
103#[cfg(feature = "alloc")]
104impl<const UPPERCASE: bool> AsRef<[u8]> for HexOrBin<UPPERCASE> {
105    fn as_ref(&self) -> &[u8] {
106        self.0.as_ref()
107    }
108}
109
110#[cfg(feature = "alloc")]
111impl<const UPPERCASE: bool> From<&[u8]> for HexOrBin<UPPERCASE> {
112    fn from(bytes: &[u8]) -> HexOrBin<UPPERCASE> {
113        Self(bytes.into())
114    }
115}
116
117#[cfg(feature = "alloc")]
118impl<const UPPERCASE: bool> From<Vec<u8>> for HexOrBin<UPPERCASE> {
119    fn from(vec: Vec<u8>) -> HexOrBin<UPPERCASE> {
120        Self(vec)
121    }
122}
123
124#[cfg(feature = "alloc")]
125impl<const UPPERCASE: bool> From<HexOrBin<UPPERCASE>> for Vec<u8> {
126    fn from(vec: HexOrBin<UPPERCASE>) -> Vec<u8> {
127        vec.0
128    }
129}
130
131#[cfg(feature = "alloc")]
132impl<const UPPERCASE: bool> Serialize for HexOrBin<UPPERCASE> {
133    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
134    where
135        S: Serializer,
136    {
137        if UPPERCASE {
138            serialize_hex_upper_or_bin(self, serializer)
139        } else {
140            serialize_hex_lower_or_bin(self, serializer)
141        }
142    }
143}
144
145#[cfg(feature = "alloc")]
146impl<'de, const UPPERCASE: bool> Deserialize<'de> for HexOrBin<UPPERCASE> {
147    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148    where
149        D: Deserializer<'de>,
150    {
151        deserialize_hex_or_bin_vec(deserializer).map(Self)
152    }
153}
154
155#[cfg(all(feature = "alloc", feature = "zeroize"))]
156impl<const UPPERCASE: bool> Zeroize for HexOrBin<UPPERCASE> {
157    fn zeroize(&mut self) {
158        self.0.as_mut_slice().zeroize();
159    }
160}