1use crate::FromHex;
18use core::fmt;
19use core::marker::PhantomData;
20use serde_core::de::{Error, Visitor};
21use serde_core::Deserializer;
22
23#[inline]
30pub fn serialize<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
31where
32 S: serde_core::Serializer,
33 T: AsRef<[u8]>,
34{
35 serialize_inner::<S, false, true>(data.as_ref(), serializer)
36}
37
38#[inline]
42pub fn serialize_upper<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
43where
44 S: serde_core::Serializer,
45 T: AsRef<[u8]>,
46{
47 serialize_inner::<S, true, true>(data.as_ref(), serializer)
48}
49
50const STACK_LEN: usize = 128;
52
53const STREAM_LEN: usize = 4096;
55
56fn serialize_inner<S, const UPPER: bool, const PREFIX: bool>(
60 data: &[u8],
61 serializer: S,
62) -> Result<S::Ok, S::Error>
63where
64 S: serde_core::Serializer,
65{
66 if data.len() <= STACK_LEN {
67 let mut buf = crate::impl_core::uninit_array::<u8, { STACK_LEN * 2 + 2 }>();
68 let prefix_len = PREFIX as usize * 2;
69 let len = prefix_len + data.len() * 2;
70 if PREFIX {
71 buf[0].write(b'0');
72 buf[1].write(b'x');
73 }
74 unsafe { crate::imp::encode::<UPPER>(data, &mut buf[prefix_len..len]) };
76 let s = unsafe {
79 core::str::from_utf8_unchecked(crate::impl_core::slice_assume_init(&buf[..len]))
80 };
81 serializer.serialize_str(s)
82 } else {
83 serializer.collect_str(&BufferedHex::<UPPER, PREFIX>(data))
84 }
85}
86
87struct BufferedHex<'a, const UPPER: bool, const PREFIX: bool>(&'a [u8]);
88
89impl<const UPPER: bool, const PREFIX: bool> fmt::Display for BufferedHex<'_, UPPER, PREFIX> {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 use crate::output::{BufferedOutput, FormatterOutput, Output};
92
93 let mut formatter = FormatterOutput::new(f);
94 let mut output = BufferedOutput::<_, STREAM_LEN>::new(&mut formatter);
95 if PREFIX {
96 output.write(b"0x");
97 }
98 unsafe { crate::imp::encode::<UPPER>(self.0, &mut output) };
100 output.finish();
101 formatter.finish()
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use core::fmt::Write;
109
110 struct Sink {
111 writes: usize,
112 bytes: usize,
113 fail_at: usize,
114 }
115
116 impl fmt::Write for Sink {
117 fn write_str(&mut self, s: &str) -> fmt::Result {
118 self.writes += 1;
119 if self.writes >= self.fail_at {
120 return Err(fmt::Error);
121 }
122 self.bytes += s.len();
123 Ok(())
124 }
125 }
126
127 #[test]
128 fn buffered_hex_batches_writes() {
129 let mut sink = Sink {
130 writes: 0,
131 bytes: 0,
132 fail_at: usize::MAX,
133 };
134 write!(sink, "{}", BufferedHex::<false, true>(&[0xab; 4097])).unwrap();
135 assert_eq!(sink.bytes, 8196);
136 assert_eq!(sink.writes, 3);
138 }
139
140 #[test]
141 fn buffered_hex_propagates_flush_errors() {
142 for fail_at in 1..=3 {
144 let mut sink = Sink {
145 writes: 0,
146 bytes: 0,
147 fail_at,
148 };
149 assert!(write!(sink, "{}", BufferedHex::<false, true>(&[0xab; 4097])).is_err());
150 assert_eq!(sink.writes, fail_at);
152 }
153 }
154}
155
156#[inline]
161pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
162where
163 D: Deserializer<'de>,
164 T: FromHex,
165 <T as FromHex>::Error: fmt::Display,
166{
167 struct HexStrVisitor<T>(PhantomData<T>);
168
169 impl<T> Visitor<'_> for HexStrVisitor<T>
170 where
171 T: FromHex,
172 <T as FromHex>::Error: fmt::Display,
173 {
174 type Value = T;
175
176 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.write_str("a hex encoded string")
178 }
179
180 fn visit_bytes<E: Error>(self, data: &[u8]) -> Result<Self::Value, E> {
181 FromHex::from_hex(data).map_err(Error::custom)
182 }
183
184 fn visit_str<E: Error>(self, data: &str) -> Result<Self::Value, E> {
185 FromHex::from_hex(data.as_bytes()).map_err(Error::custom)
186 }
187 }
188
189 deserializer.deserialize_str(HexStrVisitor(PhantomData))
190}
191
192pub mod no_prefix {
208 #[inline]
215 pub fn serialize<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: serde_core::Serializer,
218 T: AsRef<[u8]>,
219 {
220 super::serialize_inner::<S, false, false>(data.as_ref(), serializer)
221 }
222
223 #[inline]
227 pub fn serialize_upper<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
228 where
229 S: serde_core::Serializer,
230 T: AsRef<[u8]>,
231 {
232 super::serialize_inner::<S, true, false>(data.as_ref(), serializer)
233 }
234
235 pub use super::deserialize;
236}