serde_human_bytes/codec.rs
1//! Pluggable encoding format for human-readable byte serialization.
2//!
3//! A [`Codec`] decides how `&[u8]` is rendered into / parsed from a string
4//! when the underlying serde format is human-readable (JSON, YAML, TOML…).
5//! For non-human-readable formats (bincode, postcard, CBOR…), the codec is
6//! bypassed entirely and bytes are emitted verbatim.
7//!
8//! Three codecs ship with the crate:
9//!
10//! | Codec | Encode | Decode |
11//! |-------------|----------------------|----------------------------|
12//! | [`LowerHex`] | lowercase hex | case-insensitive hex |
13//! | [`UpperHex`] | UPPERCASE hex | case-insensitive hex |
14//! | [`Base64`] | standard base64 | standard base64 |
15
16use alloc::string::String;
17use alloc::vec::Vec;
18use serde::de::Error;
19
20/// Encoding/decoding strategy used in human-readable mode.
21pub trait Codec {
22 /// Render bytes as the human-readable string form.
23 fn encode(bytes: &[u8]) -> String;
24
25 /// Parse the human-readable string form back into bytes.
26 fn decode<E: Error>(s: &str) -> Result<Vec<u8>, E>;
27}
28
29/// Lowercase hex (default).
30pub struct LowerHex;
31
32impl Codec for LowerHex {
33 fn encode(bytes: &[u8]) -> String {
34 hex::encode(bytes)
35 }
36 fn decode<E: Error>(s: &str) -> Result<Vec<u8>, E> {
37 hex::decode(s).map_err(E::custom)
38 }
39}
40
41/// UPPERCASE hex. Decoder is case-insensitive, matching [`LowerHex`].
42pub struct UpperHex;
43
44impl Codec for UpperHex {
45 fn encode(bytes: &[u8]) -> String {
46 hex::encode_upper(bytes)
47 }
48 fn decode<E: Error>(s: &str) -> Result<Vec<u8>, E> {
49 hex::decode(s).map_err(E::custom)
50 }
51}
52
53/// Standard base64.
54pub struct Base64;
55
56impl Codec for Base64 {
57 fn encode(bytes: &[u8]) -> String {
58 ::base64::encode(bytes)
59 }
60 fn decode<E: Error>(s: &str) -> Result<Vec<u8>, E> {
61 ::base64::decode(s).map_err(E::custom)
62 }
63}