| { | ||
| "git": { | ||
| "sha1": "1e8246a889f2b43299279e0c7ebd849dcaa7cb32" | ||
| "sha1": "6f9f73481506597750c9ab6674329cbb2b6679f0" | ||
| }, | ||
| "path_in_vcs": "" | ||
| } |
@@ -17,3 +17,3 @@ version: '2.1' | ||
| # MSRV | ||
| 'rust:1.57.0' | ||
| 'rust:1.48.0' | ||
| ] | ||
@@ -26,2 +26,3 @@ # a hacky scheme to work around CircleCI's inability to deal with mutable docker tags, forcing us to | ||
| 'stable', | ||
| 'beta', | ||
| 'nightly' | ||
@@ -94,3 +95,3 @@ ] | ||
| - run: | ||
| # dev dependencies can't build on 1.57.0 | ||
| # dev dependencies can't build on 1.48.0 | ||
| name: Run tests | ||
@@ -97,0 +98,0 @@ command: | |
+105
-81
@@ -6,2 +6,11 @@ # This file is automatically @generated by Cargo. | ||
| [[package]] | ||
| name = "aho-corasick" | ||
| version = "1.0.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" | ||
| dependencies = [ | ||
| "memchr", | ||
| ] | ||
| [[package]] | ||
| name = "anes" | ||
@@ -40,5 +49,6 @@ version = "0.1.6" | ||
| name = "base64" | ||
| version = "0.21.2" | ||
| version = "0.21.3" | ||
| dependencies = [ | ||
| "criterion", | ||
| "lazy_static", | ||
| "rand", | ||
@@ -196,5 +206,5 @@ "rstest", | ||
| name = "crossbeam-epoch" | ||
| version = "0.9.14" | ||
| version = "0.9.15" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" | ||
| checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" | ||
| dependencies = [ | ||
@@ -210,5 +220,5 @@ "autocfg", | ||
| name = "crossbeam-utils" | ||
| version = "0.8.15" | ||
| version = "0.8.16" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" | ||
| checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" | ||
| dependencies = [ | ||
@@ -220,11 +230,11 @@ "cfg-if", | ||
| name = "either" | ||
| version = "1.8.1" | ||
| version = "1.9.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" | ||
| checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" | ||
| [[package]] | ||
| name = "getrandom" | ||
| version = "0.2.9" | ||
| version = "0.2.10" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" | ||
| checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" | ||
| dependencies = [ | ||
@@ -268,8 +278,5 @@ "cfg-if", | ||
| name = "hermit-abi" | ||
| version = "0.2.6" | ||
| version = "0.3.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" | ||
| dependencies = [ | ||
| "libc", | ||
| ] | ||
| checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" | ||
@@ -297,11 +304,11 @@ [[package]] | ||
| name = "itoa" | ||
| version = "1.0.6" | ||
| version = "1.0.9" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" | ||
| checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" | ||
| [[package]] | ||
| name = "js-sys" | ||
| version = "0.3.63" | ||
| version = "0.3.64" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" | ||
| checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" | ||
| dependencies = [ | ||
@@ -319,20 +326,23 @@ "wasm-bindgen", | ||
| name = "libc" | ||
| version = "0.2.144" | ||
| version = "0.2.147" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" | ||
| checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" | ||
| [[package]] | ||
| name = "log" | ||
| version = "0.4.17" | ||
| version = "0.4.20" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" | ||
| dependencies = [ | ||
| "cfg-if", | ||
| ] | ||
| checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" | ||
| [[package]] | ||
| name = "memchr" | ||
| version = "2.5.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" | ||
| [[package]] | ||
| name = "memoffset" | ||
| version = "0.8.0" | ||
| version = "0.9.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" | ||
| checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" | ||
| dependencies = [ | ||
@@ -344,5 +354,5 @@ "autocfg", | ||
| name = "num-traits" | ||
| version = "0.2.15" | ||
| version = "0.2.16" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" | ||
| checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" | ||
| dependencies = [ | ||
@@ -354,7 +364,7 @@ "autocfg", | ||
| name = "num_cpus" | ||
| version = "1.15.0" | ||
| version = "1.16.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" | ||
| checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" | ||
| dependencies = [ | ||
| "hermit-abi 0.2.6", | ||
| "hermit-abi 0.3.2", | ||
| "libc", | ||
@@ -365,5 +375,5 @@ ] | ||
| name = "once_cell" | ||
| version = "1.17.1" | ||
| version = "1.18.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" | ||
| checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" | ||
@@ -378,11 +388,11 @@ [[package]] | ||
| name = "os_str_bytes" | ||
| version = "6.5.0" | ||
| version = "6.5.1" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" | ||
| checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" | ||
| [[package]] | ||
| name = "plotters" | ||
| version = "0.3.4" | ||
| version = "0.3.5" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" | ||
| checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" | ||
| dependencies = [ | ||
@@ -398,11 +408,11 @@ "num-traits", | ||
| name = "plotters-backend" | ||
| version = "0.3.4" | ||
| version = "0.3.5" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" | ||
| checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" | ||
| [[package]] | ||
| name = "plotters-svg" | ||
| version = "0.3.3" | ||
| version = "0.3.5" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" | ||
| checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" | ||
| dependencies = [ | ||
@@ -444,5 +454,5 @@ "plotters-backend", | ||
| name = "proc-macro2" | ||
| version = "1.0.58" | ||
| version = "1.0.66" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" | ||
| checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" | ||
| dependencies = [ | ||
@@ -454,5 +464,5 @@ "unicode-ident", | ||
| name = "quote" | ||
| version = "1.0.27" | ||
| version = "1.0.33" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" | ||
| checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" | ||
| dependencies = [ | ||
@@ -516,6 +526,9 @@ "proc-macro2", | ||
| name = "regex" | ||
| version = "1.8.2" | ||
| version = "1.9.3" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" | ||
| checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" | ||
| dependencies = [ | ||
| "aho-corasick", | ||
| "memchr", | ||
| "regex-automata", | ||
| "regex-syntax", | ||
@@ -525,6 +538,17 @@ ] | ||
| [[package]] | ||
| name = "regex-automata" | ||
| version = "0.3.6" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" | ||
| dependencies = [ | ||
| "aho-corasick", | ||
| "memchr", | ||
| "regex-syntax", | ||
| ] | ||
| [[package]] | ||
| name = "regex-syntax" | ||
| version = "0.7.2" | ||
| version = "0.7.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" | ||
| checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" | ||
@@ -566,5 +590,5 @@ [[package]] | ||
| name = "ryu" | ||
| version = "1.0.13" | ||
| version = "1.0.15" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" | ||
| checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" | ||
@@ -582,17 +606,17 @@ [[package]] | ||
| name = "scopeguard" | ||
| version = "1.1.0" | ||
| version = "1.2.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | ||
| checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" | ||
| [[package]] | ||
| name = "semver" | ||
| version = "1.0.17" | ||
| version = "1.0.18" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" | ||
| checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" | ||
| [[package]] | ||
| name = "serde" | ||
| version = "1.0.163" | ||
| version = "1.0.188" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" | ||
| checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" | ||
| dependencies = [ | ||
@@ -604,9 +628,9 @@ "serde_derive", | ||
| name = "serde_derive" | ||
| version = "1.0.163" | ||
| version = "1.0.188" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" | ||
| checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "quote", | ||
| "syn 2.0.16", | ||
| "syn 2.0.29", | ||
| ] | ||
@@ -616,5 +640,5 @@ | ||
| name = "serde_json" | ||
| version = "1.0.96" | ||
| version = "1.0.105" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" | ||
| checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" | ||
| dependencies = [ | ||
@@ -669,5 +693,5 @@ "itoa", | ||
| name = "syn" | ||
| version = "2.0.16" | ||
| version = "2.0.29" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" | ||
| checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" | ||
| dependencies = [ | ||
@@ -706,5 +730,5 @@ "proc-macro2", | ||
| name = "unicode-ident" | ||
| version = "1.0.9" | ||
| version = "1.0.11" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" | ||
| checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" | ||
@@ -753,5 +777,5 @@ [[package]] | ||
| name = "wasm-bindgen" | ||
| version = "0.2.86" | ||
| version = "0.2.87" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" | ||
| checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" | ||
| dependencies = [ | ||
@@ -764,5 +788,5 @@ "cfg-if", | ||
| name = "wasm-bindgen-backend" | ||
| version = "0.2.86" | ||
| version = "0.2.87" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" | ||
| checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" | ||
| dependencies = [ | ||
@@ -774,3 +798,3 @@ "bumpalo", | ||
| "quote", | ||
| "syn 2.0.16", | ||
| "syn 2.0.29", | ||
| "wasm-bindgen-shared", | ||
@@ -781,5 +805,5 @@ ] | ||
| name = "wasm-bindgen-macro" | ||
| version = "0.2.86" | ||
| version = "0.2.87" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" | ||
| checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" | ||
| dependencies = [ | ||
@@ -792,9 +816,9 @@ "quote", | ||
| name = "wasm-bindgen-macro-support" | ||
| version = "0.2.86" | ||
| version = "0.2.87" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" | ||
| checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "quote", | ||
| "syn 2.0.16", | ||
| "syn 2.0.29", | ||
| "wasm-bindgen-backend", | ||
@@ -806,11 +830,11 @@ "wasm-bindgen-shared", | ||
| name = "wasm-bindgen-shared" | ||
| version = "0.2.86" | ||
| version = "0.2.87" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" | ||
| checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" | ||
| [[package]] | ||
| name = "web-sys" | ||
| version = "0.3.63" | ||
| version = "0.3.64" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" | ||
| checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" | ||
| dependencies = [ | ||
@@ -817,0 +841,0 @@ "js-sys", |
+10
-4
@@ -13,6 +13,6 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| [package] | ||
| edition = "2021" | ||
| rust-version = "1.57.0" | ||
| edition = "2018" | ||
| rust-version = "1.48.0" | ||
| name = "base64" | ||
| version = "0.21.2" | ||
| version = "0.21.3" | ||
| authors = [ | ||
@@ -36,4 +36,7 @@ "Alice Maz <alice@alicemaz.com>", | ||
| [package.metadata.docs.rs] | ||
| rustdoc-args = ["--generate-link-to-definition"] | ||
| [profile.bench] | ||
| debug = true | ||
| debug = 2 | ||
@@ -50,2 +53,5 @@ [profile.test] | ||
| [dev-dependencies.lazy_static] | ||
| version = "1.4.0" | ||
| [dev-dependencies.rand] | ||
@@ -52,0 +58,0 @@ version = "0.8.5" |
+1
-1
@@ -1,1 +0,1 @@ | ||
| msrv = "1.57.0" | ||
| msrv = "1.48.0" |
+1
-1
@@ -66,3 +66,3 @@ # [base64](https://crates.io/crates/base64) | ||
| The minimum supported Rust version is 1.57.0. | ||
| The minimum supported Rust version is 1.48.0. | ||
@@ -69,0 +69,0 @@ # Contributing |
+7
-1
@@ -0,1 +1,8 @@ | ||
| # 0.21.3 | ||
| - Implement `source` instead of `cause` on Error types | ||
| - Roll back MSRV to 1.48.0 so Debian can continue to live in a time warp | ||
| - Slightly faster chunked encoding for short inputs | ||
| - Decrease binary size | ||
| # 0.21.2 | ||
@@ -15,3 +22,2 @@ | ||
| # 0.21.0 | ||
@@ -18,0 +24,0 @@ |
+34
-3
| //! Provides [Alphabet] and constants for alphabets commonly used in the wild. | ||
| use crate::PAD_BYTE; | ||
| use core::fmt; | ||
| use core::{convert, fmt}; | ||
| #[cfg(any(feature = "std", test))] | ||
@@ -15,2 +15,6 @@ use std::error; | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// Building and using a custom Alphabet: | ||
| /// | ||
| /// ``` | ||
@@ -23,2 +27,29 @@ /// let custom = base64::alphabet::Alphabet::new("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").unwrap(); | ||
| /// ``` | ||
| /// | ||
| /// Building a const: | ||
| /// | ||
| /// ``` | ||
| /// use base64::alphabet::Alphabet; | ||
| /// | ||
| /// static CUSTOM: Alphabet = { | ||
| /// // Result::unwrap() isn't const yet, but panic!() is OK | ||
| /// match Alphabet::new("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") { | ||
| /// Ok(x) => x, | ||
| /// Err(_) => panic!("creation of alphabet failed"), | ||
| /// } | ||
| /// }; | ||
| /// ``` | ||
| /// | ||
| /// Building a lazy_static: | ||
| /// | ||
| /// ``` | ||
| /// use base64::{ | ||
| /// alphabet::Alphabet, | ||
| /// engine::{general_purpose::GeneralPurpose, GeneralPurposeConfig}, | ||
| /// }; | ||
| /// | ||
| /// lazy_static::lazy_static! { | ||
| /// static ref CUSTOM: Alphabet = Alphabet::new("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").unwrap(); | ||
| /// } | ||
| /// ``` | ||
| #[derive(Clone, Debug, Eq, PartialEq)] | ||
@@ -98,3 +129,3 @@ pub struct Alphabet { | ||
| impl TryFrom<&str> for Alphabet { | ||
| impl convert::TryFrom<&str> for Alphabet { | ||
| type Error = ParseAlphabetError; | ||
@@ -177,3 +208,3 @@ | ||
| use crate::alphabet::*; | ||
| use std::convert::TryFrom as _; | ||
| use core::convert::TryFrom as _; | ||
@@ -180,0 +211,0 @@ #[test] |
+18
-78
@@ -0,10 +1,10 @@ | ||
| use crate::{ | ||
| encode::add_padding, | ||
| engine::{Config, Engine}, | ||
| }; | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| use alloc::string::String; | ||
| use core::cmp; | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| use core::str; | ||
| use crate::encode::add_padding; | ||
| use crate::engine::{Config, Engine}; | ||
| /// The output mechanism for ChunkedEncoder's encoded bytes. | ||
@@ -18,8 +18,5 @@ pub trait Sink { | ||
| const BUF_SIZE: usize = 1024; | ||
| /// A base64 encoder that emits encoded bytes in chunks without heap allocation. | ||
| pub struct ChunkedEncoder<'e, E: Engine + ?Sized> { | ||
| engine: &'e E, | ||
| max_input_chunk_len: usize, | ||
| } | ||
@@ -29,31 +26,20 @@ | ||
| pub fn new(engine: &'e E) -> ChunkedEncoder<'e, E> { | ||
| ChunkedEncoder { | ||
| engine, | ||
| max_input_chunk_len: max_input_length(BUF_SIZE, engine.config().encode_padding()), | ||
| } | ||
| ChunkedEncoder { engine } | ||
| } | ||
| pub fn encode<S: Sink>(&self, bytes: &[u8], sink: &mut S) -> Result<(), S::Error> { | ||
| let mut encode_buf: [u8; BUF_SIZE] = [0; BUF_SIZE]; | ||
| let mut input_index = 0; | ||
| const BUF_SIZE: usize = 1024; | ||
| const CHUNK_SIZE: usize = BUF_SIZE / 4 * 3; | ||
| while input_index < bytes.len() { | ||
| // either the full input chunk size, or it's the last iteration | ||
| let input_chunk_len = cmp::min(self.max_input_chunk_len, bytes.len() - input_index); | ||
| let chunk = &bytes[input_index..(input_index + input_chunk_len)]; | ||
| let mut b64_bytes_written = self.engine.internal_encode(chunk, &mut encode_buf); | ||
| input_index += input_chunk_len; | ||
| let more_input_left = input_index < bytes.len(); | ||
| if self.engine.config().encode_padding() && !more_input_left { | ||
| // no more input, add padding if needed. Buffer will have room because | ||
| // max_input_length leaves room for it. | ||
| b64_bytes_written += | ||
| add_padding(b64_bytes_written, &mut encode_buf[b64_bytes_written..]); | ||
| let mut buf = [0; BUF_SIZE]; | ||
| for chunk in bytes.chunks(CHUNK_SIZE) { | ||
| let mut len = self.engine.internal_encode(chunk, &mut buf); | ||
| if chunk.len() != CHUNK_SIZE && self.engine.config().encode_padding() { | ||
| // Final, potentially partial, chunk. | ||
| // Only need to consider if padding is needed on a partial chunk since full chunk | ||
| // is a multiple of 3, which therefore won't be padded. | ||
| // Pad output to multiple of four bytes if required by config. | ||
| len += add_padding(len, &mut buf[len..]); | ||
| } | ||
| sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?; | ||
| sink.write_encoded_bytes(&buf[..len])?; | ||
| } | ||
@@ -65,23 +51,2 @@ | ||
| /// Calculate the longest input that can be encoded for the given output buffer size. | ||
| /// | ||
| /// If the config requires padding, two bytes of buffer space will be set aside so that the last | ||
| /// chunk of input can be encoded safely. | ||
| /// | ||
| /// The input length will always be a multiple of 3 so that no encoding state has to be carried over | ||
| /// between chunks. | ||
| fn max_input_length(encoded_buf_len: usize, padded: bool) -> usize { | ||
| let effective_buf_len = if padded { | ||
| // make room for padding | ||
| encoded_buf_len | ||
| .checked_sub(2) | ||
| .expect("Don't use a tiny buffer") | ||
| } else { | ||
| encoded_buf_len | ||
| }; | ||
| // No padding, so just normal base64 expansion. | ||
| (effective_buf_len / 4) * 3 | ||
| } | ||
| // A really simple sink that just appends to a string | ||
@@ -158,27 +123,2 @@ #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[test] | ||
| fn max_input_length_no_pad() { | ||
| assert_eq!(768, max_input_length(1024, false)); | ||
| } | ||
| #[test] | ||
| fn max_input_length_with_pad_decrements_one_triple() { | ||
| assert_eq!(765, max_input_length(1024, true)); | ||
| } | ||
| #[test] | ||
| fn max_input_length_with_pad_one_byte_short() { | ||
| assert_eq!(765, max_input_length(1025, true)); | ||
| } | ||
| #[test] | ||
| fn max_input_length_with_pad_fits_exactly() { | ||
| assert_eq!(768, max_input_length(1026, true)); | ||
| } | ||
| #[test] | ||
| fn max_input_length_cant_use_extra_single_encoded_byte() { | ||
| assert_eq!(300, max_input_length(401, false)); | ||
| } | ||
| pub fn chunked_encode_matches_normal_encode_random<S: SinkTestHelper>(sink_test_helper: &S) { | ||
@@ -190,3 +130,3 @@ let mut input_buf: Vec<u8> = Vec::new(); | ||
| for _ in 0..5_000 { | ||
| for _ in 0..20_000 { | ||
| input_buf.clear(); | ||
@@ -193,0 +133,0 @@ output_buf.clear(); |
+2
-6
@@ -44,7 +44,3 @@ use crate::engine::{general_purpose::STANDARD, DecodeEstimate, Engine}; | ||
| #[cfg(any(feature = "std", test))] | ||
| impl error::Error for DecodeError { | ||
| fn cause(&self) -> Option<&dyn error::Error> { | ||
| None | ||
| } | ||
| } | ||
| impl error::Error for DecodeError {} | ||
@@ -73,3 +69,3 @@ /// Errors that can occur while decoding into a slice. | ||
| impl error::Error for DecodeSliceError { | ||
| fn cause(&self) -> Option<&dyn error::Error> { | ||
| fn source(&self) -> Option<&(dyn error::Error + 'static)> { | ||
| match self { | ||
@@ -76,0 +72,0 @@ DecodeSliceError::DecodeError(e) => Some(e), |
+1
-5
@@ -152,7 +152,3 @@ #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[cfg(any(feature = "std", test))] | ||
| impl error::Error for EncodeSliceError { | ||
| fn cause(&self) -> Option<&dyn error::Error> { | ||
| None | ||
| } | ||
| } | ||
| impl error::Error for EncodeSliceError {} | ||
@@ -159,0 +155,0 @@ #[cfg(test)] |
+110
-53
@@ -117,10 +117,19 @@ //! Provides the [Engine] abstraction and out of the box implementations. | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[inline] | ||
| fn encode<T: AsRef<[u8]>>(&self, input: T) -> String { | ||
| let encoded_size = encoded_len(input.as_ref().len(), self.config().encode_padding()) | ||
| .expect("integer overflow when calculating buffer size"); | ||
| let mut buf = vec![0; encoded_size]; | ||
| fn inner<E>(engine: &E, input_bytes: &[u8]) -> String | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let encoded_size = encoded_len(input_bytes.len(), engine.config().encode_padding()) | ||
| .expect("integer overflow when calculating buffer size"); | ||
| encode_with_padding(input.as_ref(), &mut buf[..], self, encoded_size); | ||
| let mut buf = vec![0; encoded_size]; | ||
| String::from_utf8(buf).expect("Invalid UTF8") | ||
| encode_with_padding(input_bytes, &mut buf[..], engine, encoded_size); | ||
| String::from_utf8(buf).expect("Invalid UTF8") | ||
| } | ||
| inner(self, input.as_ref()) | ||
| } | ||
@@ -149,12 +158,16 @@ | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[inline] | ||
| fn encode_string<T: AsRef<[u8]>>(&self, input: T, output_buf: &mut String) { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>(engine: &E, input_bytes: &[u8], output_buf: &mut String) | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let mut sink = chunked_encoder::StringSink::new(output_buf); | ||
| chunked_encoder::ChunkedEncoder::new(self) | ||
| chunked_encoder::ChunkedEncoder::new(engine) | ||
| .encode(input_bytes, &mut sink) | ||
| .expect("Writing to a String shouldn't fail"); | ||
| } | ||
| inner(self, input.as_ref(), output_buf) | ||
| } | ||
@@ -184,2 +197,3 @@ | ||
| /// ``` | ||
| #[inline] | ||
| fn encode_slice<T: AsRef<[u8]>>( | ||
@@ -190,16 +204,25 @@ &self, | ||
| ) -> Result<usize, EncodeSliceError> { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>( | ||
| engine: &E, | ||
| input_bytes: &[u8], | ||
| output_buf: &mut [u8], | ||
| ) -> Result<usize, EncodeSliceError> | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let encoded_size = encoded_len(input_bytes.len(), engine.config().encode_padding()) | ||
| .expect("usize overflow when calculating buffer size"); | ||
| let encoded_size = encoded_len(input_bytes.len(), self.config().encode_padding()) | ||
| .expect("usize overflow when calculating buffer size"); | ||
| if output_buf.len() < encoded_size { | ||
| return Err(EncodeSliceError::OutputSliceTooSmall); | ||
| } | ||
| if output_buf.len() < encoded_size { | ||
| return Err(EncodeSliceError::OutputSliceTooSmall); | ||
| } | ||
| let b64_output = &mut output_buf[0..encoded_size]; | ||
| let b64_output = &mut output_buf[0..encoded_size]; | ||
| encode_with_padding(input_bytes, b64_output, engine, encoded_size); | ||
| encode_with_padding(input_bytes, b64_output, self, encoded_size); | ||
| Ok(encoded_size) | ||
| } | ||
| Ok(encoded_size) | ||
| inner(self, input.as_ref(), output_buf) | ||
| } | ||
@@ -226,14 +249,21 @@ | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[inline] | ||
| fn decode<T: AsRef<[u8]>>(&self, input: T) -> Result<Vec<u8>, DecodeError> { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>(engine: &E, input_bytes: &[u8]) -> Result<Vec<u8>, DecodeError> | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let estimate = engine.internal_decoded_len_estimate(input_bytes.len()); | ||
| let mut buffer = vec![0; estimate.decoded_len_estimate()]; | ||
| let estimate = self.internal_decoded_len_estimate(input_bytes.len()); | ||
| let mut buffer = vec![0; estimate.decoded_len_estimate()]; | ||
| let bytes_written = engine | ||
| .internal_decode(input_bytes, &mut buffer, estimate)? | ||
| .decoded_len; | ||
| let bytes_written = self | ||
| .internal_decode(input_bytes, &mut buffer, estimate)? | ||
| .decoded_len; | ||
| buffer.truncate(bytes_written); | ||
| buffer.truncate(bytes_written); | ||
| Ok(buffer) | ||
| Ok(buffer) | ||
| } | ||
| inner(self, input.as_ref()) | ||
| } | ||
@@ -272,2 +302,3 @@ | ||
| #[cfg(any(feature = "alloc", feature = "std", test))] | ||
| #[inline] | ||
| fn decode_vec<T: AsRef<[u8]>>( | ||
@@ -278,21 +309,28 @@ &self, | ||
| ) -> Result<(), DecodeError> { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>(engine: &E, input_bytes: &[u8], buffer: &mut Vec<u8>) -> Result<(), DecodeError> | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let starting_output_len = buffer.len(); | ||
| let estimate = engine.internal_decoded_len_estimate(input_bytes.len()); | ||
| let starting_output_len = buffer.len(); | ||
| let total_len_estimate = estimate | ||
| .decoded_len_estimate() | ||
| .checked_add(starting_output_len) | ||
| .expect("Overflow when calculating output buffer length"); | ||
| let estimate = self.internal_decoded_len_estimate(input_bytes.len()); | ||
| let total_len_estimate = estimate | ||
| .decoded_len_estimate() | ||
| .checked_add(starting_output_len) | ||
| .expect("Overflow when calculating output buffer length"); | ||
| buffer.resize(total_len_estimate, 0); | ||
| buffer.resize(total_len_estimate, 0); | ||
| let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..]; | ||
| let bytes_written = self | ||
| .internal_decode(input_bytes, buffer_slice, estimate)? | ||
| .decoded_len; | ||
| let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..]; | ||
| buffer.truncate(starting_output_len + bytes_written); | ||
| let bytes_written = engine | ||
| .internal_decode(input_bytes, buffer_slice, estimate)? | ||
| .decoded_len; | ||
| Ok(()) | ||
| buffer.truncate(starting_output_len + bytes_written); | ||
| Ok(()) | ||
| } | ||
| inner(self, input.as_ref(), buffer) | ||
| } | ||
@@ -311,2 +349,3 @@ | ||
| /// if the output buffer is too small. | ||
| #[inline] | ||
| fn decode_slice<T: AsRef<[u8]>>( | ||
@@ -317,12 +356,23 @@ &self, | ||
| ) -> Result<usize, DecodeSliceError> { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>( | ||
| engine: &E, | ||
| input_bytes: &[u8], | ||
| output: &mut [u8], | ||
| ) -> Result<usize, DecodeSliceError> | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| let estimate = engine.internal_decoded_len_estimate(input_bytes.len()); | ||
| let estimate = self.internal_decoded_len_estimate(input_bytes.len()); | ||
| if output.len() < estimate.decoded_len_estimate() { | ||
| return Err(DecodeSliceError::OutputSliceTooSmall); | ||
| if output.len() < estimate.decoded_len_estimate() { | ||
| return Err(DecodeSliceError::OutputSliceTooSmall); | ||
| } | ||
| engine | ||
| .internal_decode(input_bytes, output, estimate) | ||
| .map_err(|e| e.into()) | ||
| .map(|dm| dm.decoded_len) | ||
| } | ||
| self.internal_decode(input_bytes, output, estimate) | ||
| .map_err(|e| e.into()) | ||
| .map(|dm| dm.decoded_len) | ||
| inner(self, input.as_ref(), output) | ||
| } | ||
@@ -344,2 +394,3 @@ | ||
| /// Panics if the provided output buffer is too small for the decoded data. | ||
| #[inline] | ||
| fn decode_slice_unchecked<T: AsRef<[u8]>>( | ||
@@ -350,10 +401,16 @@ &self, | ||
| ) -> Result<usize, DecodeError> { | ||
| let input_bytes = input.as_ref(); | ||
| fn inner<E>(engine: &E, input_bytes: &[u8], output: &mut [u8]) -> Result<usize, DecodeError> | ||
| where | ||
| E: Engine + ?Sized, | ||
| { | ||
| engine | ||
| .internal_decode( | ||
| input_bytes, | ||
| output, | ||
| engine.internal_decoded_len_estimate(input_bytes.len()), | ||
| ) | ||
| .map(|dm| dm.decoded_len) | ||
| } | ||
| self.internal_decode( | ||
| input_bytes, | ||
| output, | ||
| self.internal_decoded_len_estimate(input_bytes.len()), | ||
| ) | ||
| .map(|dm| dm.decoded_len) | ||
| inner(self, input.as_ref(), output) | ||
| } | ||
@@ -360,0 +417,0 @@ } |
@@ -626,3 +626,3 @@ // rstest_reuse template functions have unused variables | ||
| // the different amounts of proper padding, w/ offset from end for the last non-padding char | ||
| let suffixes = vec![("/w==", 2), ("iYu=", 1), ("zzzz", 0)]; | ||
| let suffixes = [("/w==", 2), ("iYu=", 1), ("zzzz", 0)]; | ||
@@ -873,3 +873,3 @@ let prefix_quads_range = distributions::Uniform::from(0..=256); | ||
| let suffixes = vec!["/w", "/w=", "iYU"]; | ||
| let suffixes = ["/w", "/w=", "iYU"]; | ||
| for num_prefix_quads in 0..256 { | ||
@@ -901,3 +901,3 @@ for &suffix in suffixes.iter() { | ||
| let suffixes = vec!["/w=", "/w==", "iYU="]; | ||
| let suffixes = ["/w=", "/w==", "iYU="]; | ||
| for num_prefix_quads in 0..256 { | ||
@@ -904,0 +904,0 @@ for &suffix in suffixes.iter() { |
@@ -47,7 +47,2 @@ use super::encoder::EncoderWriter; | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// Calling `write()` (or related methods) or `finish()` after `finish()` has completed without | ||
| /// error is invalid and will panic. | ||
| /// | ||
| /// # Performance | ||
@@ -148,2 +143,3 @@ /// | ||
| use rand::Rng; | ||
| use std::cmp; | ||
| use std::io::Write; | ||
@@ -163,5 +159,4 @@ | ||
| for _ in 0..size { | ||
| orig_data.push(rng.gen()); | ||
| } | ||
| orig_data.resize(size, 0); | ||
| rng.fill(&mut orig_data[..]); | ||
@@ -181,2 +176,36 @@ let engine = random_engine(&mut rng); | ||
| } | ||
| #[test] | ||
| fn incremental_writes() { | ||
| let mut rng = rand::thread_rng(); | ||
| let mut orig_data = Vec::<u8>::new(); | ||
| let mut normal_encoded = String::new(); | ||
| let size = 5_000; | ||
| for _ in 0..size { | ||
| orig_data.clear(); | ||
| normal_encoded.clear(); | ||
| orig_data.resize(size, 0); | ||
| rng.fill(&mut orig_data[..]); | ||
| let engine = random_engine(&mut rng); | ||
| engine.encode_string(&orig_data, &mut normal_encoded); | ||
| let mut stream_encoder = EncoderStringWriter::new(&engine); | ||
| // write small nibbles of data | ||
| let mut offset = 0; | ||
| while offset < size { | ||
| let nibble_size = cmp::min(rng.gen_range(0..=64), size - offset); | ||
| let len = stream_encoder | ||
| .write(&orig_data[offset..offset + nibble_size]) | ||
| .unwrap(); | ||
| offset += len; | ||
| } | ||
| let stream_encoded = stream_encoder.into_inner(); | ||
| assert_eq!(normal_encoded, stream_encoded); | ||
| } | ||
| } | ||
| } |
@@ -361,3 +361,3 @@ use std::io::{Cursor, Write}; | ||
| io::ErrorKind::Interrupted => continue, | ||
| _ => Err(e).unwrap(), // bail | ||
| _ => panic!("{:?}", e), // bail | ||
| }, | ||
@@ -364,0 +364,0 @@ } |
Sorry, the diff of this file is not supported yet