|
1 |
| -//! # Getting started |
| 1 | +//! Correct, fast, and configurable [base64][] decoding and encoding. Base64 |
| 2 | +//! transports binary data efficiently in contexts where only plain text is |
| 3 | +//! allowed. |
2 | 4 | //!
|
3 |
| -//! 1. Perhaps one of the preconfigured engines in [engine::general_purpose] will suit, e.g. |
4 |
| -//! [engine::general_purpose::STANDARD_NO_PAD]. |
5 |
| -//! - These are re-exported in [prelude] with a `BASE64_` prefix for those who prefer to |
6 |
| -//! `use base64::prelude::*` or equivalent, e.g. [prelude::BASE64_STANDARD_NO_PAD] |
7 |
| -//! 1. If not, choose which alphabet you want. Most usage will want [alphabet::STANDARD] or [alphabet::URL_SAFE]. |
8 |
| -//! 1. Choose which [Engine] implementation you want. For the moment there is only one: [engine::GeneralPurpose]. |
9 |
| -//! 1. Configure the engine appropriately using the engine's `Config` type. |
10 |
| -//! - This is where you'll select whether to add padding (when encoding) or expect it (when |
11 |
| -//! decoding). If given the choice, prefer no padding. |
12 |
| -//! 1. Build the engine using the selected alphabet and config. |
| 5 | +//! [base64]: https://developer.mozilla.org/en-US/docs/Glossary/Base64 |
13 | 6 | //!
|
14 |
| -//! For more detail, see below. |
| 7 | +//! # Usage |
15 | 8 | //!
|
16 |
| -//! ## Alphabets |
| 9 | +//! Use an [`Engine`] to decode or encode base64, configured with the base64 |
| 10 | +//! alphabet and padding behavior best suited to your application. |
17 | 11 | //!
|
18 |
| -//! An [alphabet::Alphabet] defines what ASCII symbols are used to encode to or decode from. |
| 12 | +//! ## Engine setup |
19 | 13 | //!
|
20 |
| -//! Constants in [alphabet] like [alphabet::STANDARD] or [alphabet::URL_SAFE] provide commonly used |
21 |
| -//! alphabets, but you can also build your own custom [alphabet::Alphabet] if needed. |
| 14 | +//! There is more than one way to encode a stream of bytes as “base64”. |
| 15 | +//! Different applications use different encoding |
| 16 | +//! [alphabets][alphabet::Alphabet] and |
| 17 | +//! [padding behaviors][engine::general_purpose::GeneralPurposeConfig]. |
22 | 18 | //!
|
23 |
| -//! ## Engines |
| 19 | +//! ### Encoding alphabet |
24 | 20 | //!
|
25 |
| -//! Once you have an `Alphabet`, you can pick which `Engine` you want. A few parts of the public |
26 |
| -//! API provide a default, but otherwise the user must provide an `Engine` to use. |
| 21 | +//! Almost all base64 [alphabets][alphabet::Alphabet] use `A-Z`, `a-z`, and |
| 22 | +//! `0-9`, which gives nearly 64 characters (26 + 26 + 10 = 62), but they differ |
| 23 | +//! in their choice of their final 2. |
27 | 24 | //!
|
28 |
| -//! See [Engine] for more. |
| 25 | +//! Most applications use the [standard][alphabet::STANDARD] alphabet specified |
| 26 | +//! in [RFC 4648][rfc-alphabet]. If that’s all you need, you can get started |
| 27 | +//! quickly by using the pre-configured |
| 28 | +//! [`STANDARD`][engine::general_purpose::STANDARD] engine, which is also available |
| 29 | +//! in the [`prelude`] module as shown here, if you prefer a minimal `use` |
| 30 | +//! footprint. |
29 | 31 | //!
|
30 |
| -//! ## Config |
| 32 | +#![cfg_attr(feature = "alloc", doc = "```")] |
| 33 | +#![cfg_attr(not(feature = "alloc"), doc = "```ignore")] |
| 34 | +//! use base64::prelude::*; |
31 | 35 | //!
|
32 |
| -//! In addition to an `Alphabet`, constructing an `Engine` also requires an [engine::Config]. Each |
33 |
| -//! `Engine` has a corresponding `Config` implementation since different `Engine`s may offer different |
34 |
| -//! levels of configurability. |
| 36 | +//! # fn main() -> Result<(), base64::DecodeError> { |
| 37 | +//! assert_eq!(BASE64_STANDARD.decode(b"+uwgVQA=")?, b"\xFA\xEC\x20\x55\0"); |
| 38 | +//! assert_eq!(BASE64_STANDARD.encode(b"\xFF\xEC\x20\x55\0"), "/+wgVQA="); |
| 39 | +//! # Ok(()) |
| 40 | +//! # } |
| 41 | +//! ``` |
35 | 42 | //!
|
36 |
| -//! # Encoding |
| 43 | +//! [rfc-alphabet]: https://datatracker.ietf.org/doc/html/rfc4648#section-4 |
37 | 44 | //!
|
38 |
| -//! Several different encoding methods on [Engine] are available to you depending on your desire for |
39 |
| -//! convenience vs performance. |
| 45 | +//! Other common alphabets are available in the [`alphabet`] module. |
40 | 46 | //!
|
41 |
| -//! | Method | Output | Allocates | |
42 |
| -//! | ------------------------ | ---------------------------- | ------------------------------ | |
43 |
| -//! | [Engine::encode] | Returns a new `String` | Always | |
44 |
| -//! | [Engine::encode_string] | Appends to provided `String` | Only if `String` needs to grow | |
45 |
| -//! | [Engine::encode_slice] | Writes to provided `&[u8]` | Never - fastest | |
| 47 | +//! #### URL-safe alphabet |
46 | 48 | //!
|
47 |
| -//! All of the encoding methods will pad as per the engine's config. |
| 49 | +//! The standard alphabet uses `+` and `/` as its two non-alphanumeric tokens, |
| 50 | +//! which cannot be safely used in URL’s without encoding them as `%2B` and |
| 51 | +//! `%2F`. |
48 | 52 | //!
|
49 |
| -//! # Decoding |
| 53 | +//! To avoid that, some applications use a [“URL-safe” alphabet][alphabet::URL_SAFE], |
| 54 | +//! which uses `-` and `_` instead. To use that alternative alphabet, use the |
| 55 | +//! [`URL_SAFE`][engine::general_purpose::URL_SAFE] engine. This example doesn't |
| 56 | +//! use [`prelude`] to show what a more explicit `use` would look like. |
50 | 57 | //!
|
51 |
| -//! Just as for encoding, there are different decoding methods available. |
| 58 | +#![cfg_attr(feature = "alloc", doc = "```")] |
| 59 | +#![cfg_attr(not(feature = "alloc"), doc = "```ignore")] |
| 60 | +//! use base64::{engine::general_purpose::URL_SAFE, Engine as _}; |
52 | 61 | //!
|
53 |
| -//! | Method | Output | Allocates | |
54 |
| -//! | ------------------------ | ----------------------------- | ------------------------------ | |
55 |
| -//! | [Engine::decode] | Returns a new `Vec<u8>` | Always | |
56 |
| -//! | [Engine::decode_vec] | Appends to provided `Vec<u8>` | Only if `Vec` needs to grow | |
57 |
| -//! | [Engine::decode_slice] | Writes to provided `&[u8]` | Never - fastest | |
| 62 | +//! # fn main() -> Result<(), base64::DecodeError> { |
| 63 | +//! assert_eq!(URL_SAFE.decode(b"-uwgVQA=")?, b"\xFA\xEC\x20\x55\0"); |
| 64 | +//! assert_eq!(URL_SAFE.encode(b"\xFF\xEC\x20\x55\0"), "_-wgVQA="); |
| 65 | +//! # Ok(()) |
| 66 | +//! # } |
| 67 | +//! ``` |
58 | 68 | //!
|
59 |
| -//! Unlike encoding, where all possible input is valid, decoding can fail (see [DecodeError]). |
| 69 | +//! ### Padding characters |
60 | 70 | //!
|
61 |
| -//! Input can be invalid because it has invalid characters or invalid padding. The nature of how |
62 |
| -//! padding is checked depends on the engine's config. |
63 |
| -//! Whitespace in the input is invalid, just like any other non-base64 byte. |
| 71 | +//! Each base64 character represents 6 bits (2⁶ = 64) of the original binary |
| 72 | +//! data, and every 3 bytes of input binary data will encode to 4 base64 |
| 73 | +//! characters (8 bits × 3 = 6 bits × 4 = 24 bits). |
64 | 74 | //!
|
65 |
| -//! # `Read` and `Write` |
| 75 | +//! When the input is not an even multiple of 3 bytes in length, [canonical][] |
| 76 | +//! base64 encoders insert padding characters at the end, so that the output |
| 77 | +//! length is always a multiple of 4: |
66 | 78 | //!
|
67 |
| -//! To decode a [std::io::Read] of b64 bytes, wrap a reader (file, network socket, etc) with |
68 |
| -//! [read::DecoderReader]. |
| 79 | +//! [canonical]: https://datatracker.ietf.org/doc/html/rfc4648#section-3.5 |
69 | 80 | //!
|
70 |
| -//! To write raw bytes and have them b64 encoded on the fly, wrap a [std::io::Write] with |
71 |
| -//! [write::EncoderWriter]. |
| 81 | +#![cfg_attr(feature = "alloc", doc = "```")] |
| 82 | +#![cfg_attr(not(feature = "alloc"), doc = "```ignore")] |
| 83 | +//! use base64::{engine::general_purpose::STANDARD, Engine as _}; |
72 | 84 | //!
|
73 |
| -//! There is some performance overhead (15% or so) because of the necessary buffer shuffling -- |
74 |
| -//! still fast enough that almost nobody cares. Also, these implementations do not heap allocate. |
| 85 | +//! assert_eq!(STANDARD.encode(b""), ""); |
| 86 | +//! assert_eq!(STANDARD.encode(b"f"), "Zg=="); |
| 87 | +//! assert_eq!(STANDARD.encode(b"fo"), "Zm8="); |
| 88 | +//! assert_eq!(STANDARD.encode(b"foo"), "Zm9v"); |
| 89 | +//! ``` |
75 | 90 | //!
|
76 |
| -//! # `Display` |
| 91 | +//! Canonical encoding ensures that base64 encodings will be exactly the same, |
| 92 | +//! byte-for-byte, regardless of input length. But the `=` padding characters |
| 93 | +//! aren’t necessary for decoding, and they may be omitted by using a |
| 94 | +//! [`NO_PAD`][engine::general_purpose::NO_PAD] configuration: |
77 | 95 | //!
|
78 |
| -//! See [display] for how to transparently base64-encode data via a `Display` implementation. |
| 96 | +#![cfg_attr(feature = "alloc", doc = "```")] |
| 97 | +#![cfg_attr(not(feature = "alloc"), doc = "```ignore")] |
| 98 | +//! use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _}; |
79 | 99 | //!
|
80 |
| -//! # Examples |
| 100 | +//! assert_eq!(STANDARD_NO_PAD.encode(b""), ""); |
| 101 | +//! assert_eq!(STANDARD_NO_PAD.encode(b"f"), "Zg"); |
| 102 | +//! assert_eq!(STANDARD_NO_PAD.encode(b"fo"), "Zm8"); |
| 103 | +//! assert_eq!(STANDARD_NO_PAD.encode(b"foo"), "Zm9v"); |
| 104 | +//! ``` |
81 | 105 | //!
|
82 |
| -//! ## Using predefined engines |
| 106 | +//! The pre-configured `NO_PAD` engines will reject inputs containing padding |
| 107 | +//! `=` characters. To encode without padding and still accept padding while |
| 108 | +//! decoding, create an [engine][engine::general_purpose::GeneralPurpose] with |
| 109 | +//! that [padding mode][engine::DecodePaddingMode]. |
83 | 110 | //!
|
84 | 111 | #![cfg_attr(feature = "alloc", doc = "```")]
|
85 | 112 | #![cfg_attr(not(feature = "alloc"), doc = "```ignore")]
|
86 |
| -//! use base64::{Engine as _, engine::general_purpose}; |
87 |
| -//! |
88 |
| -//! let orig = b"data"; |
89 |
| -//! let encoded: String = general_purpose::STANDARD_NO_PAD.encode(orig); |
90 |
| -//! assert_eq!("ZGF0YQ", encoded); |
91 |
| -//! assert_eq!(orig.as_slice(), &general_purpose::STANDARD_NO_PAD.decode(encoded).unwrap()); |
92 |
| -//! |
93 |
| -//! // or, URL-safe |
94 |
| -//! let encoded_url = general_purpose::URL_SAFE_NO_PAD.encode(orig); |
| 113 | +//! # use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _}; |
| 114 | +//! assert_eq!(STANDARD_NO_PAD.decode(b"Zm8="), Err(base64::DecodeError::InvalidPadding)); |
95 | 115 | //! ```
|
96 | 116 | //!
|
97 |
| -//! ## Custom alphabet, config, and engine |
| 117 | +//! ### Further customization |
| 118 | +//! |
| 119 | +//! Decoding and encoding behavior can be customized by creating an |
| 120 | +//! [engine][engine::GeneralPurpose] with an [alphabet][alphabet::Alphabet] and |
| 121 | +//! [padding configuration][engine::GeneralPurposeConfig]: |
98 | 122 | //!
|
99 | 123 | #![cfg_attr(feature = "alloc", doc = "```")]
|
100 | 124 | #![cfg_attr(not(feature = "alloc"), doc = "```ignore")]
|
|
117 | 141 | //!
|
118 | 142 | //! ```
|
119 | 143 | //!
|
| 144 | +//! ## Memory allocation |
| 145 | +//! |
| 146 | +//! The [decode][Engine::decode()] and [encode][Engine::encode()] engine methods |
| 147 | +//! allocate memory for their results – `decode` returns a `Vec<u8>` and |
| 148 | +//! `encode` returns a `String`. To instead decode or encode into a buffer that |
| 149 | +//! you allocated, use one of the alternative methods: |
| 150 | +//! |
| 151 | +//! #### Decoding |
| 152 | +//! |
| 153 | +//! | Method | Output | Allocates memory | |
| 154 | +//! | -------------------------- | ----------------------------- | ----------------------------- | |
| 155 | +//! | [`Engine::decode`] | returns a new `Vec<u8>` | always | |
| 156 | +//! | [`Engine::decode_vec`] | appends to provided `Vec<u8>` | if `Vec` lacks capacity | |
| 157 | +//! | [`Engine::decode_slice`] | writes to provided `&[u8]` | never |
| 158 | +//! |
| 159 | +//! #### Encoding |
| 160 | +//! |
| 161 | +//! | Method | Output | Allocates memory | |
| 162 | +//! | -------------------------- | ---------------------------- | ------------------------------ | |
| 163 | +//! | [`Engine::encode`] | returns a new `String` | always | |
| 164 | +//! | [`Engine::encode_string`] | appends to provided `String` | if `String` lacks capacity | |
| 165 | +//! | [`Engine::encode_slice`] | writes to provided `&[u8]` | never | |
| 166 | +//! |
| 167 | +//! ## Input and output |
| 168 | +//! |
| 169 | +//! The `base64` crate can [decode][Engine::decode()] and |
| 170 | +//! [encode][Engine::encode()] values in memory, or |
| 171 | +//! [`DecoderReader`][read::DecoderReader] and |
| 172 | +//! [`EncoderWriter`][write::EncoderWriter] provide streaming decoding and |
| 173 | +//! encoding for any [readable][std::io::Read] or [writable][std::io::Write] |
| 174 | +//! byte stream. |
| 175 | +//! |
| 176 | +//! #### Decoding |
| 177 | +//! |
| 178 | +#![cfg_attr(feature = "std", doc = "```")] |
| 179 | +#![cfg_attr(not(feature = "std"), doc = "```ignore")] |
| 180 | +//! # use std::io; |
| 181 | +//! use base64::{engine::general_purpose::STANDARD, read::DecoderReader}; |
| 182 | +//! |
| 183 | +//! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 184 | +//! let mut input = io::stdin(); |
| 185 | +//! let mut decoder = DecoderReader::new(&mut input, &STANDARD); |
| 186 | +//! io::copy(&mut decoder, &mut io::stdout())?; |
| 187 | +//! # Ok(()) |
| 188 | +//! # } |
| 189 | +//! ``` |
| 190 | +//! |
| 191 | +//! #### Encoding |
| 192 | +//! |
| 193 | +#![cfg_attr(feature = "std", doc = "```")] |
| 194 | +#![cfg_attr(not(feature = "std"), doc = "```ignore")] |
| 195 | +//! # use std::io; |
| 196 | +//! use base64::{engine::general_purpose::STANDARD, write::EncoderWriter}; |
| 197 | +//! |
| 198 | +//! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 199 | +//! let mut output = io::stdout(); |
| 200 | +//! let mut encoder = EncoderWriter::new(&mut output, &STANDARD); |
| 201 | +//! io::copy(&mut io::stdin(), &mut encoder)?; |
| 202 | +//! # Ok(()) |
| 203 | +//! # } |
| 204 | +//! ``` |
| 205 | +//! |
| 206 | +//! #### Display |
| 207 | +//! |
| 208 | +//! If you only need a base64 representation for implementing the |
| 209 | +//! [`Display`][std::fmt::Display] trait, use |
| 210 | +//! [`Base64Display`][display::Base64Display]: |
| 211 | +//! |
| 212 | +//! ``` |
| 213 | +//! use base64::{display::Base64Display, engine::general_purpose::STANDARD}; |
| 214 | +//! |
| 215 | +//! let value = Base64Display::new(b"\0\x01\x02\x03", &STANDARD); |
| 216 | +//! assert_eq!("base64: AAECAw==", format!("base64: {}", value)); |
| 217 | +//! ``` |
| 218 | +//! |
120 | 219 | //! # Panics
|
121 | 220 | //!
|
122 | 221 | //! If length calculations result in overflowing `usize`, a panic will result.
|
|
0 commit comments