data_encoding_macro/lib.rs
1//! Macros for data-encoding
2//!
3//! This library provides macros to define compile-time byte arrays from encoded strings (using
4//! common bases like [base64], [base32], or [hexadecimal], and also custom bases). It also provides
5//! a macro to define compile-time custom encodings to be used with the [data-encoding] crate at
6//! run-time.
7//!
8//! Up to Rust 1.50, you may need to add the following to your `.cargo/config.toml` to use this
9//! library in no-std or no-alloc environments:
10//!
11//! ```toml
12//! [unstable]
13//! features = ["host_dep"]
14//! ```
15//!
16//! From Rust 1.51, you may need to add the following to your `Cargo.toml`:
17//!
18//! ```toml
19//! [package]
20//! resolver = "2"
21//! ```
22//!
23//! # Examples
24//!
25//! You can define a compile-time byte slice from an encoded string literal:
26//!
27//! ```rust
28//! const HELLO_SLICE: &'static [u8] = &data_encoding_macro::hexlower!("68656c6c6f");
29//! const FOOBAR_SLICE: &'static [u8] = &data_encoding_macro::base64!("Zm9vYmFy");
30//! # fn main() {}
31//! ```
32//!
33//! You can also define a compile-time byte array from an encoded string literal:
34//!
35//! ```rust
36//! data_encoding_macro::hexlower_array!("const HELLO" = "68656c6c6f");
37//! data_encoding_macro::base64_array!("const FOOBAR" = "Zm9vYmFy");
38//! # fn main() {}
39//! ```
40//!
41//! You can define a compile-time custom encoding from its specification:
42//!
43//! ```rust
44//! const HEX: data_encoding::Encoding = data_encoding_macro::new_encoding! {
45//! symbols: "0123456789abcdef",
46//! translate_from: "ABCDEF",
47//! translate_to: "abcdef",
48//! };
49//! const BASE64: data_encoding::Encoding = data_encoding_macro::new_encoding! {
50//! symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
51//! padding: '=',
52//! };
53//! # fn main() {}
54//! ```
55//!
56//! [base32]: macro.base32.html
57//! [base64]: macro.base64.html
58//! [data-encoding]: https://crates.io/crates/data-encoding
59//! [hexadecimal]: macro.hexlower_permissive.html
60
61#![no_std]
62#![warn(unused_results)]
63
64#[doc(hidden)]
65pub use data_encoding_macro_internal::{
66 internal_decode_array, internal_decode_slice, internal_new_encoding,
67};
68
69/// Defines a compile-time byte array by decoding a string literal
70///
71/// This macro takes a list of `key: value,` pairs (the last comma is required). It takes the
72/// key-value pairs specifying the encoding to use to decode the input (see [new_encoding] for the
73/// possible key-value pairs), the input itself keyed by `input`, and the output keyed by `name`.
74/// The output must be of the form `[pub] {const|static} <name>`.
75///
76/// # Examples
77///
78/// ```rust
79/// data_encoding_macro::decode_array! {
80/// name: "const OCTAL",
81/// symbols: "01234567",
82/// padding: '=',
83/// input: "237610==",
84/// }
85/// # fn main() {}
86/// ```
87///
88/// [new_encoding]: macro.new_encoding.html
89#[macro_export]
90macro_rules! decode_array {
91 ($($arg: tt)*) => {
92 $crate::internal_decode_array!($($arg)*);
93 };
94}
95
96/// Defines a compile-time byte slice by decoding a string literal
97///
98/// This macro takes a list of `key: value,` pairs (the last comma is required). It takes the
99/// key-value pairs specifying the encoding to use to decode the input (see [new_encoding] for the
100/// possible key-value pairs), the input itself keyed by `input`, and the output keyed by `name`.
101///
102/// # Examples
103///
104/// ```rust
105/// const OCTAL: &'static [u8] = &data_encoding_macro::decode_slice! {
106/// symbols: "01234567",
107/// padding: '=',
108/// input: "237610==",
109/// };
110/// # fn main() {}
111/// ```
112///
113/// [new_encoding]: macro.new_encoding.html
114#[macro_export]
115macro_rules! decode_slice {
116 ($($arg: tt)*) => {
117 $crate::internal_decode_slice!($($arg)*)
118 };
119}
120
121/// Defines a compile-time custom encoding
122///
123/// This macro takes a list of `key: value,` pairs (the last comma is required). The possible
124/// key-value pairs are:
125///
126/// ```text
127/// symbols: <string>, // e.g. "01234567"
128/// padding: [None]|<char>, // e.g. '='
129/// bit_order: [MostSignificantFirst]|LeastSignificantFirst,
130/// check_trailing_bits: [true]|false,
131/// ignore: [""]|<string>, // e.g. " \t\n"
132/// wrap_width: [0]|<int>, // e.g. 76
133/// wrap_separator: [""]|<string>, // e.g. "\r\n"
134/// translate_from: [""]|<string>, // e.g. "ABCDEF"
135/// translate_to: [""]|<string>, // e.g. "abcdef"
136/// ```
137///
138/// Only `symbols` is required. Everything else is optional and defaults to the value between square
139/// brackets.
140///
141/// # Examples
142///
143/// ```rust
144/// const HEX: data_encoding::Encoding = data_encoding_macro::new_encoding! {
145/// symbols: "0123456789abcdef",
146/// ignore: " \r\t\n",
147/// wrap_width: 32,
148/// wrap_separator: "\n",
149/// translate_from: "ABCDEF",
150/// translate_to: "abcdef",
151/// };
152/// # fn main() {}
153/// ```
154#[macro_export]
155macro_rules! new_encoding {
156 ($($arg: tt)*) => {
157 data_encoding::Encoding::internal_new(&$crate::internal_new_encoding!{ $($arg)* })
158 };
159}
160
161macro_rules! make {
162 ($base: ident $base_array: ident = $ref: ident; $($spec: tt)*) => {
163 #[macro_export]
164 macro_rules! $base_array {
165 ($n: tt = $x: tt) => {
166 $crate::decode_array!(name: $n, input: $x, $($spec)*);
167 };
168 }
169 #[macro_export]
170 macro_rules! $base {
171 ($x: tt) => {
172 $crate::decode_slice!(input: $x, $($spec)*)
173 };
174 }
175 #[test]
176 fn $base() {
177 assert_eq!(new_encoding!($($spec)*), data_encoding::$ref);
178 }
179 };
180}
181
182make! {
183 hexlower hexlower_array = HEXLOWER;
184 symbols: "0123456789abcdef",
185}
186make! {
187 hexlower_permissive hexlower_permissive_array = HEXLOWER_PERMISSIVE;
188 symbols: "0123456789abcdef",
189 translate_from: "ABCDEF",
190 translate_to: "abcdef",
191}
192make! {
193 hexupper hexupper_array = HEXUPPER;
194 symbols: "0123456789ABCDEF",
195}
196make! {
197 hexupper_permissive hexupper_permissive_array = HEXUPPER_PERMISSIVE;
198 symbols: "0123456789ABCDEF",
199 translate_from: "abcdef",
200 translate_to: "ABCDEF",
201}
202make! {
203 base32 base32_array = BASE32;
204 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
205 padding: '=',
206}
207make! {
208 base32_nopad base32_nopad_array = BASE32_NOPAD;
209 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
210}
211make! {
212 base32hex base32hex_array = BASE32HEX;
213 symbols: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
214 padding: '=',
215}
216make! {
217 base32hex_nopad base32hex_nopad_array = BASE32HEX_NOPAD;
218 symbols: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
219}
220make! {
221 base32_dnssec base32_dnssec_array = BASE32_DNSSEC;
222 symbols: "0123456789abcdefghijklmnopqrstuv",
223 translate_from: "ABCDEFGHIJKLMNOPQRSTUV",
224 translate_to: "abcdefghijklmnopqrstuv",
225}
226make! {
227 base32_dnscurve base32_dnscurve_array = BASE32_DNSCURVE;
228 symbols: "0123456789bcdfghjklmnpqrstuvwxyz",
229 bit_order: LeastSignificantFirst,
230 translate_from: "BCDFGHJKLMNPQRSTUVWXYZ",
231 translate_to: "bcdfghjklmnpqrstuvwxyz",
232}
233make! {
234 base64 base64_array = BASE64;
235 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
236 padding: '=',
237}
238make! {
239 base64_nopad base64_nopad_array = BASE64_NOPAD;
240 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
241}
242make! {
243 base64_mime base64_mime_array = BASE64_MIME;
244 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
245 padding: '=',
246 wrap_width: 76,
247 wrap_separator: "\r\n",
248}
249make! {
250 base64_mime_permissive base64_mime_permissive_array = BASE64_MIME_PERMISSIVE;
251 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
252 padding: '=',
253 wrap_width: 76,
254 wrap_separator: "\r\n",
255 check_trailing_bits: false,
256}
257make! {
258 base64url base64url_array = BASE64URL;
259 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
260 padding: '=',
261}
262make! {
263 base64url_nopad base64url_nopad_array = BASE64URL_NOPAD;
264 symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
265}