1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* SPDX-FileCopyrightText: 2026 Stalwart Labs LLC <hello@stalw.art>
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
//! Base32 (RFC 4648 section 6) and the Stalwart base32 alphabet.
//!
//! Every operation is a method on a [`Base32`] engine:
//!
//! ```
//! use encodify::base32;
//!
//! assert_eq!(base32::STANDARD.encode(b"foobar"), "MZXW6YTBOI======");
//! assert_eq!(base32::STANDARD_NO_PAD.encode(b"foobar"), "MZXW6YTBOI");
//! assert_eq!(base32::STANDARD.decode("MZXW6YTBOI======"), Ok(b"foobar".to_vec()));
//!
//! let id = base32::STALWART.encode_u64(20080258862541);
//! assert_eq!(&*id, "singleton");
//! assert_eq!(base32::STALWART.decode_u64("singleton"), Ok(20080258862541));
//! ```
//!
//! # Decoding rules
//!
//! The one-shot decoders ([`Base32::decode`], [`Base32::decode_append`],
//! [`Base32::decode_slice`]) are strict: a byte outside the engine's alphabet
//! is an error (RFC 4648 section 3.3), padding must be exactly what the
//! encoder writes (or absent, depending on the engine's [`Padding`]), a final
//! group of 1, 3 or 6 symbols is an invalid length and the unused bits of the
//! last symbol must be zero, so every byte string has exactly one accepted
//! encoding.
//!
//! Decoding is case-sensitive. [`STANDARD`] and [`STANDARD_NO_PAD`] accept only
//! the uppercase symbols of RFC 4648 table 3, and [`STALWART`] only its
//! lowercase ones. Accepting both cases would give every value many
//! encodings; RFC 6541 (ATPS) labels, which the DNS compares without regard to
//! case, are only ever encoded.
//!
//! The streaming [`Decoder`] is lenient instead: it stops at the first byte
//! that is not a symbol and does not check the trailing bits, so that a
//! caller can read LEB128 fields out of a base32 string that is followed by
//! other text.
//!
//! # Integers
//!
//! [`Base32::encode_u64`] and [`Base32::decode_u64`] write a `u64` as a
//! positional numeral: the first symbol carries the top 4 bits and the next
//! twelve carry 5 bits each, leading zero symbols are dropped, and zero is a
//! single zero symbol. This is the format of Stalwart's JMAP ids.
pub use Display;
pub use U64Text;
pub use ;
use Tables;
/// The base32 alphabets.
/// How an engine writes and checks `=` padding.
/// A base32 configuration: alphabet and padding. Engines are `Copy` and cheap
/// to pass around; all the constants in this module are engines.
/// RFC 4648 alphabet, padded.
pub const STANDARD: Base32 = new;
/// RFC 4648 alphabet without padding, as used by RFC 6541 (ATPS) query
/// labels.
pub const STANDARD_NO_PAD: Base32 = STANDARD.with_padding;
/// Stalwart alphabet, never padded.
pub const STALWART: Base32 = new.with_padding;