1#![warn(missing_docs)]
2
3use core::iter::FromIterator;
4
5mod internal {
6 use crate::{
7 decode::{hex_decode_with_case, CheckCase},
8 encode::hex_encode_custom,
9 };
10 #[cfg(feature = "alloc")]
11 use alloc::{borrow::Cow, format, string::ToString, vec};
12 use core::iter::FromIterator;
13 use serde::{
14 de::{Error, IntoDeserializer},
15 Deserializer, Serializer,
16 };
17
18 pub(crate) fn serialize<S, T>(
19 data: T,
20 serializer: S,
21 with_prefix: bool,
22 case: CheckCase,
23 ) -> Result<S::Ok, S::Error>
24 where
25 S: Serializer,
26 T: AsRef<[u8]>,
27 {
28 let src: &[u8] = data.as_ref();
29
30 let mut dst_length = data.as_ref().len() << 1;
31 if with_prefix {
32 dst_length += 2;
33 }
34
35 let mut dst = vec![0u8; dst_length];
36 let mut dst_start = 0;
37 if with_prefix {
38 dst[0] = b'0';
39 dst[1] = b'x';
40
41 dst_start = 2;
42 }
43
44 hex_encode_custom(src, &mut dst[dst_start..], matches!(case, CheckCase::Upper))
45 .map_err(serde::ser::Error::custom)?;
46 serializer.serialize_str(unsafe { ::core::str::from_utf8_unchecked(&dst) })
47 }
48
49 pub(crate) fn deserialize<'de, D, T>(
50 deserializer: D,
51 with_prefix: bool,
52 check_case: CheckCase,
53 ) -> Result<T, D::Error>
54 where
55 D: Deserializer<'de>,
56 T: FromIterator<u8>,
57 {
58 let raw_src: Cow<str> = serde::Deserialize::deserialize(deserializer)?;
59 if with_prefix && !raw_src.starts_with("0x") {
60 return Err(D::Error::custom("invalid prefix".to_string()));
61 }
62
63 let src: &[u8] = {
64 if with_prefix {
65 raw_src[2..].as_bytes()
66 } else {
67 raw_src.as_bytes()
68 }
69 };
70
71 if src.len() & 1 != 0 {
72 return Err(D::Error::custom("invalid length".to_string()));
73 }
74
75 let mut dst = vec![0; src.len() >> 1];
77 hex_decode_with_case(src, &mut dst, check_case)
78 .map_err(|e| Error::custom(format!("{:?}", e)))?;
79 Ok(dst.into_iter().collect())
80 }
81
82 pub(crate) fn serialize_option<S, T>(
83 option_data: &Option<T>,
84 serializer: S,
85 with_prefix: bool,
86 case: CheckCase,
87 ) -> Result<S::Ok, S::Error>
88 where
89 S: Serializer,
90 T: AsRef<[u8]>,
91 {
92 match option_data {
93 Some(data) => serialize(data, serializer, with_prefix, case),
94 None => serializer.serialize_none(),
95 }
96 }
97
98 pub(crate) fn deserialize_option<'de, D, T>(
99 deserializer: D,
100 with_prefix: bool,
101 check_case: CheckCase,
102 ) -> Result<Option<T>, D::Error>
103 where
104 D: Deserializer<'de>,
105 T: FromIterator<u8>,
106 {
107 let option_str: Option<Cow<str>> = serde::Deserialize::deserialize(deserializer)?;
108 match option_str {
109 Some(raw_src) => {
110 let des: Vec<u8> =
111 deserialize(raw_src.into_deserializer(), with_prefix, check_case)?;
112 Ok(Some(des.into_iter().collect()))
113 }
114 None => Ok(None),
115 }
116 }
117}
118
119pub fn serialize<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
121where
122 S: serde::Serializer,
123 T: AsRef<[u8]>,
124{
125 withpfx_ignorecase::serialize(data, serializer)
126}
127
128pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
130where
131 D: serde::Deserializer<'de>,
132 T: FromIterator<u8>,
133{
134 withpfx_ignorecase::deserialize(deserializer)
135}
136
137macro_rules! faster_hex_serde_macros {
139 ($mod_name:ident, $with_pfx:expr, $check_case:expr) => {
140 pub mod $mod_name {
143 use crate::decode::CheckCase;
144 use crate::serde::internal;
145 use core::iter::FromIterator;
146
147 pub fn serialize<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
149 where
150 S: serde::Serializer,
151 T: AsRef<[u8]>,
152 {
153 internal::serialize(data, serializer, $with_pfx, $check_case)
154 }
155
156 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
158 where
159 D: serde::Deserializer<'de>,
160 T: FromIterator<u8>,
161 {
162 internal::deserialize(deserializer, $with_pfx, $check_case)
163 }
164 }
165 };
166}
167
168faster_hex_serde_macros!(withpfx_ignorecase, true, CheckCase::None);
171faster_hex_serde_macros!(nopfx_ignorecase, false, CheckCase::None);
174faster_hex_serde_macros!(withpfx_lowercase, true, CheckCase::Lower);
177faster_hex_serde_macros!(nopfx_lowercase, false, CheckCase::Lower);
180
181faster_hex_serde_macros!(withpfx_uppercase, true, CheckCase::Upper);
184faster_hex_serde_macros!(nopfx_uppercase, false, CheckCase::Upper);
187
188macro_rules! faster_hex_serde_option_macros {
190 ($mod_name:ident, $with_pfx:expr, $check_case:expr) => {
191 pub mod $mod_name {
194 use crate::decode::CheckCase;
195 use crate::serde::internal;
196 use core::iter::FromIterator;
197
198 pub fn serialize<S, T>(data: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
200 where
201 S: serde::Serializer,
202 T: AsRef<[u8]>,
203 {
204 internal::serialize_option(data, serializer, $with_pfx, $check_case)
205 }
206
207 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
209 where
210 D: serde::Deserializer<'de>,
211 T: FromIterator<u8>,
212 {
213 internal::deserialize_option(deserializer, $with_pfx, $check_case)
214 }
215 }
216 };
217}
218
219faster_hex_serde_option_macros!(option_withpfx_ignorecase, true, CheckCase::None);
221faster_hex_serde_option_macros!(option_nopfx_ignorecase, false, CheckCase::None);
223faster_hex_serde_option_macros!(option_withpfx_lowercase, true, CheckCase::Lower);
225faster_hex_serde_option_macros!(option_nopfx_lowercase, false, CheckCase::Lower);
227faster_hex_serde_option_macros!(option_withpfx_uppercase, true, CheckCase::Upper);
229faster_hex_serde_option_macros!(option_nopfx_uppercase, false, CheckCase::Upper);
231
232#[cfg(test)]
233mod tests {
234 use super::{
235 nopfx_ignorecase, nopfx_lowercase, nopfx_uppercase, option_nopfx_ignorecase,
236 option_nopfx_lowercase, option_nopfx_uppercase, option_withpfx_ignorecase,
237 option_withpfx_lowercase, option_withpfx_uppercase, withpfx_ignorecase, withpfx_lowercase,
238 withpfx_uppercase,
239 };
240 use crate as faster_hex;
241 use bytes::Bytes;
242 use proptest::proptest;
243 use serde::{Deserialize, Serialize};
244
245 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
246 struct Simple {
247 #[serde(with = "faster_hex")]
248 bar: Vec<u8>,
249 }
250
251 #[test]
252 fn test_deserialize_escaped() {
253 let x: Simple = serde_json::from_str(
255 r#"{
256 "bar": "\u0030x\u00303"
257 }"#,
258 )
259 .unwrap();
260 assert_eq!(x.bar, b"\x03");
261 }
262
263 fn _test_simple(src: &str) {
264 let simple = Simple { bar: src.into() };
265 let result = serde_json::to_string(&simple);
266 assert!(result.is_ok());
267 let result = result.unwrap();
268
269 assert!(result.starts_with(r#"{"bar":"0x"#));
271
272 assert!(result[7..].chars().all(|c| !c.is_uppercase()));
274
275 let decode_simple = serde_json::from_str::<Simple>(&result);
276 assert!(decode_simple.is_ok());
277 assert_eq!(decode_simple.unwrap(), simple);
278 }
279
280 proptest! {
281 #[test]
282 fn test_simple(ref s in ".*") {
283 _test_simple(s);
284 }
285 }
286
287 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
288 struct Foo {
289 #[serde(with = "nopfx_lowercase")]
290 bar_nopfx_lowercase_vec: Vec<u8>,
291 #[serde(with = "nopfx_lowercase")]
292 bar_nopfx_lowercase_bytes: Bytes,
293
294 #[serde(with = "withpfx_lowercase")]
295 bar_withpfx_lowercase_vec: Vec<u8>,
296 #[serde(with = "withpfx_lowercase")]
297 bar_withpfx_lowercase_bytes: Bytes,
298
299 #[serde(with = "nopfx_uppercase")]
300 bar_nopfx_uppercase_vec: Vec<u8>,
301 #[serde(with = "nopfx_uppercase")]
302 bar_nopfx_uppercase_bytes: Bytes,
303
304 #[serde(with = "withpfx_uppercase")]
305 bar_withpfx_uppercase_vec: Vec<u8>,
306 #[serde(with = "withpfx_uppercase")]
307 bar_withpfx_uppercase_bytes: Bytes,
308
309 #[serde(with = "withpfx_ignorecase")]
310 bar_withpfx_ignorecase_vec: Vec<u8>,
311 #[serde(with = "withpfx_ignorecase")]
312 bar_withpfx_ignorecase_bytes: Bytes,
313
314 #[serde(with = "nopfx_ignorecase")]
315 bar_nopfx_ignorecase_vec: Vec<u8>,
316 #[serde(with = "nopfx_ignorecase")]
317 bar_nopfx_ignorecase_bytes: Bytes,
318
319 #[serde(with = "option_nopfx_ignorecase")]
320 bar_nopfx_ignorecase_vec_option: Option<Vec<u8>>,
321 #[serde(with = "option_nopfx_ignorecase")]
322 bar_nopfx_ignorecase_bytes_option: Option<Bytes>,
323
324 #[serde(with = "option_withpfx_ignorecase")]
325 bar_withpfx_ignorecase_vec_option: Option<Vec<u8>>,
326 #[serde(with = "option_withpfx_ignorecase")]
327 bar_withpfx_ignorecase_bytes_option: Option<Bytes>,
328
329 #[serde(with = "option_nopfx_lowercase")]
330 bar_nopfx_lowercase_vec_option: Option<Vec<u8>>,
331 #[serde(with = "option_nopfx_lowercase")]
332 bar_nopfx_lowercase_bytes_option: Option<Bytes>,
333
334 #[serde(with = "option_withpfx_lowercase")]
335 bar_withpfx_lowercase_vec_option: Option<Vec<u8>>,
336 #[serde(with = "option_withpfx_lowercase")]
337 bar_withpfx_lowercase_bytes_option: Option<Bytes>,
338
339 #[serde(with = "option_nopfx_uppercase")]
340 bar_nopfx_uppercase_vec_option: Option<Vec<u8>>,
341 #[serde(with = "option_nopfx_uppercase")]
342 bar_nopfx_uppercase_bytes_option: Option<Bytes>,
343
344 #[serde(with = "option_withpfx_uppercase")]
345 bar_withpfx_uppercase_vec_option: Option<Vec<u8>>,
346 #[serde(with = "option_withpfx_uppercase")]
347 bar_withpfx_uppercase_bytes_option: Option<Bytes>,
348 }
349
350 #[test]
351 fn test_serde_default() {
352 {
353 let foo_defuault = Foo {
354 bar_nopfx_lowercase_vec: vec![],
355 bar_nopfx_lowercase_bytes: Default::default(),
356 bar_withpfx_lowercase_vec: vec![],
357 bar_withpfx_lowercase_bytes: Default::default(),
358 bar_nopfx_uppercase_vec: vec![],
359 bar_nopfx_uppercase_bytes: Default::default(),
360 bar_withpfx_uppercase_vec: vec![],
361 bar_withpfx_uppercase_bytes: Default::default(),
362 bar_withpfx_ignorecase_vec: vec![],
363 bar_withpfx_ignorecase_bytes: Default::default(),
364 bar_nopfx_ignorecase_vec: vec![],
365 bar_nopfx_ignorecase_bytes: Default::default(),
366 bar_nopfx_ignorecase_vec_option: Default::default(),
367 bar_nopfx_ignorecase_bytes_option: Default::default(),
368 bar_withpfx_ignorecase_vec_option: Default::default(),
369 bar_withpfx_ignorecase_bytes_option: Default::default(),
370 bar_nopfx_lowercase_vec_option: Default::default(),
371 bar_nopfx_lowercase_bytes_option: Default::default(),
372 bar_withpfx_lowercase_vec_option: Default::default(),
373 bar_withpfx_lowercase_bytes_option: Default::default(),
374 bar_nopfx_uppercase_vec_option: Default::default(),
375 bar_nopfx_uppercase_bytes_option: Default::default(),
376 bar_withpfx_uppercase_vec_option: Default::default(),
377 bar_withpfx_uppercase_bytes_option: Default::default(),
378 };
379 let serde_result = serde_json::to_string(&foo_defuault).unwrap();
380 let expect = r#"
381{"bar_nopfx_lowercase_vec":"",
382"bar_nopfx_lowercase_bytes":"",
383"bar_withpfx_lowercase_vec":"0x",
384"bar_withpfx_lowercase_bytes":"0x",
385"bar_nopfx_uppercase_vec":"",
386"bar_nopfx_uppercase_bytes":"",
387"bar_withpfx_uppercase_vec":"0x",
388"bar_withpfx_uppercase_bytes":"0x",
389"bar_withpfx_ignorecase_vec":"0x",
390"bar_withpfx_ignorecase_bytes":"0x",
391"bar_nopfx_ignorecase_vec":"",
392"bar_nopfx_ignorecase_bytes":"",
393"bar_nopfx_ignorecase_vec_option":null,
394"bar_nopfx_ignorecase_bytes_option":null,
395"bar_withpfx_ignorecase_vec_option":null,
396"bar_withpfx_ignorecase_bytes_option":null,
397"bar_nopfx_lowercase_vec_option":null,
398"bar_nopfx_lowercase_bytes_option":null,
399"bar_withpfx_lowercase_vec_option":null,
400"bar_withpfx_lowercase_bytes_option":null,
401"bar_nopfx_uppercase_vec_option":null,
402"bar_nopfx_uppercase_bytes_option":null,
403"bar_withpfx_uppercase_vec_option":null,
404"bar_withpfx_uppercase_bytes_option":null}"#;
405
406 let expect = expect.replace('\n', "");
407 assert_eq!(serde_result, expect);
408
409 let foo_src: Foo = serde_json::from_str(&serde_result).unwrap();
410 assert_eq!(foo_defuault, foo_src);
411 }
412 }
413
414 fn _test_serde(src: &str) {
415 let foo = Foo {
416 bar_nopfx_lowercase_vec: Vec::from(src),
417 bar_nopfx_lowercase_bytes: Bytes::from(Vec::from(src)),
418 bar_withpfx_lowercase_vec: Vec::from(src),
419 bar_withpfx_lowercase_bytes: Bytes::from(Vec::from(src)),
420 bar_nopfx_uppercase_vec: Vec::from(src),
421 bar_nopfx_uppercase_bytes: Bytes::from(Vec::from(src)),
422 bar_withpfx_uppercase_vec: Vec::from(src),
423 bar_withpfx_uppercase_bytes: Bytes::from(Vec::from(src)),
424
425 bar_withpfx_ignorecase_vec: Vec::from(src),
426 bar_withpfx_ignorecase_bytes: Bytes::from(Vec::from(src)),
427 bar_nopfx_ignorecase_vec: Vec::from(src),
428 bar_nopfx_ignorecase_bytes: Bytes::from(Vec::from(src)),
429 bar_withpfx_ignorecase_vec_option: Some(Vec::from(src)),
430 bar_nopfx_ignorecase_bytes_option: Some(Bytes::from(Vec::from(src))),
431 bar_nopfx_ignorecase_vec_option: Some(Vec::from(src)),
432 bar_withpfx_ignorecase_bytes_option: Some(Bytes::from(Vec::from(src))),
433 bar_nopfx_lowercase_vec_option: Some(Vec::from(src)),
434 bar_nopfx_lowercase_bytes_option: Some(Bytes::from(Vec::from(src))),
435 bar_withpfx_lowercase_vec_option: Some(Vec::from(src)),
436 bar_withpfx_lowercase_bytes_option: Some(Bytes::from(Vec::from(src))),
437 bar_nopfx_uppercase_vec_option: Some(Vec::from(src)),
438 bar_nopfx_uppercase_bytes_option: Some(Bytes::from(Vec::from(src))),
439 bar_withpfx_uppercase_vec_option: Some(Vec::from(src)),
440 bar_withpfx_uppercase_bytes_option: Some(Bytes::from(Vec::from(src))),
441 };
442 let hex_str = hex::encode(src);
443 let hex_str_upper = hex::encode_upper(src);
444 let serde_result = serde_json::to_string(&foo).unwrap();
445
446 let expect = format!(
447 r#"{{"bar_nopfx_lowercase_vec":"{}",
448"bar_nopfx_lowercase_bytes":"{}",
449"bar_withpfx_lowercase_vec":"0x{}",
450"bar_withpfx_lowercase_bytes":"0x{}",
451"bar_nopfx_uppercase_vec":"{}",
452"bar_nopfx_uppercase_bytes":"{}",
453"bar_withpfx_uppercase_vec":"0x{}",
454"bar_withpfx_uppercase_bytes":"0x{}",
455"bar_withpfx_ignorecase_vec":"0x{}",
456"bar_withpfx_ignorecase_bytes":"0x{}",
457"bar_nopfx_ignorecase_vec":"{}",
458"bar_nopfx_ignorecase_bytes":"{}",
459"bar_nopfx_ignorecase_vec_option":"{}",
460"bar_nopfx_ignorecase_bytes_option":"{}",
461"bar_withpfx_ignorecase_vec_option":"0x{}",
462"bar_withpfx_ignorecase_bytes_option":"0x{}",
463"bar_nopfx_lowercase_vec_option":"{}",
464"bar_nopfx_lowercase_bytes_option":"{}",
465"bar_withpfx_lowercase_vec_option":"0x{}",
466"bar_withpfx_lowercase_bytes_option":"0x{}",
467"bar_nopfx_uppercase_vec_option":"{}",
468"bar_nopfx_uppercase_bytes_option":"{}",
469"bar_withpfx_uppercase_vec_option":"0x{}",
470"bar_withpfx_uppercase_bytes_option":"0x{}"}}"#,
471 hex_str,
472 hex_str,
473 hex_str,
474 hex_str,
475 hex_str_upper,
476 hex_str_upper,
477 hex_str_upper,
478 hex_str_upper,
479 hex_str,
480 hex_str,
481 hex_str,
482 hex_str,
483 hex_str,
484 hex_str,
485 hex_str,
486 hex_str,
487 hex_str,
488 hex_str,
489 hex_str,
490 hex_str,
491 hex_str_upper,
492 hex_str_upper,
493 hex_str_upper,
494 hex_str_upper,
495 );
496 let expect = expect.replace('\n', "");
497 assert_eq!(serde_result, expect);
498
499 let foo_src: Foo = serde_json::from_str(&serde_result).unwrap();
500 assert_eq!(foo, foo_src);
501 }
502
503 proptest! {
504 #[test]
505 fn test_serde(ref s in ".*") {
506 _test_serde(s);
507 }
508 }
509
510 fn _test_serde_deserialize(src: &str) {
511 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
512 struct FooNoPfxLower {
513 #[serde(with = "nopfx_lowercase")]
514 bar: Vec<u8>,
515 }
516
517 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
518 struct FooWithPfxLower {
519 #[serde(with = "withpfx_lowercase")]
520 bar: Vec<u8>,
521 }
522
523 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
524 struct FooNoPfxUpper {
525 #[serde(with = "nopfx_uppercase")]
526 bar: Vec<u8>,
527 }
528 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
529 struct FooWithPfxUpper {
530 #[serde(with = "withpfx_uppercase")]
531 bar: Vec<u8>,
532 }
533
534 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
535 struct FooNoPfxIgnoreCase {
536 #[serde(with = "nopfx_ignorecase")]
537 bar: Vec<u8>,
538 }
539 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
540 struct FooWithPfxIgnoreCase {
541 #[serde(with = "withpfx_ignorecase")]
542 bar: Vec<u8>,
543 }
544
545 {
546 let hex_foo = serde_json::to_string(&FooNoPfxLower { bar: src.into() }).unwrap();
547 let foo_pfx: serde_json::Result<FooWithPfxLower> = serde_json::from_str(&hex_foo);
548 assert!(foo_pfx.is_err());
550 assert!(foo_pfx.unwrap_err().to_string().contains("invalid prefix"));
551 }
552
553 {
554 let foo_lower = serde_json::to_string(&FooNoPfxLower { bar: src.into() }).unwrap();
555 let foo_upper_result: serde_json::Result<FooNoPfxUpper> =
556 serde_json::from_str(&foo_lower);
557 if hex::encode(src).contains(char::is_lowercase) {
558 assert!(foo_upper_result.is_err());
560 assert!(foo_upper_result
561 .unwrap_err()
562 .to_string()
563 .contains("Invalid character"));
564 }
565 }
566 }
567
568 proptest! {
569 #[test]
570 fn test_serde_deserialize(ref s in ".*") {
571 _test_serde_deserialize(s);
572 }
573 }
574}