const_decoder2/
lib.rs

1//! Constant functions for converting hex- and base64-encoded strings into bytes.
2//! Works on stable Rust and in no-std environments. Base-(2,4,8,16,32,64) encodings with
3//! custom alphabets are supported as well via [`Encoding`].
4//!
5//! [`Decoder`] is the base type encapsulating decoding logic, with [`SkipWhitespace`]
6//! and [`Pem`] types providing its variations with slightly different properties.
7//! (For example, `Pem` allows to parse PEM files.)
8//!
9//! Methods in base types require specifying the length of the output byte array, either in its type,
10//! or using the turbofish syntax (see the examples below). To avoid this, you can instead use
11//! the [`decode!`] macro.
12//!
13//! Conversions are primarily useful for testing, but can be used in other contexts as well.
14//!
15//! # Alternatives
16//!
17//! [`hex-literal`] and [`binary_macros`] crates expose similar functionality
18//! as procedural macros. Because of this, macros cannot be used in no-std environments,
19//! while this approach can.
20//!
21//! In the longer-term (after stabilizing [const mutable refs], etc.)
22//! it should become possible to use "ordinary" encoding crates, such as [`hex`].
23//!
24//! [const mutable refs]: https://github.com/rust-lang/rust/issues/57349
25//! [`binary_macros`]: https://crates.io/crates/binary_macros
26//! [`hex-literal`]: https://crates.io/crates/hex_literal
27//! [`hex`]: https://crates.io/crates/hex
28//!
29//! # Examples
30//!
31//! ```
32//! use const_decoder::Decoder;
33//! // An Ed25519 secret key.
34//! const SECRET_KEY: [u8; 64] = Decoder::Hex.decode(
35//!     b"9e55d1e1aa1f455b8baad9fdf975503655f8b359d542fa7e4ce84106d625b352\
36//!       06fac1f22240cffd637ead6647188429fafda9c9cb7eae43386ac17f61115075",
37//! );
38//! ```
39//!
40//! Same input string decoded using [`decode!`]:
41//!
42//! ```
43//! use const_decoder::{decode, Decoder};
44//!
45//! const SECRET_KEY: &[u8] = &decode!(
46//!     Decoder::Hex,
47//!     b"9e55d1e1aa1f455b8baad9fdf975503655f8b359d542fa7e4ce84106d625b352\
48//!       06fac1f22240cffd637ead6647188429fafda9c9cb7eae43386ac17f61115075",
49//! );
50//! ```
51//!
52//! Note how specifying the output length is avoided by placing the `decode!` output behind a reference.
53//!
54//! [`include_bytes!`] macro works as well.
55//!
56//! ```
57//! # use const_decoder::{decode, Pem};
58//! # // We don't actually want to access FS in tests, so we hack the `include_bytes` macro.
59//! # macro_rules! include_bytes {
60//! #     ($path:tt) => { &[b'A'; 1184] };
61//! # }
62//! const CERT: &[u8] = &decode!(Pem, include_bytes!("certificate.crt"));
63//! ```
64//!
65//! Naturally, all code works in the runtime context as well.
66//!
67//! ```
68//! # use const_decoder::Decoder;
69//! let public_key: [u8; 32] = Decoder::Hex.decode(
70//!     b"06fac1f22240cffd637ead6647188429fafda9c9cb7eae43386ac17f61115075",
71//! );
72//! let other_public_key: [u8; 32] = Decoder::Base64.decode(
73//!     b"6IcUt5J4tArK8SR8SpBZb8Rp7E7kyvaTfv9N8WlOinw=",
74//! );
75//! ```
76//!
77//! ## Compile-time errors
78//!
79//! The code will fail to compile if there is an error in the literal:
80//!
81//! ```compile_fail
82//! # use const_decoder::Decoder;
83//! // The provided hex string is too short
84//! const BOGUS: [u8; 32] = Decoder::Hex.decode(b"c0ffee");
85//! ```
86//!
87//! ```compile_fail
88//! # use const_decoder::Decoder;
89//! // The provided hex string is too long
90//! const BOGUS: [u8; 3] = Decoder::Hex.decode(b"c01dbeef");
91//! ```
92//!
93//! ```compile_fail
94//! # use const_decoder::Decoder;
95//! // The provided string contains invalid chars
96//! const BOGUS: [u8; 5] = Decoder::Hex.decode(b"c0ffeecup");
97//! ```
98
99#![no_std]
100// Documentation settings.
101#![doc(html_root_url = "https://docs.rs/const-decoder/0.4.0")]
102// Linter settings.
103#![warn(missing_debug_implementations, missing_docs, bare_trait_objects)]
104#![warn(clippy::all, clippy::pedantic)]
105#![allow(clippy::must_use_candidate, clippy::shadow_unrelated)]
106
107pub use crate::{
108    decoder::{Decoder, Encoding},
109    macros::DecoderWrapper,
110    wrappers::{Pem, SkipWhitespace},
111};
112
113mod decoder;
114mod macros;
115#[cfg(test)]
116mod tests;
117mod wrappers;
118
119#[cfg(doctest)]
120doc_comment::doctest!("../README.md");