diff -Nru rust-base64-0.10.1/benches/benchmarks.rs rust-base64-0.12.1/benches/benchmarks.rs --- rust-base64-0.10.1/benches/benchmarks.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/benches/benchmarks.rs 2020-04-29 23:19:11.000000000 +0000 @@ -11,7 +11,7 @@ use criterion::{black_box, Bencher, Criterion, ParameterizedBenchmark, Throughput}; use rand::{FromEntropy, Rng}; -use std::io::Write; +use std::io::{self, Read, Write}; const TEST_CONFIG: Config = base64::STANDARD; @@ -52,6 +52,24 @@ }); } +fn do_decode_bench_stream(b: &mut Bencher, &size: &usize) { + let mut v: Vec = Vec::with_capacity(size * 3 / 4); + fill(&mut v); + let encoded = encode(&v); + + let mut buf = Vec::new(); + buf.resize(size, 0); + buf.truncate(0); + + b.iter(|| { + let mut cursor = io::Cursor::new(&encoded[..]); + let mut decoder = base64::read::DecoderReader::new(&mut cursor, TEST_CONFIG); + decoder.read_to_end(&mut buf).unwrap(); + buf.clear(); + black_box(&buf); + }); +} + fn do_encode_bench(b: &mut Bencher, &size: &usize) { let mut v: Vec = Vec::with_capacity(size); fill(&mut v); @@ -124,7 +142,7 @@ ParameterizedBenchmark::new("encode", do_encode_bench, byte_sizes.iter().cloned()) .warm_up_time(std::time::Duration::from_millis(500)) .measurement_time(std::time::Duration::from_secs(3)) - .throughput(|s| Throughput::Bytes(*s as u32)) + .throughput(|s| Throughput::Bytes(*s as u64)) .with_function("encode_display", do_encode_bench_display) .with_function("encode_reuse_buf", do_encode_bench_reuse_buf) .with_function("encode_slice", do_encode_bench_slice) @@ -135,9 +153,10 @@ ParameterizedBenchmark::new("decode", do_decode_bench, byte_sizes.iter().cloned()) .warm_up_time(std::time::Duration::from_millis(500)) .measurement_time(std::time::Duration::from_secs(3)) - .throughput(|s| Throughput::Bytes(*s as u32)) + .throughput(|s| Throughput::Bytes(*s as u64)) .with_function("decode_reuse_buf", do_decode_bench_reuse_buf) .with_function("decode_slice", do_decode_bench_slice) + .with_function("decode_stream", do_decode_bench_stream) } fn bench(c: &mut Criterion) { diff -Nru rust-base64-0.10.1/Cargo.lock rust-base64-0.12.1/Cargo.lock --- rust-base64-0.10.1/Cargo.lock 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/Cargo.lock 2020-05-06 14:26:38.000000000 +0000 @@ -0,0 +1,647 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "arrayvec" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.12.1" +dependencies = [ + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bstr" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion-plot" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "doc-comment" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memoffset" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xoshiro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-automata" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tinytemplate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" +"checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" +"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" +"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" +"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" +"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" +"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" +"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154" +"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff -Nru rust-base64-0.10.1/Cargo.toml rust-base64-0.12.1/Cargo.toml --- rust-base64-0.10.1/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/Cargo.toml 2020-05-06 14:26:38.000000000 +0000 @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,26 +11,33 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "base64" -version = "0.10.1" +version = "0.12.1" authors = ["Alice Maz ", "Marshall Pierce "] description = "encodes and decodes base64 as bytes or utf8" -documentation = "https://github.com/alicemaz/rust-base64/blob/master/README.md" +documentation = "https://docs.rs/base64" readme = "README.md" -keywords = ["base64", "utf8", "encode", "decode"] +keywords = ["base64", "utf8", "encode", "decode", "no_std"] categories = ["encoding"] license = "MIT/Apache-2.0" -repository = "https://github.com/alicemaz/rust-base64" +repository = "https://github.com/marshallpierce/rust-base64" [profile.bench] debug = true [[bench]] name = "benchmarks" harness = false -[dependencies.byteorder] -version = "1.2.6" [dev-dependencies.criterion] -version = "0.2" +version = "0.3" + +[dev-dependencies.doc-comment] +version = "0.3" [dev-dependencies.rand] version = "0.6.1" + +[features] +alloc = [] +default = ["std"] +std = [] diff -Nru rust-base64-0.10.1/Cargo.toml.orig rust-base64-0.12.1/Cargo.toml.orig --- rust-base64-0.10.1/Cargo.toml.orig 2019-01-25 03:11:16.000000000 +0000 +++ rust-base64-0.12.1/Cargo.toml.orig 2020-05-06 14:24:43.000000000 +0000 @@ -1,25 +1,29 @@ [package] name = "base64" -version = "0.10.1" +version = "0.12.1" authors = ["Alice Maz ", "Marshall Pierce "] description = "encodes and decodes base64 as bytes or utf8" -repository = "https://github.com/alicemaz/rust-base64" -documentation = "https://github.com/alicemaz/rust-base64/blob/master/README.md" +repository = "https://github.com/marshallpierce/rust-base64" +documentation = "https://docs.rs/base64" readme = "README.md" -keywords = ["base64", "utf8", "encode", "decode"] +keywords = ["base64", "utf8", "encode", "decode", "no_std"] categories = ["encoding"] license = "MIT/Apache-2.0" +edition = "2018" [[bench]] name = "benchmarks" harness = false -[dependencies] -byteorder = "1.2.6" - [dev-dependencies] -criterion = "0.2" +criterion = "0.3" rand = "0.6.1" +doc-comment = "0.3" + +[features] +default = ["std"] +alloc = [] +std = [] [profile.bench] # Useful for better disassembly when using `perf record` and `perf annotate` diff -Nru rust-base64-0.10.1/.cargo_vcs_info.json rust-base64-0.12.1/.cargo_vcs_info.json --- rust-base64-0.10.1/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/.cargo_vcs_info.json 2020-05-06 14:26:38.000000000 +0000 @@ -1,5 +1,5 @@ { "git": { - "sha1": "6dc5dd724de381a8985e0fb3b4cfdb845b872996" + "sha1": "0dc82f9dbffb94703bf43d73cc5edcab116243e1" } } diff -Nru rust-base64-0.10.1/debian/cargo-checksum.json rust-base64-0.12.1/debian/cargo-checksum.json --- rust-base64-0.10.1/debian/cargo-checksum.json 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/cargo-checksum.json 2020-05-10 14:13:19.000000000 +0000 @@ -1 +1 @@ -{"package":"0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e","files":{}} +{"package":"53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42","files":{}} diff -Nru rust-base64-0.10.1/debian/changelog rust-base64-0.12.1/debian/changelog --- rust-base64-0.10.1/debian/changelog 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/changelog 2020-05-10 14:13:19.000000000 +0000 @@ -1,3 +1,16 @@ +rust-base64 (0.12.1-1) unstable; urgency=medium + + * Team upload. + * Package base64 0.12.1 from crates.io using debcargo 2.4.2 + + -- Sylvestre Ledru Sun, 10 May 2020 16:13:19 +0200 + +rust-base64 (0.11.0-1) unstable; urgency=medium + + * Package base64 0.11.0 from crates.io using debcargo 2.4.0 + + -- kpcyrd Tue, 31 Dec 2019 02:23:36 +0100 + rust-base64 (0.10.1-1) unstable; urgency=medium * Team upload. diff -Nru rust-base64-0.10.1/debian/control rust-base64-0.12.1/debian/control --- rust-base64-0.10.1/debian/control 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/control 2020-05-10 14:13:19.000000000 +0000 @@ -2,16 +2,15 @@ Section: rust Priority: optional Build-Depends: debhelper (>= 11), - dh-cargo (>= 15), + dh-cargo (>= 18), cargo:native , rustc:native , - libstd-rust-dev , - librust-byteorder-1+default-dev (>= 1.2.6-~~) + libstd-rust-dev Maintainer: Debian Rust Maintainers Uploaders: kpcyrd , Andrej Shadura -Standards-Version: 4.2.0 +Standards-Version: 4.4.1 Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/base64] Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/base64 @@ -19,16 +18,23 @@ Architecture: any Multi-Arch: same Depends: - ${misc:Depends}, - librust-byteorder-1+default-dev (>= 1.2.6-~~) + ${misc:Depends} Provides: + librust-base64+alloc-dev (= ${binary:Version}), librust-base64+default-dev (= ${binary:Version}), + librust-base64+std-dev (= ${binary:Version}), librust-base64-0-dev (= ${binary:Version}), + librust-base64-0+alloc-dev (= ${binary:Version}), librust-base64-0+default-dev (= ${binary:Version}), - librust-base64-0.10-dev (= ${binary:Version}), - librust-base64-0.10+default-dev (= ${binary:Version}), - librust-base64-0.10.1-dev (= ${binary:Version}), - librust-base64-0.10.1+default-dev (= ${binary:Version}) + librust-base64-0+std-dev (= ${binary:Version}), + librust-base64-0.12-dev (= ${binary:Version}), + librust-base64-0.12+alloc-dev (= ${binary:Version}), + librust-base64-0.12+default-dev (= ${binary:Version}), + librust-base64-0.12+std-dev (= ${binary:Version}), + librust-base64-0.12.1-dev (= ${binary:Version}), + librust-base64-0.12.1+alloc-dev (= ${binary:Version}), + librust-base64-0.12.1+default-dev (= ${binary:Version}), + librust-base64-0.12.1+std-dev (= ${binary:Version}) Description: Encodes and decodes base64 as bytes or utf8 - Rust source code This package contains the source for the Rust base64 crate, packaged by debcargo for use with cargo and dh-cargo. diff -Nru rust-base64-0.10.1/debian/copyright rust-base64-0.12.1/debian/copyright --- rust-base64-0.10.1/debian/copyright 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/copyright 2020-05-10 14:13:19.000000000 +0000 @@ -3,7 +3,7 @@ Upstream-Contact: Alice Maz Marshall Pierce -Source: https://github.com/alicemaz/rust-base64 +Source: https://github.com/marshallpierce/rust-base64 Files: * Copyright: diff -Nru rust-base64-0.10.1/debian/copyright.debcargo.hint rust-base64-0.12.1/debian/copyright.debcargo.hint --- rust-base64-0.10.1/debian/copyright.debcargo.hint 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/copyright.debcargo.hint 2020-05-10 14:13:19.000000000 +0000 @@ -3,7 +3,7 @@ Upstream-Contact: Alice Maz Marshall Pierce -Source: https://github.com/alicemaz/rust-base64 +Source: https://github.com/marshallpierce/rust-base64 Files: * Copyright: @@ -25,9 +25,9 @@ Files: debian/* Copyright: - 2018-2019 Debian Rust Maintainers - 2018-2019 kpcyrd - 2018-2019 Andrej Shadura + 2018-2020 Debian Rust Maintainers + 2018-2020 kpcyrd + 2018-2020 Andrej Shadura License: MIT or Apache-2.0 License: Apache-2.0 diff -Nru rust-base64-0.10.1/debian/tests/control rust-base64-0.12.1/debian/tests/control --- rust-base64-0.10.1/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/debian/tests/control 2020-05-10 14:13:19.000000000 +0000 @@ -0,0 +1,9 @@ +Test-Command: /usr/share/cargo/bin/cargo-auto-test base64 0.12.1 --all-targets --all-features +Features: test-name=@ +Depends: dh-cargo (>= 18), librust-criterion-0.3+default-dev, librust-doc-comment-0.3+default-dev, librust-rand-0.6+default-dev (>= 0.6.1-~~), @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test base64 0.12.1 --all-targets --no-default-features +Features: test-name=librust-base64-dev +Depends: dh-cargo (>= 18), librust-criterion-0.3+default-dev, librust-doc-comment-0.3+default-dev, librust-rand-0.6+default-dev (>= 0.6.1-~~), @ +Restrictions: allow-stderr, skip-not-installable diff -Nru rust-base64-0.10.1/debian/watch rust-base64-0.12.1/debian/watch --- rust-base64-0.10.1/debian/watch 2019-07-20 19:18:07.000000000 +0000 +++ rust-base64-0.12.1/debian/watch 2020-05-10 14:13:19.000000000 +0000 @@ -2,4 +2,3 @@ opts=filenamemangle=s/.*\/(.*)\/download/base64-$1\.tar\.gz/g,\ uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/base64 .*/crates/base64/@ANY_VERSION@/download - diff -Nru rust-base64-0.10.1/examples/make_tables.rs rust-base64-0.12.1/examples/make_tables.rs --- rust-base64-0.10.1/examples/make_tables.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/examples/make_tables.rs 2020-05-06 14:23:29.000000000 +0000 @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::iter::Iterator; fn main() { @@ -26,7 +26,7 @@ .chain(0x30..0x3A) // - .chain(0x2D..0x2E) - // _s + // _ .chain(0x5F..0x60) .collect(); print_encode_table(&url_alphabet, "URL_SAFE_ENCODE", 0); @@ -41,12 +41,39 @@ .collect(); print_encode_table(&crypt_alphabet, "CRYPT_ENCODE", 0); print_decode_table(&crypt_alphabet, "CRYPT_DECODE", 0); + + // ./ + let bcrypt_alphabet: Vec = (b'.'..(b'/' + 1)) + // A-Z + .chain(b'A'..(b'Z' + 1)) + // a-z + .chain(b'a'..(b'z' + 1)) + // 0-9 + .chain(b'0'..(b'9' + 1)) + .collect(); + print_encode_table(&bcrypt_alphabet, "BCRYPT_ENCODE", 0); + print_decode_table(&bcrypt_alphabet, "BCRYPT_DECODE", 0); + + // A-Z + let imap_alphabet: Vec = (0x41..0x5B) + // a-z + .chain(0x61..0x7B) + // 0-9 + .chain(0x30..0x3A) + // + + .chain(0x2B..0x2C) + // , + .chain(0x2C..0x2D) + .collect(); + print_encode_table(&imap_alphabet, "IMAP_MUTF7_ENCODE", 0); + print_decode_table(&imap_alphabet, "IMAP_MUTF7_DECODE", 0); } fn print_encode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) { - println!("#[cfg_attr(rustfmt, rustfmt_skip)]"); + check_alphabet(alphabet); + println!("#[rustfmt::skip]"); println!( - "{:width$}pub const {}: &'static [u8; 64] = &[", + "{:width$}pub const {}: &[u8; 64] = &[", "", const_name, width = indent_depth @@ -69,6 +96,7 @@ } fn print_decode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) { + check_alphabet(alphabet); // map of alphabet bytes to 6-bit morsels let mut input_to_morsel = HashMap::::new(); @@ -78,9 +106,9 @@ let _ = input_to_morsel.insert(*ascii_byte, morsel as u8); } - println!("#[cfg_attr(rustfmt, rustfmt_skip)]"); + println!("#[rustfmt::skip]"); println!( - "{:width$}pub const {}: &'static [u8; 256] = &[", + "{:width$}pub const {}: &[u8; 256] = &[", "", const_name, width = indent_depth @@ -114,3 +142,10 @@ } println!("{:width$}];", "", width = indent_depth); } + +fn check_alphabet(alphabet: &[u8]) { + assert_eq!(64, alphabet.len()); + let mut set: HashSet = HashSet::new(); + set.extend(alphabet); + assert_eq!(64, set.len()); +} diff -Nru rust-base64-0.10.1/README.md rust-base64-0.12.1/README.md --- rust-base64-0.10.1/README.md 2019-01-25 02:49:33.000000000 +0000 +++ rust-base64-0.12.1/README.md 2020-04-29 23:19:11.000000000 +0000 @@ -1,7 +1,7 @@ [base64](https://crates.io/crates/base64) === -[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64) [![Build](https://travis-ci.org/alicemaz/rust-base64.svg?branch=master)](https://travis-ci.org/alicemaz/rust-base64) [![codecov](https://codecov.io/gh/alicemaz/rust-base64/branch/master/graph/badge.svg)](https://codecov.io/gh/alicemaz/rust-base64) +[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64) [![Build](https://travis-ci.org/marshallpierce/rust-base64.svg?branch=master)](https://travis-ci.org/marshallpierce/rust-base64) [![codecov](https://codecov.io/gh/marshallpierce/rust-base64/branch/master/graph/badge.svg)](https://codecov.io/gh/marshallpierce/rust-base64) [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) @@ -9,6 +9,8 @@ It's base64. What more could anyone want? +This library's goals are to be *correct* and *fast*. It's thoroughly tested and widely used. It exposes functionality at multiple levels of abstraction so you can choose the level of convenience vs performance that you want, e.g. `decode_config_slice` decodes into an existing `&mut [u8]` and is pretty fast (2.6GiB/s for a 3 KiB input), whereas `decode_config` allocates a new `Vec` and returns it, which might be more convenient in some cases, but is slower (although still fast enough for almost any purpose) at 2.1 GiB/s. + Example --- @@ -31,23 +33,28 @@ Rust version compatibility --- -The minimum required Rust version is 1.27.2. +The minimum required Rust version is 1.34.0. Developing --- Benchmarks are in `benches/`. Running them requires nightly rust, but `rustup` makes it easy: -``` +```bash rustup run nightly cargo bench ``` Decoding is aided by some pre-calculated tables, which are generated by: -``` +```bash cargo run --example make_tables > src/tables.rs.tmp && mv src/tables.rs.tmp src/tables.rs ``` +no_std +--- + +This crate supports no_std. By default the crate targets std via the `std` feature. You can deactivate the `default-features` to target core instead. In that case you lose out on all the functionality revolving around `std::io`, `std::error::Error` and heap allocations. There is an additional `alloc` feature that you can activate to bring back the support for heap allocations. + Profiling --- @@ -55,19 +62,19 @@ Run the benchmark binary with `perf` (shown here filtering to one particular benchmark, which will make the results easier to read). `perf` is only available to the root user on most systems as it fiddles with event counters in your CPU, so use `sudo`. We need to run the actual benchmark binary, hence the path into `target`. You can see the actual full path with `rustup run nightly cargo bench -v`; it will print out the commands it runs. If you use the exact path that `bench` outputs, make sure you get the one that's for the benchmarks, not the tests. You may also want to `cargo clean` so you have only one `benchmarks-` binary (they tend to accumulate). -``` +```bash sudo perf record target/release/deps/benchmarks-* --bench decode_10mib_reuse ``` Then analyze the results, again with perf: -``` +```bash sudo perf annotate -l ``` You'll see a bunch of interleaved rust source and assembly like this. The section with `lib.rs:327` is telling us that 4.02% of samples saw the `movzbl` aka bit shift as the active instruction. However, this percentage is not as exact as it seems due to a phenomenon called *skid*. Basically, a consequence of how fancy modern CPUs are is that this sort of instruction profiling is inherently inaccurate, especially in branch-heavy code. -``` +```text lib.rs:322 0.70 : 10698: mov %rdi,%rax 2.82 : 1069b: shr $0x38,%rax : if morsel == decode_tables::INVALID_VALUE { @@ -93,10 +100,11 @@ This uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). See `fuzz/fuzzers` for the available fuzzing scripts. To run, use an invocation like these: -``` +```bash cargo +nightly fuzz run roundtrip cargo +nightly fuzz run roundtrip_no_pad cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240 +cargo +nightly fuzz run decode_random ``` diff -Nru rust-base64-0.10.1/RELEASE-NOTES.md rust-base64-0.12.1/RELEASE-NOTES.md --- rust-base64-0.10.1/RELEASE-NOTES.md 2019-01-25 03:10:51.000000000 +0000 +++ rust-base64-0.12.1/RELEASE-NOTES.md 2020-05-06 14:24:22.000000000 +0000 @@ -1,11 +1,22 @@ -# Next +# 0.12.1 -- TBD +- Add `Bcrypt` alphabet + +# 0.12.0 + +- A `Read` implementation (`DecoderReader`) to let users transparently decoded data from a b64 input source +- IMAP's modified b64 alphabet +- Relaxed type restrictions to just `AsRef<[ut8]>` for main `encode*`/`decode*` functions +- A minor performance improvement in encoding + +# 0.11.0 +- Minimum rust version 1.34.0 +- `no_std` is now supported via the two new features `alloc` and `std`. # 0.10.1 - Minimum rust version 1.27.2 -- Fix bug in streaming encoding ([#90](https://github.com/alicemaz/rust-base64/pull/90)): if the underlying writer didn't write all the bytes given to it, the remaining bytes would not be retried later. See the docs on `EncoderWriter::write`. +- Fix bug in streaming encoding ([#90](https://github.com/marshallpierce/rust-base64/pull/90)): if the underlying writer didn't write all the bytes given to it, the remaining bytes would not be retried later. See the docs on `EncoderWriter::write`. - Make it configurable whether or not to return an error when decoding detects excess trailing bits. # 0.10.0 diff -Nru rust-base64-0.10.1/src/chunked_encoder.rs rust-base64-0.12.1/src/chunked_encoder.rs --- rust-base64-0.10.1/src/chunked_encoder.rs 2018-12-16 14:44:34.000000000 +0000 +++ rust-base64-0.12.1/src/chunked_encoder.rs 2020-04-29 23:19:11.000000000 +0000 @@ -1,6 +1,12 @@ -use encode::{add_padding, encode_to_slice}; -use std::{cmp, str}; -use Config; +use crate::{ + encode::{add_padding, encode_to_slice}, + Config, +}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use alloc::string::String; +use core::cmp; +#[cfg(any(feature = "alloc", feature = "std", test))] +use core::str; /// The output mechanism for ChunkedEncoder's encoded bytes. pub trait Sink { @@ -78,16 +84,19 @@ } // A really simple sink that just appends to a string +#[cfg(any(feature = "alloc", feature = "std", test))] pub(crate) struct StringSink<'a> { string: &'a mut String, } +#[cfg(any(feature = "alloc", feature = "std", test))] impl<'a> StringSink<'a> { pub(crate) fn new(s: &mut String) -> StringSink { StringSink { string: s } } } +#[cfg(any(feature = "alloc", feature = "std", test))] impl<'a> Sink for StringSink<'a> { type Error = (); @@ -100,14 +109,13 @@ #[cfg(test)] pub mod tests { - extern crate rand; - use super::*; - use tests::random_config; - use *; + use crate::{encode_config_buf, tests::random_config, CharacterSet, STANDARD}; - use self::rand::distributions::{Distribution, Uniform}; - use self::rand::{FromEntropy, Rng}; + use rand::{ + distributions::{Distribution, Uniform}, + FromEntropy, Rng, + }; #[test] fn chunked_encode_empty() { @@ -170,7 +178,7 @@ #[test] fn max_input_length_cant_use_extra_single_encoded_byte() { - let config = Config::new(CharacterSet::Standard, false); + let config = Config::new(crate::CharacterSet::Standard, false); assert_eq!(300, max_input_length(401, config)); } @@ -236,5 +244,4 @@ s } } - } diff -Nru rust-base64-0.10.1/src/decode.rs rust-base64-0.12.1/src/decode.rs --- rust-base64-0.10.1/src/decode.rs 2019-01-25 03:06:00.000000000 +0000 +++ rust-base64-0.12.1/src/decode.rs 2020-04-29 23:19:11.000000000 +0000 @@ -1,7 +1,12 @@ -use byteorder::{BigEndian, ByteOrder}; -use {tables, Config, STANDARD}; +use crate::{tables, Config}; -use std::{error, fmt, str}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use crate::STANDARD; +#[cfg(any(feature = "alloc", feature = "std", test))] +use alloc::vec::Vec; +use core::fmt; +#[cfg(any(feature = "std", test))] +use std::error; // decode logic operates on chunks of 8 input bytes without padding const INPUT_CHUNK_LEN: usize = 8; @@ -46,6 +51,7 @@ } } +#[cfg(any(feature = "std", test))] impl error::Error for DecodeError { fn description(&self) -> &str { match *self { @@ -55,7 +61,7 @@ } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -74,7 +80,8 @@ /// println!("{:?}", bytes); ///} ///``` -pub fn decode>(input: &T) -> Result, DecodeError> { +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn decode>(input: T) -> Result, DecodeError> { decode_config(input, STANDARD) } @@ -94,10 +101,8 @@ /// println!("{:?}", bytes_url); ///} ///``` -pub fn decode_config>( - input: &T, - config: Config, -) -> Result, DecodeError> { +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn decode_config>(input: T, config: Config) -> Result, DecodeError> { let mut buffer = Vec::::with_capacity(input.as_ref().len() * 4 / 3); decode_config_buf(input, config, &mut buffer).map(|_| buffer) @@ -124,8 +129,9 @@ /// println!("{:?}", buffer); ///} ///``` -pub fn decode_config_buf>( - input: &T, +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn decode_config_buf>( + input: T, config: Config, buffer: &mut Vec, ) -> Result<(), DecodeError> { @@ -160,19 +166,14 @@ /// input, rounded up, or in other words `(input_len + 3) / 4 * 3`. /// /// If the slice is not large enough, this will panic. -pub fn decode_config_slice>( - input: &T, +pub fn decode_config_slice>( + input: T, config: Config, output: &mut [u8], ) -> Result { let input_bytes = input.as_ref(); - decode_helper( - input_bytes, - num_chunks(input_bytes), - config, - output, - ) + decode_helper(input_bytes, num_chunks(input_bytes), config, output) } /// Return the number of input chunks (including a possibly partial final chunk) in the input @@ -340,16 +341,17 @@ if i % 4 < 2 { // Check for case #2. - let bad_padding_index = start_of_leftovers + if padding_bytes > 0 { - // If we've already seen padding, report the first padding index. - // This is to be consistent with the faster logic above: it will report an - // error on the first padding character (since it doesn't expect to see - // anything but actual encoded data). - first_padding_index - } else { - // haven't seen padding before, just use where we are now - i - }; + let bad_padding_index = start_of_leftovers + + if padding_bytes > 0 { + // If we've already seen padding, report the first padding index. + // This is to be consistent with the faster logic above: it will report an + // error on the first padding character (since it doesn't expect to see + // anything but actual encoded data). + first_padding_index + } else { + // haven't seen padding before, just use where we are now + i + }; return Err(DecodeError::InvalidByte(bad_padding_index, *b)); } @@ -423,6 +425,11 @@ Ok(output_index) } +#[inline] +fn write_u64(output: &mut [u8], value: u64) { + output[..8].copy_from_slice(&value.to_be_bytes()); +} + /// Decode 8 bytes of input into 6 bytes of output. 8 bytes of output will be written, but only the /// first 6 of those contain meaningful data. /// @@ -511,7 +518,7 @@ } accum |= (morsel as u64) << 16; - BigEndian::write_u64(output, accum); + write_u64(output, accum); Ok(()) } @@ -541,14 +548,17 @@ #[cfg(test)] mod tests { - extern crate rand; - use super::*; - use encode::encode_config_buf; - use tests::{assert_encode_sanity, random_config}; + use crate::{ + encode::encode_config_buf, + encode::encode_config_slice, + tests::{assert_encode_sanity, random_config}, + }; - use self::rand::distributions::{Distribution, Uniform}; - use self::rand::{FromEntropy, Rng}; + use rand::{ + distributions::{Distribution, Uniform}, + FromEntropy, Rng, + }; #[test] fn decode_chunk_precise_writes_only_6_bytes() { @@ -716,24 +726,35 @@ #[test] fn detect_invalid_last_symbol_two_bytes() { - let decode = |input, forgiving| { - decode_config(input, STANDARD.decode_allow_trailing_bits(forgiving)) - }; + let decode = + |input, forgiving| decode_config(input, STANDARD.decode_allow_trailing_bits(forgiving)); - // example from https://github.com/alicemaz/rust-base64/issues/75 + // example from https://github.com/marshallpierce/rust-base64/issues/75 assert!(decode("iYU=", false).is_ok()); // trailing 01 - assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'V')), decode("iYV=", false)); + assert_eq!( + Err(DecodeError::InvalidLastSymbol(2, b'V')), + decode("iYV=", false) + ); assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); // trailing 10 - assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'W')), decode("iYW=", false)); + assert_eq!( + Err(DecodeError::InvalidLastSymbol(2, b'W')), + decode("iYW=", false) + ); assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); // trailing 11 - assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'X')), decode("iYX=", false)); + assert_eq!( + Err(DecodeError::InvalidLastSymbol(2, b'X')), + decode("iYX=", false) + ); assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); // also works when there are 2 quads in the last block - assert_eq!(Err(DecodeError::InvalidLastSymbol(6, b'X')), decode("AAAAiYX=", false)); + assert_eq!( + Err(DecodeError::InvalidLastSymbol(6, b'X')), + decode("AAAAiYX=", false) + ); assert_eq!(Ok(vec![0, 0, 0, 137, 133]), decode("AAAAiYX=", true)); } @@ -767,7 +788,7 @@ for b2 in 0_u16..256 { bytes[1] = b2 as u8; let mut b64 = vec![0_u8; 4]; - assert_eq!(4, ::encode_config_slice(&bytes, STANDARD, &mut b64[..])); + assert_eq!(4, encode_config_slice(&bytes, STANDARD, &mut b64[..])); let mut v = ::std::vec::Vec::with_capacity(2); v.extend_from_slice(&bytes[..]); @@ -806,7 +827,7 @@ for b in 0_u16..256 { let mut b64 = vec![0_u8; 4]; - assert_eq!(4, ::encode_config_slice(&[b as u8], STANDARD, &mut b64[..])); + assert_eq!(4, encode_config_slice(&[b as u8], STANDARD, &mut b64[..])); let mut v = ::std::vec::Vec::with_capacity(1); v.push(b as u8); @@ -835,4 +856,12 @@ } } } + + #[test] + fn decode_imap() { + assert_eq!( + decode_config(b"+,,+", crate::IMAP_MUTF7), + decode_config(b"+//+", crate::STANDARD_NO_PAD) + ); + } } diff -Nru rust-base64-0.10.1/src/display.rs rust-base64-0.12.1/src/display.rs --- rust-base64-0.10.1/src/display.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/src/display.rs 2019-11-20 04:06:02.000000000 +0000 @@ -11,8 +11,8 @@ use super::chunked_encoder::ChunkedEncoder; use super::Config; -use std::fmt::{Display, Formatter}; -use std::{fmt, str}; +use core::fmt::{Display, Formatter}; +use core::{fmt, str}; /// A convenience wrapper for base64'ing bytes into a format string without heap allocation. pub struct Base64Display<'a> { diff -Nru rust-base64-0.10.1/src/encode.rs rust-base64-0.12.1/src/encode.rs --- rust-base64-0.10.1/src/encode.rs 2018-12-16 14:44:34.000000000 +0000 +++ rust-base64-0.12.1/src/encode.rs 2020-04-29 23:19:11.000000000 +0000 @@ -1,5 +1,9 @@ -use byteorder::{BigEndian, ByteOrder}; -use {Config, STANDARD}; +use crate::Config; +#[cfg(any(feature = "alloc", feature = "std", test))] +use crate::{chunked_encoder, STANDARD}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use alloc::{string::String, vec}; +use core::convert::TryInto; ///Encode arbitrary octets as base64. ///Returns a String. @@ -15,7 +19,8 @@ /// println!("{}", b64); ///} ///``` -pub fn encode>(input: &T) -> String { +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn encode>(input: T) -> String { encode_config(input, STANDARD) } @@ -35,14 +40,14 @@ /// println!("{}", b64_url); ///} ///``` -pub fn encode_config>(input: &T, config: Config) -> String { +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn encode_config>(input: T, config: Config) -> String { let mut buf = match encoded_size(input.as_ref().len(), config) { Some(n) => vec![0; n], None => panic!("integer overflow when calculating buffer size"), }; - let encoded_len = encode_config_slice(input.as_ref(), config, &mut buf[..]); - debug_assert_eq!(encoded_len, buf.len()); + encode_with_padding(input.as_ref(), config, buf.len(), &mut buf[..]); String::from_utf8(buf).expect("Invalid UTF8") } @@ -65,12 +70,13 @@ /// println!("{}", buf); ///} ///``` -pub fn encode_config_buf>(input: &T, config: Config, buf: &mut String) { +#[cfg(any(feature = "alloc", feature = "std", test))] +pub fn encode_config_buf>(input: T, config: Config, buf: &mut String) { let input_bytes = input.as_ref(); { - let mut sink = ::chunked_encoder::StringSink::new(buf); - let encoder = ::chunked_encoder::ChunkedEncoder::new(config); + let mut sink = chunked_encoder::StringSink::new(buf); + let encoder = chunked_encoder::ChunkedEncoder::new(config); encoder .encode(input_bytes, &mut sink) @@ -108,11 +114,7 @@ /// assert_eq!(s, base64::decode(&buf).unwrap().as_slice()); /// } /// ``` -pub fn encode_config_slice>( - input: &T, - config: Config, - output: &mut [u8], -) -> usize { +pub fn encode_config_slice>(input: T, config: Config, output: &mut [u8]) -> usize { let input_bytes = input.as_ref(); let encoded_size = encoded_size(input_bytes.len(), config) @@ -153,6 +155,11 @@ debug_assert_eq!(encoded_size, encoded_bytes); } +#[inline] +fn read_u64(s: &[u8]) -> u64 { + u64::from_be_bytes(s[..8].try_into().unwrap()) +} + /// Encode input bytes to utf8 base64 bytes. Does not pad. /// `output` must be long enough to hold the encoded `input` without padding. /// Returns the number of bytes written. @@ -183,7 +190,7 @@ // Plus, single-digit percentage performance differences might well be quite different // on different hardware. - let input_u64 = BigEndian::read_u64(&input_chunk[0..]); + let input_u64 = read_u64(&input_chunk[0..]); output_chunk[0] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; output_chunk[1] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; @@ -194,7 +201,7 @@ output_chunk[6] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; output_chunk[7] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - let input_u64 = BigEndian::read_u64(&input_chunk[6..]); + let input_u64 = read_u64(&input_chunk[6..]); output_chunk[8] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; output_chunk[9] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; @@ -205,7 +212,7 @@ output_chunk[14] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; output_chunk[15] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - let input_u64 = BigEndian::read_u64(&input_chunk[12..]); + let input_u64 = read_u64(&input_chunk[12..]); output_chunk[16] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; output_chunk[17] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; @@ -216,7 +223,7 @@ output_chunk[22] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; output_chunk[23] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - let input_u64 = BigEndian::read_u64(&input_chunk[18..]); + let input_u64 = read_u64(&input_chunk[18..]); output_chunk[24] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; output_chunk[25] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; @@ -258,9 +265,9 @@ if rem == 2 { output[output_index] = encode_table[(input[start_of_rem] >> 2) as usize]; - output[output_index + 1] = - encode_table[((input[start_of_rem] << 4 | input[start_of_rem + 1] >> 4) - & LOW_SIX_BITS_U8) as usize]; + output[output_index + 1] = encode_table[((input[start_of_rem] << 4 + | input[start_of_rem + 1] >> 4) + & LOW_SIX_BITS_U8) as usize]; output[output_index + 2] = encode_table[((input[start_of_rem + 1] << 2) & LOW_SIX_BITS_U8) as usize]; output_index += 3; @@ -314,15 +321,17 @@ #[cfg(test)] mod tests { - extern crate rand; - use super::*; - use decode::decode_config_buf; - use tests::{assert_encode_sanity, random_config}; - use {Config, STANDARD, URL_SAFE_NO_PAD}; + use crate::{ + decode::decode_config_buf, + tests::{assert_encode_sanity, random_config}, + Config, STANDARD, URL_SAFE_NO_PAD, + }; - use self::rand::distributions::{Distribution, Uniform}; - use self::rand::{FromEntropy, Rng}; + use rand::{ + distributions::{Distribution, Uniform}, + FromEntropy, Rng, + }; use std; use std::str; @@ -656,4 +665,11 @@ assert_eq!(encoded_len, encoded.len()); } + #[test] + fn encode_imap() { + assert_eq!( + encode_config(b"\xFB\xFF", crate::IMAP_MUTF7), + encode_config(b"\xFB\xFF", crate::STANDARD_NO_PAD).replace("/", ",") + ); + } } diff -Nru rust-base64-0.10.1/src/lib.rs rust-base64-0.12.1/src/lib.rs --- rust-base64-0.10.1/src/lib.rs 2019-01-25 03:08:11.000000000 +0000 +++ rust-base64-0.12.1/src/lib.rs 2020-05-06 14:15:36.000000000 +0000 @@ -43,13 +43,21 @@ //! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is //! valid, but excess padding is not.) Whitespace in the input is invalid. //! +//! # `Read` and `Write` +//! +//! To map a `Read` of b64 bytes to the decoded bytes, wrap a reader (file, network socket, etc) +//! with `base64::read::DecoderReader`. To write raw bytes and have them b64 encoded on the fly, +//! wrap a writer with `base64::write::EncoderWriter`. There is some performance overhead (15% or +//! so) because of the necessary buffer shuffling -- still fast enough that almost nobody cares. +//! Also, these implementations do not heap allocate. +//! //! # Panics //! //! If length calculations result in overflowing `usize`, a panic will result. //! //! The `_slice` flavors of encode or decode will panic if the provided output slice is too small, -#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))] #![deny( missing_docs, trivial_casts, @@ -58,22 +66,40 @@ unused_import_braces, unused_results, variant_size_differences, - warnings, - unsafe_code + warnings )] +#![forbid(unsafe_code)] +#![cfg_attr(not(any(feature = "std", test)), no_std)] -extern crate byteorder; +#[cfg(all(feature = "alloc", not(any(feature = "std", test))))] +extern crate alloc; +#[cfg(any(feature = "std", test))] +extern crate std as alloc; + +#[cfg(test)] +#[macro_use] +extern crate doc_comment; + +#[cfg(test)] +doctest!("../README.md"); mod chunked_encoder; pub mod display; +#[cfg(any(feature = "std", test))] +pub mod read; mod tables; +#[cfg(any(feature = "std", test))] pub mod write; mod encode; -pub use encode::{encode, encode_config, encode_config_buf, encode_config_slice}; +pub use crate::encode::encode_config_slice; +#[cfg(any(feature = "alloc", feature = "std", test))] +pub use crate::encode::{encode, encode_config, encode_config_buf}; mod decode; -pub use decode::{decode, decode_config, decode_config_buf, decode_config_slice, DecodeError}; +#[cfg(any(feature = "alloc", feature = "std", test))] +pub use crate::decode::{decode, decode_config, decode_config_buf}; +pub use crate::decode::{decode_config_slice, DecodeError}; #[cfg(test)] mod tests; @@ -93,6 +119,12 @@ /// /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses. Crypt, + /// The bcrypt character set (uses `./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`). + Bcrypt, + /// The character set used in IMAP-modified UTF-7 (uses `+` and `,`). + /// + /// See [RFC 3501](https://tools.ietf.org/html/rfc3501#section-5.1.3) + ImapMutf7, } impl CharacterSet { @@ -101,6 +133,8 @@ CharacterSet::Standard => tables::STANDARD_ENCODE, CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE, CharacterSet::Crypt => tables::CRYPT_ENCODE, + CharacterSet::Bcrypt => tables::BCRYPT_ENCODE, + CharacterSet::ImapMutf7 => tables::IMAP_MUTF7_ENCODE, } } @@ -109,6 +143,8 @@ CharacterSet::Standard => tables::STANDARD_DECODE, CharacterSet::UrlSafe => tables::URL_SAFE_DECODE, CharacterSet::Crypt => tables::CRYPT_DECODE, + CharacterSet::Bcrypt => tables::BCRYPT_DECODE, + CharacterSet::ImapMutf7 => tables::IMAP_MUTF7_DECODE, } } } @@ -127,7 +163,11 @@ impl Config { /// Create a new `Config`. pub fn new(char_set: CharacterSet, pad: bool) -> Config { - Config { char_set, pad, decode_allow_trailing_bits: false } + Config { + char_set, + pad, + decode_allow_trailing_bits: false, + } } /// Sets whether to pad output with `=` characters. @@ -140,7 +180,10 @@ /// This is useful when implementing /// [forgiving-base64 decode](https://infra.spec.whatwg.org/#forgiving-base64-decode). pub fn decode_allow_trailing_bits(self, allow: bool) -> Config { - Config { decode_allow_trailing_bits: allow, ..self } + Config { + decode_allow_trailing_bits: allow, + ..self + } } } @@ -178,3 +221,17 @@ pad: false, decode_allow_trailing_bits: false, }; + +/// Bcrypt character set +pub const BCRYPT: Config = Config { + char_set: CharacterSet::Bcrypt, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// IMAP modified UTF-7 requirements +pub const IMAP_MUTF7: Config = Config { + char_set: CharacterSet::ImapMutf7, + pad: false, + decode_allow_trailing_bits: false, +}; diff -Nru rust-base64-0.10.1/src/read/decoder.rs rust-base64-0.12.1/src/read/decoder.rs --- rust-base64-0.10.1/src/read/decoder.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/src/read/decoder.rs 2020-04-29 23:19:11.000000000 +0000 @@ -0,0 +1,282 @@ +use crate::{decode_config_slice, Config, DecodeError}; +use std::io::Read; +use std::{cmp, fmt, io}; + +// This should be large, but it has to fit on the stack. +pub(crate) const BUF_SIZE: usize = 1024; + +// 4 bytes of base64 data encode 3 bytes of raw data (modulo padding). +const BASE64_CHUNK_SIZE: usize = 4; +const DECODED_CHUNK_SIZE: usize = 3; + +/// A `Read` implementation that decodes base64 data read from an underlying reader. +/// +/// # Examples +/// +/// ``` +/// use std::io::Read; +/// use std::io::Cursor; +/// +/// // use a cursor as the simplest possible `Read` -- in real code this is probably a file, etc. +/// let mut wrapped_reader = Cursor::new(b"YXNkZg=="); +/// let mut decoder = base64::read::DecoderReader::new( +/// &mut wrapped_reader, base64::STANDARD); +/// +/// // handle errors as you normally would +/// let mut result = Vec::new(); +/// decoder.read_to_end(&mut result).unwrap(); +/// +/// assert_eq!(b"asdf", &result[..]); +/// +/// ``` +pub struct DecoderReader<'a, R: 'a + io::Read> { + config: Config, + /// Where b64 data is read from + r: &'a mut R, + + // Holds b64 data read from the delegate reader. + b64_buffer: [u8; BUF_SIZE], + // The start of the pending buffered data in b64_buffer. + b64_offset: usize, + // The amount of buffered b64 data. + b64_len: usize, + // Since the caller may provide us with a buffer of size 1 or 2 that's too small to copy a + // decoded chunk in to, we have to be able to hang on to a few decoded bytes. + // Technically we only need to hold 2 bytes but then we'd need a separate temporary buffer to + // decode 3 bytes into and then juggle copying one byte into the provided read buf and the rest + // into here, which seems like a lot of complexity for 1 extra byte of storage. + decoded_buffer: [u8; 3], + // index of start of decoded data + decoded_offset: usize, + // length of decoded data + decoded_len: usize, + // used to provide accurate offsets in errors + total_b64_decoded: usize, +} + +impl<'a, R: io::Read> fmt::Debug for DecoderReader<'a, R> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("DecoderReader") + .field("config", &self.config) + .field("b64_offset", &self.b64_offset) + .field("b64_len", &self.b64_len) + .field("decoded_buffer", &self.decoded_buffer) + .field("decoded_offset", &self.decoded_offset) + .field("decoded_len", &self.decoded_len) + .field("total_b64_decoded", &self.total_b64_decoded) + .finish() + } +} + +impl<'a, R: io::Read> DecoderReader<'a, R> { + /// Create a new decoder that will read from the provided reader `r`. + pub fn new(r: &'a mut R, config: Config) -> Self { + DecoderReader { + config, + r, + b64_buffer: [0; BUF_SIZE], + b64_offset: 0, + b64_len: 0, + decoded_buffer: [0; DECODED_CHUNK_SIZE], + decoded_offset: 0, + decoded_len: 0, + total_b64_decoded: 0, + } + } + + /// Write as much as possible of the decoded buffer into the target buffer. + /// Must only be called when there is something to write and space to write into. + /// Returns a Result with the number of (decoded) bytes copied. + fn flush_decoded_buf(&mut self, buf: &mut [u8]) -> io::Result { + debug_assert!(self.decoded_len > 0); + debug_assert!(buf.len() > 0); + + let copy_len = cmp::min(self.decoded_len, buf.len()); + debug_assert!(copy_len > 0); + debug_assert!(copy_len <= self.decoded_len); + + buf[..copy_len].copy_from_slice( + &self.decoded_buffer[self.decoded_offset..self.decoded_offset + copy_len], + ); + + self.decoded_offset += copy_len; + self.decoded_len -= copy_len; + + debug_assert!(self.decoded_len < DECODED_CHUNK_SIZE); + + Ok(copy_len) + } + + /// Read into the remaining space in the buffer after the current contents. + /// Must only be called when there is space to read into in the buffer. + /// Returns the number of bytes read. + fn read_from_delegate(&mut self) -> io::Result { + debug_assert!(self.b64_offset + self.b64_len < BUF_SIZE); + + let read = self + .r + .read(&mut self.b64_buffer[self.b64_offset + self.b64_len..])?; + self.b64_len += read; + + debug_assert!(self.b64_offset + self.b64_len <= BUF_SIZE); + + return Ok(read); + } + + /// Decode the requested number of bytes from the b64 buffer into the provided buffer. It's the + /// caller's responsibility to choose the number of b64 bytes to decode correctly. + /// + /// Returns a Result with the number of decoded bytes written to `buf`. + fn decode_to_buf(&mut self, num_bytes: usize, buf: &mut [u8]) -> io::Result { + debug_assert!(self.b64_len >= num_bytes); + debug_assert!(self.b64_offset + self.b64_len <= BUF_SIZE); + debug_assert!(buf.len() > 0); + + let decoded = decode_config_slice( + &self.b64_buffer[self.b64_offset..self.b64_offset + num_bytes], + self.config, + &mut buf[..], + ) + .map_err(|e| match e { + DecodeError::InvalidByte(offset, byte) => { + DecodeError::InvalidByte(self.total_b64_decoded + offset, byte) + } + DecodeError::InvalidLength => DecodeError::InvalidLength, + DecodeError::InvalidLastSymbol(offset, byte) => { + DecodeError::InvalidLastSymbol(self.total_b64_decoded + offset, byte) + } + }) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + self.total_b64_decoded += num_bytes; + self.b64_offset += num_bytes; + self.b64_len -= num_bytes; + + debug_assert!(self.b64_offset + self.b64_len <= BUF_SIZE); + + Ok(decoded) + } +} + +impl<'a, R: Read> Read for DecoderReader<'a, R> { + /// Decode input from the wrapped reader. + /// + /// Under non-error circumstances, this returns `Ok` with the value being the number of bytes + /// written in `buf`. + /// + /// Where possible, this function buffers base64 to minimize the number of read() calls to the + /// delegate reader. + /// + /// # Errors + /// + /// Any errors emitted by the delegate reader are returned. Decoding errors due to invalid + /// base64 are also possible, and will have `io::ErrorKind::InvalidData`. + fn read(&mut self, buf: &mut [u8]) -> io::Result { + if buf.len() == 0 { + return Ok(0); + } + + // offset == BUF_SIZE when we copied it all last time + debug_assert!(self.b64_offset <= BUF_SIZE); + debug_assert!(self.b64_offset + self.b64_len <= BUF_SIZE); + debug_assert!(if self.b64_offset == BUF_SIZE { + self.b64_len == 0 + } else { + self.b64_len <= BUF_SIZE + }); + + debug_assert!(if self.decoded_len == 0 { + // can be = when we were able to copy the complete chunk + self.decoded_offset <= DECODED_CHUNK_SIZE + } else { + self.decoded_offset < DECODED_CHUNK_SIZE + }); + + // We shouldn't ever decode into here when we can't immediately write at least one byte into + // the provided buf, so the effective length should only be 3 momentarily between when we + // decode and when we copy into the target buffer. + debug_assert!(self.decoded_len < DECODED_CHUNK_SIZE); + debug_assert!(self.decoded_len + self.decoded_offset <= DECODED_CHUNK_SIZE); + + if self.decoded_len > 0 { + // we have a few leftover decoded bytes; flush that rather than pull in more b64 + self.flush_decoded_buf(buf) + } else { + let mut at_eof = false; + while self.b64_len < BASE64_CHUNK_SIZE { + // Work around lack of copy_within, which is only present in 1.37 + // Copy any bytes we have to the start of the buffer. + // We know we have < 1 chunk, so we can use a tiny tmp buffer. + let mut memmove_buf = [0_u8; BASE64_CHUNK_SIZE]; + memmove_buf[..self.b64_len].copy_from_slice( + &self.b64_buffer[self.b64_offset..self.b64_offset + self.b64_len], + ); + self.b64_buffer[0..self.b64_len].copy_from_slice(&memmove_buf[..self.b64_len]); + self.b64_offset = 0; + + // then fill in more data + let read = self.read_from_delegate()?; + if read == 0 { + // we never pass in an empty buf, so 0 => we've hit EOF + at_eof = true; + break; + } + } + + if self.b64_len == 0 { + debug_assert!(at_eof); + // we must be at EOF, and we have no data left to decode + return Ok(0); + }; + + debug_assert!(if at_eof { + // if we are at eof, we may not have a complete chunk + self.b64_len > 0 + } else { + // otherwise, we must have at least one chunk + self.b64_len >= BASE64_CHUNK_SIZE + }); + + debug_assert_eq!(0, self.decoded_len); + + if buf.len() < DECODED_CHUNK_SIZE { + // caller requested an annoyingly short read + // have to write to a tmp buf first to avoid double mutable borrow + let mut decoded_chunk = [0_u8; DECODED_CHUNK_SIZE]; + // if we are at eof, could have less than BASE64_CHUNK_SIZE, in which case we have + // to assume that these last few tokens are, in fact, valid (i.e. must be 2-4 b64 + // tokens, not 1, since 1 token can't decode to 1 byte). + let to_decode = cmp::min(self.b64_len, BASE64_CHUNK_SIZE); + + let decoded = self.decode_to_buf(to_decode, &mut decoded_chunk[..])?; + self.decoded_buffer[..decoded].copy_from_slice(&decoded_chunk[..decoded]); + + self.decoded_offset = 0; + self.decoded_len = decoded; + + // can be less than 3 on last block due to padding + debug_assert!(decoded <= 3); + + self.flush_decoded_buf(buf) + } else { + let b64_bytes_that_can_decode_into_buf = (buf.len() / DECODED_CHUNK_SIZE) + .checked_mul(BASE64_CHUNK_SIZE) + .expect("too many chunks"); + debug_assert!(b64_bytes_that_can_decode_into_buf >= BASE64_CHUNK_SIZE); + + let b64_bytes_available_to_decode = if at_eof { + self.b64_len + } else { + // only use complete chunks + self.b64_len - self.b64_len % 4 + }; + + let actual_decode_len = cmp::min( + b64_bytes_that_can_decode_into_buf, + b64_bytes_available_to_decode, + ); + self.decode_to_buf(actual_decode_len, buf) + } + } + } +} diff -Nru rust-base64-0.10.1/src/read/decoder_tests.rs rust-base64-0.12.1/src/read/decoder_tests.rs --- rust-base64-0.10.1/src/read/decoder_tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/src/read/decoder_tests.rs 2020-04-29 23:19:11.000000000 +0000 @@ -0,0 +1,335 @@ +use std::io::{self, Read}; + +use rand::{Rng, RngCore}; +use std::{cmp, iter}; + +use super::decoder::{DecoderReader, BUF_SIZE}; +use crate::encode::encode_config_buf; +use crate::tests::random_config; +use crate::{decode_config_buf, DecodeError, STANDARD}; + +#[test] +fn simple() { + let tests: &[(&[u8], &[u8])] = &[ + (&b"0"[..], &b"MA=="[..]), + (b"01", b"MDE="), + (b"012", b"MDEy"), + (b"0123", b"MDEyMw=="), + (b"01234", b"MDEyMzQ="), + (b"012345", b"MDEyMzQ1"), + (b"0123456", b"MDEyMzQ1Ng=="), + (b"01234567", b"MDEyMzQ1Njc="), + (b"012345678", b"MDEyMzQ1Njc4"), + (b"0123456789", b"MDEyMzQ1Njc4OQ=="), + ][..]; + + for (text_expected, base64data) in tests.iter() { + // Read n bytes at a time. + for n in 1..base64data.len() + 1 { + let mut wrapped_reader = io::Cursor::new(base64data); + let mut decoder = DecoderReader::new(&mut wrapped_reader, STANDARD); + + // handle errors as you normally would + let mut text_got = Vec::new(); + let mut buffer = vec![0u8; n]; + while let Ok(read) = decoder.read(&mut buffer[..]) { + if read == 0 { + break; + } + text_got.extend_from_slice(&buffer[..read]); + } + + assert_eq!( + text_got, + *text_expected, + "\nGot: {}\nExpected: {}", + String::from_utf8_lossy(&text_got[..]), + String::from_utf8_lossy(text_expected) + ); + } + } +} + +// Make sure we error out on trailing junk. +#[test] +fn trailing_junk() { + let tests: &[&[u8]] = &[&b"MDEyMzQ1Njc4*!@#$%^&"[..], b"MDEyMzQ1Njc4OQ== "][..]; + + for base64data in tests.iter() { + // Read n bytes at a time. + for n in 1..base64data.len() + 1 { + let mut wrapped_reader = io::Cursor::new(base64data); + let mut decoder = DecoderReader::new(&mut wrapped_reader, STANDARD); + + // handle errors as you normally would + let mut buffer = vec![0u8; n]; + let mut saw_error = false; + loop { + match decoder.read(&mut buffer[..]) { + Err(_) => { + saw_error = true; + break; + } + Ok(read) if read == 0 => break, + Ok(_) => (), + } + } + + assert!(saw_error); + } + } +} + +#[test] +fn handles_short_read_from_delegate() { + let mut rng = rand::thread_rng(); + let mut bytes = Vec::new(); + let mut b64 = String::new(); + let mut decoded = Vec::new(); + + for _ in 0..10_000 { + bytes.clear(); + b64.clear(); + decoded.clear(); + + let size = rng.gen_range(0, 10 * BUF_SIZE); + bytes.extend(iter::repeat(0).take(size)); + bytes.truncate(size); + rng.fill_bytes(&mut bytes[..size]); + assert_eq!(size, bytes.len()); + + let config = random_config(&mut rng); + encode_config_buf(&bytes[..], config, &mut b64); + + let mut wrapped_reader = io::Cursor::new(b64.as_bytes()); + let mut short_reader = RandomShortRead { + delegate: &mut wrapped_reader, + rng: &mut rng, + }; + + let mut decoder = DecoderReader::new(&mut short_reader, config); + + let decoded_len = decoder.read_to_end(&mut decoded).unwrap(); + assert_eq!(size, decoded_len); + assert_eq!(&bytes[..], &decoded[..]); + } +} + +#[test] +fn read_in_short_increments() { + let mut rng = rand::thread_rng(); + let mut bytes = Vec::new(); + let mut b64 = String::new(); + let mut decoded = Vec::new(); + + for _ in 0..10_000 { + bytes.clear(); + b64.clear(); + decoded.clear(); + + let size = rng.gen_range(0, 10 * BUF_SIZE); + bytes.extend(iter::repeat(0).take(size)); + // leave room to play around with larger buffers + decoded.extend(iter::repeat(0).take(size * 3)); + + rng.fill_bytes(&mut bytes[..]); + assert_eq!(size, bytes.len()); + + let config = random_config(&mut rng); + + encode_config_buf(&bytes[..], config, &mut b64); + + let mut wrapped_reader = io::Cursor::new(&b64[..]); + let mut decoder = DecoderReader::new(&mut wrapped_reader, config); + + consume_with_short_reads_and_validate(&mut rng, &bytes[..], &mut decoded, &mut decoder); + } +} + +#[test] +fn read_in_short_increments_with_short_delegate_reads() { + let mut rng = rand::thread_rng(); + let mut bytes = Vec::new(); + let mut b64 = String::new(); + let mut decoded = Vec::new(); + + for _ in 0..10_000 { + bytes.clear(); + b64.clear(); + decoded.clear(); + + let size = rng.gen_range(0, 10 * BUF_SIZE); + bytes.extend(iter::repeat(0).take(size)); + // leave room to play around with larger buffers + decoded.extend(iter::repeat(0).take(size * 3)); + + rng.fill_bytes(&mut bytes[..]); + assert_eq!(size, bytes.len()); + + let config = random_config(&mut rng); + + encode_config_buf(&bytes[..], config, &mut b64); + + let mut base_reader = io::Cursor::new(&b64[..]); + let mut decoder = DecoderReader::new(&mut base_reader, config); + let mut short_reader = RandomShortRead { + delegate: &mut decoder, + rng: &mut rand::thread_rng(), + }; + + consume_with_short_reads_and_validate(&mut rng, &bytes[..], &mut decoded, &mut short_reader) + } +} + +#[test] +fn reports_invalid_last_symbol_correctly() { + let mut rng = rand::thread_rng(); + let mut bytes = Vec::new(); + let mut b64 = String::new(); + let mut b64_bytes = Vec::new(); + let mut decoded = Vec::new(); + let mut bulk_decoded = Vec::new(); + + for _ in 0..1_000 { + bytes.clear(); + b64.clear(); + b64_bytes.clear(); + + let size = rng.gen_range(1, 10 * BUF_SIZE); + bytes.extend(iter::repeat(0).take(size)); + decoded.extend(iter::repeat(0).take(size)); + rng.fill_bytes(&mut bytes[..]); + assert_eq!(size, bytes.len()); + + let mut config = random_config(&mut rng); + // changing padding will cause invalid padding errors when we twiddle the last byte + config.pad = false; + + encode_config_buf(&bytes[..], config, &mut b64); + b64_bytes.extend(b64.bytes()); + assert_eq!(b64_bytes.len(), b64.len()); + + // change the last character to every possible symbol. Should behave the same as bulk + // decoding whether invalid or valid. + for &s1 in config.char_set.encode_table().iter() { + decoded.clear(); + bulk_decoded.clear(); + + // replace the last + *b64_bytes.last_mut().unwrap() = s1; + let bulk_res = decode_config_buf(&b64_bytes[..], config, &mut bulk_decoded); + + let mut wrapped_reader = io::Cursor::new(&b64_bytes[..]); + let mut decoder = DecoderReader::new(&mut wrapped_reader, config); + + let stream_res = decoder.read_to_end(&mut decoded).map(|_| ()).map_err(|e| { + e.into_inner() + .and_then(|e| e.downcast::().ok()) + }); + + assert_eq!(bulk_res.map_err(|e| Some(Box::new(e))), stream_res); + } + } +} + +#[test] +fn reports_invalid_byte_correctly() { + let mut rng = rand::thread_rng(); + let mut bytes = Vec::new(); + let mut b64 = String::new(); + let mut decoded = Vec::new(); + + for _ in 0..10_000 { + bytes.clear(); + b64.clear(); + decoded.clear(); + + let size = rng.gen_range(1, 10 * BUF_SIZE); + bytes.extend(iter::repeat(0).take(size)); + rng.fill_bytes(&mut bytes[..size]); + assert_eq!(size, bytes.len()); + + let config = random_config(&mut rng); + encode_config_buf(&bytes[..], config, &mut b64); + // replace one byte, somewhere, with '*', which is invalid + let bad_byte_pos = rng.gen_range(0, &b64.len()); + let mut b64_bytes = b64.bytes().collect::>(); + b64_bytes[bad_byte_pos] = b'*'; + + let mut wrapped_reader = io::Cursor::new(b64_bytes.clone()); + let mut decoder = DecoderReader::new(&mut wrapped_reader, config); + + // some gymnastics to avoid double-moving the io::Error, which is not Copy + let read_decode_err = decoder + .read_to_end(&mut decoded) + .map_err(|e| { + let kind = e.kind(); + let inner = e + .into_inner() + .and_then(|e| e.downcast::().ok()); + inner.map(|i| (*i, kind)) + }) + .err() + .and_then(|o| o); + + let mut bulk_buf = Vec::new(); + let bulk_decode_err = decode_config_buf(&b64_bytes[..], config, &mut bulk_buf).err(); + + // it's tricky to predict where the invalid data's offset will be since if it's in the last + // chunk it will be reported at the first padding location because it's treated as invalid + // padding. So, we just check that it's the same as it is for decoding all at once. + assert_eq!( + bulk_decode_err.map(|e| (e, io::ErrorKind::InvalidData)), + read_decode_err + ); + } +} + +fn consume_with_short_reads_and_validate( + rng: &mut rand::rngs::ThreadRng, + expected_bytes: &[u8], + decoded: &mut Vec, + short_reader: &mut R, +) -> () { + let mut total_read = 0_usize; + loop { + assert!( + total_read <= expected_bytes.len(), + "tr {} size {}", + total_read, + expected_bytes.len() + ); + if total_read == expected_bytes.len() { + assert_eq!(expected_bytes, &decoded[..total_read]); + // should be done + assert_eq!(0, short_reader.read(&mut decoded[..]).unwrap()); + // didn't write anything + assert_eq!(expected_bytes, &decoded[..total_read]); + + break; + } + let decode_len = rng.gen_range(1, cmp::max(2, expected_bytes.len() * 2)); + + let read = short_reader + .read(&mut decoded[total_read..total_read + decode_len]) + .unwrap(); + total_read += read; + } +} + +/// Limits how many bytes a reader will provide in each read call. +/// Useful for shaking out code that may work fine only with typical input sources that always fill +/// the buffer. +struct RandomShortRead<'a, 'b, R: io::Read, N: rand::Rng> { + delegate: &'b mut R, + rng: &'a mut N, +} + +impl<'a, 'b, R: io::Read, N: rand::Rng> io::Read for RandomShortRead<'a, 'b, R, N> { + fn read(&mut self, buf: &mut [u8]) -> Result { + // avoid 0 since it means EOF for non-empty buffers + let effective_len = cmp::min(self.rng.gen_range(1, 20), buf.len()); + + self.delegate.read(&mut buf[..effective_len]) + } +} diff -Nru rust-base64-0.10.1/src/read/mod.rs rust-base64-0.12.1/src/read/mod.rs --- rust-base64-0.10.1/src/read/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-base64-0.12.1/src/read/mod.rs 2020-04-29 23:19:11.000000000 +0000 @@ -0,0 +1,6 @@ +//! Implementations of `io::Read` to transparently decode base64. +mod decoder; +pub use self::decoder::DecoderReader; + +#[cfg(test)] +mod decoder_tests; diff -Nru rust-base64-0.10.1/src/tables.rs rust-base64-0.12.1/src/tables.rs --- rust-base64-0.10.1/src/tables.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/src/tables.rs 2020-05-06 14:23:41.000000000 +0000 @@ -1,5 +1,5 @@ pub const INVALID_VALUE: u8 = 255; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const STANDARD_ENCODE: &[u8; 64] = &[ 65, // input 0 (0x0) => 'A' (0x41) 66, // input 1 (0x1) => 'B' (0x42) @@ -66,7 +66,7 @@ 43, // input 62 (0x3E) => '+' (0x2B) 47, // input 63 (0x3F) => '/' (0x2F) ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const STANDARD_DECODE: &[u8; 256] = &[ INVALID_VALUE, // input 0 (0x0) INVALID_VALUE, // input 1 (0x1) @@ -325,7 +325,7 @@ INVALID_VALUE, // input 254 (0xFE) INVALID_VALUE, // input 255 (0xFF) ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const URL_SAFE_ENCODE: &[u8; 64] = &[ 65, // input 0 (0x0) => 'A' (0x41) 66, // input 1 (0x1) => 'B' (0x42) @@ -392,7 +392,7 @@ 45, // input 62 (0x3E) => '-' (0x2D) 95, // input 63 (0x3F) => '_' (0x5F) ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const URL_SAFE_DECODE: &[u8; 256] = &[ INVALID_VALUE, // input 0 (0x0) INVALID_VALUE, // input 1 (0x1) @@ -651,7 +651,7 @@ INVALID_VALUE, // input 254 (0xFE) INVALID_VALUE, // input 255 (0xFF) ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const CRYPT_ENCODE: &[u8; 64] = &[ 46, // input 0 (0x0) => '.' (0x2E) 47, // input 1 (0x1) => '/' (0x2F) @@ -718,7 +718,7 @@ 121, // input 62 (0x3E) => 'y' (0x79) 122, // input 63 (0x3F) => 'z' (0x7A) ]; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] pub const CRYPT_DECODE: &[u8; 256] = &[ INVALID_VALUE, // input 0 (0x0) INVALID_VALUE, // input 1 (0x1) @@ -846,6 +846,658 @@ INVALID_VALUE, // input 123 (0x7B) INVALID_VALUE, // input 124 (0x7C) INVALID_VALUE, // input 125 (0x7D) + INVALID_VALUE, // input 126 (0x7E) + INVALID_VALUE, // input 127 (0x7F) + INVALID_VALUE, // input 128 (0x80) + INVALID_VALUE, // input 129 (0x81) + INVALID_VALUE, // input 130 (0x82) + INVALID_VALUE, // input 131 (0x83) + INVALID_VALUE, // input 132 (0x84) + INVALID_VALUE, // input 133 (0x85) + INVALID_VALUE, // input 134 (0x86) + INVALID_VALUE, // input 135 (0x87) + INVALID_VALUE, // input 136 (0x88) + INVALID_VALUE, // input 137 (0x89) + INVALID_VALUE, // input 138 (0x8A) + INVALID_VALUE, // input 139 (0x8B) + INVALID_VALUE, // input 140 (0x8C) + INVALID_VALUE, // input 141 (0x8D) + INVALID_VALUE, // input 142 (0x8E) + INVALID_VALUE, // input 143 (0x8F) + INVALID_VALUE, // input 144 (0x90) + INVALID_VALUE, // input 145 (0x91) + INVALID_VALUE, // input 146 (0x92) + INVALID_VALUE, // input 147 (0x93) + INVALID_VALUE, // input 148 (0x94) + INVALID_VALUE, // input 149 (0x95) + INVALID_VALUE, // input 150 (0x96) + INVALID_VALUE, // input 151 (0x97) + INVALID_VALUE, // input 152 (0x98) + INVALID_VALUE, // input 153 (0x99) + INVALID_VALUE, // input 154 (0x9A) + INVALID_VALUE, // input 155 (0x9B) + INVALID_VALUE, // input 156 (0x9C) + INVALID_VALUE, // input 157 (0x9D) + INVALID_VALUE, // input 158 (0x9E) + INVALID_VALUE, // input 159 (0x9F) + INVALID_VALUE, // input 160 (0xA0) + INVALID_VALUE, // input 161 (0xA1) + INVALID_VALUE, // input 162 (0xA2) + INVALID_VALUE, // input 163 (0xA3) + INVALID_VALUE, // input 164 (0xA4) + INVALID_VALUE, // input 165 (0xA5) + INVALID_VALUE, // input 166 (0xA6) + INVALID_VALUE, // input 167 (0xA7) + INVALID_VALUE, // input 168 (0xA8) + INVALID_VALUE, // input 169 (0xA9) + INVALID_VALUE, // input 170 (0xAA) + INVALID_VALUE, // input 171 (0xAB) + INVALID_VALUE, // input 172 (0xAC) + INVALID_VALUE, // input 173 (0xAD) + INVALID_VALUE, // input 174 (0xAE) + INVALID_VALUE, // input 175 (0xAF) + INVALID_VALUE, // input 176 (0xB0) + INVALID_VALUE, // input 177 (0xB1) + INVALID_VALUE, // input 178 (0xB2) + INVALID_VALUE, // input 179 (0xB3) + INVALID_VALUE, // input 180 (0xB4) + INVALID_VALUE, // input 181 (0xB5) + INVALID_VALUE, // input 182 (0xB6) + INVALID_VALUE, // input 183 (0xB7) + INVALID_VALUE, // input 184 (0xB8) + INVALID_VALUE, // input 185 (0xB9) + INVALID_VALUE, // input 186 (0xBA) + INVALID_VALUE, // input 187 (0xBB) + INVALID_VALUE, // input 188 (0xBC) + INVALID_VALUE, // input 189 (0xBD) + INVALID_VALUE, // input 190 (0xBE) + INVALID_VALUE, // input 191 (0xBF) + INVALID_VALUE, // input 192 (0xC0) + INVALID_VALUE, // input 193 (0xC1) + INVALID_VALUE, // input 194 (0xC2) + INVALID_VALUE, // input 195 (0xC3) + INVALID_VALUE, // input 196 (0xC4) + INVALID_VALUE, // input 197 (0xC5) + INVALID_VALUE, // input 198 (0xC6) + INVALID_VALUE, // input 199 (0xC7) + INVALID_VALUE, // input 200 (0xC8) + INVALID_VALUE, // input 201 (0xC9) + INVALID_VALUE, // input 202 (0xCA) + INVALID_VALUE, // input 203 (0xCB) + INVALID_VALUE, // input 204 (0xCC) + INVALID_VALUE, // input 205 (0xCD) + INVALID_VALUE, // input 206 (0xCE) + INVALID_VALUE, // input 207 (0xCF) + INVALID_VALUE, // input 208 (0xD0) + INVALID_VALUE, // input 209 (0xD1) + INVALID_VALUE, // input 210 (0xD2) + INVALID_VALUE, // input 211 (0xD3) + INVALID_VALUE, // input 212 (0xD4) + INVALID_VALUE, // input 213 (0xD5) + INVALID_VALUE, // input 214 (0xD6) + INVALID_VALUE, // input 215 (0xD7) + INVALID_VALUE, // input 216 (0xD8) + INVALID_VALUE, // input 217 (0xD9) + INVALID_VALUE, // input 218 (0xDA) + INVALID_VALUE, // input 219 (0xDB) + INVALID_VALUE, // input 220 (0xDC) + INVALID_VALUE, // input 221 (0xDD) + INVALID_VALUE, // input 222 (0xDE) + INVALID_VALUE, // input 223 (0xDF) + INVALID_VALUE, // input 224 (0xE0) + INVALID_VALUE, // input 225 (0xE1) + INVALID_VALUE, // input 226 (0xE2) + INVALID_VALUE, // input 227 (0xE3) + INVALID_VALUE, // input 228 (0xE4) + INVALID_VALUE, // input 229 (0xE5) + INVALID_VALUE, // input 230 (0xE6) + INVALID_VALUE, // input 231 (0xE7) + INVALID_VALUE, // input 232 (0xE8) + INVALID_VALUE, // input 233 (0xE9) + INVALID_VALUE, // input 234 (0xEA) + INVALID_VALUE, // input 235 (0xEB) + INVALID_VALUE, // input 236 (0xEC) + INVALID_VALUE, // input 237 (0xED) + INVALID_VALUE, // input 238 (0xEE) + INVALID_VALUE, // input 239 (0xEF) + INVALID_VALUE, // input 240 (0xF0) + INVALID_VALUE, // input 241 (0xF1) + INVALID_VALUE, // input 242 (0xF2) + INVALID_VALUE, // input 243 (0xF3) + INVALID_VALUE, // input 244 (0xF4) + INVALID_VALUE, // input 245 (0xF5) + INVALID_VALUE, // input 246 (0xF6) + INVALID_VALUE, // input 247 (0xF7) + INVALID_VALUE, // input 248 (0xF8) + INVALID_VALUE, // input 249 (0xF9) + INVALID_VALUE, // input 250 (0xFA) + INVALID_VALUE, // input 251 (0xFB) + INVALID_VALUE, // input 252 (0xFC) + INVALID_VALUE, // input 253 (0xFD) + INVALID_VALUE, // input 254 (0xFE) + INVALID_VALUE, // input 255 (0xFF) +]; +#[rustfmt::skip] +pub const BCRYPT_ENCODE: &[u8; 64] = &[ + 46, // input 0 (0x0) => '.' (0x2E) + 47, // input 1 (0x1) => '/' (0x2F) + 65, // input 2 (0x2) => 'A' (0x41) + 66, // input 3 (0x3) => 'B' (0x42) + 67, // input 4 (0x4) => 'C' (0x43) + 68, // input 5 (0x5) => 'D' (0x44) + 69, // input 6 (0x6) => 'E' (0x45) + 70, // input 7 (0x7) => 'F' (0x46) + 71, // input 8 (0x8) => 'G' (0x47) + 72, // input 9 (0x9) => 'H' (0x48) + 73, // input 10 (0xA) => 'I' (0x49) + 74, // input 11 (0xB) => 'J' (0x4A) + 75, // input 12 (0xC) => 'K' (0x4B) + 76, // input 13 (0xD) => 'L' (0x4C) + 77, // input 14 (0xE) => 'M' (0x4D) + 78, // input 15 (0xF) => 'N' (0x4E) + 79, // input 16 (0x10) => 'O' (0x4F) + 80, // input 17 (0x11) => 'P' (0x50) + 81, // input 18 (0x12) => 'Q' (0x51) + 82, // input 19 (0x13) => 'R' (0x52) + 83, // input 20 (0x14) => 'S' (0x53) + 84, // input 21 (0x15) => 'T' (0x54) + 85, // input 22 (0x16) => 'U' (0x55) + 86, // input 23 (0x17) => 'V' (0x56) + 87, // input 24 (0x18) => 'W' (0x57) + 88, // input 25 (0x19) => 'X' (0x58) + 89, // input 26 (0x1A) => 'Y' (0x59) + 90, // input 27 (0x1B) => 'Z' (0x5A) + 97, // input 28 (0x1C) => 'a' (0x61) + 98, // input 29 (0x1D) => 'b' (0x62) + 99, // input 30 (0x1E) => 'c' (0x63) + 100, // input 31 (0x1F) => 'd' (0x64) + 101, // input 32 (0x20) => 'e' (0x65) + 102, // input 33 (0x21) => 'f' (0x66) + 103, // input 34 (0x22) => 'g' (0x67) + 104, // input 35 (0x23) => 'h' (0x68) + 105, // input 36 (0x24) => 'i' (0x69) + 106, // input 37 (0x25) => 'j' (0x6A) + 107, // input 38 (0x26) => 'k' (0x6B) + 108, // input 39 (0x27) => 'l' (0x6C) + 109, // input 40 (0x28) => 'm' (0x6D) + 110, // input 41 (0x29) => 'n' (0x6E) + 111, // input 42 (0x2A) => 'o' (0x6F) + 112, // input 43 (0x2B) => 'p' (0x70) + 113, // input 44 (0x2C) => 'q' (0x71) + 114, // input 45 (0x2D) => 'r' (0x72) + 115, // input 46 (0x2E) => 's' (0x73) + 116, // input 47 (0x2F) => 't' (0x74) + 117, // input 48 (0x30) => 'u' (0x75) + 118, // input 49 (0x31) => 'v' (0x76) + 119, // input 50 (0x32) => 'w' (0x77) + 120, // input 51 (0x33) => 'x' (0x78) + 121, // input 52 (0x34) => 'y' (0x79) + 122, // input 53 (0x35) => 'z' (0x7A) + 48, // input 54 (0x36) => '0' (0x30) + 49, // input 55 (0x37) => '1' (0x31) + 50, // input 56 (0x38) => '2' (0x32) + 51, // input 57 (0x39) => '3' (0x33) + 52, // input 58 (0x3A) => '4' (0x34) + 53, // input 59 (0x3B) => '5' (0x35) + 54, // input 60 (0x3C) => '6' (0x36) + 55, // input 61 (0x3D) => '7' (0x37) + 56, // input 62 (0x3E) => '8' (0x38) + 57, // input 63 (0x3F) => '9' (0x39) +]; +#[rustfmt::skip] +pub const BCRYPT_DECODE: &[u8; 256] = &[ + INVALID_VALUE, // input 0 (0x0) + INVALID_VALUE, // input 1 (0x1) + INVALID_VALUE, // input 2 (0x2) + INVALID_VALUE, // input 3 (0x3) + INVALID_VALUE, // input 4 (0x4) + INVALID_VALUE, // input 5 (0x5) + INVALID_VALUE, // input 6 (0x6) + INVALID_VALUE, // input 7 (0x7) + INVALID_VALUE, // input 8 (0x8) + INVALID_VALUE, // input 9 (0x9) + INVALID_VALUE, // input 10 (0xA) + INVALID_VALUE, // input 11 (0xB) + INVALID_VALUE, // input 12 (0xC) + INVALID_VALUE, // input 13 (0xD) + INVALID_VALUE, // input 14 (0xE) + INVALID_VALUE, // input 15 (0xF) + INVALID_VALUE, // input 16 (0x10) + INVALID_VALUE, // input 17 (0x11) + INVALID_VALUE, // input 18 (0x12) + INVALID_VALUE, // input 19 (0x13) + INVALID_VALUE, // input 20 (0x14) + INVALID_VALUE, // input 21 (0x15) + INVALID_VALUE, // input 22 (0x16) + INVALID_VALUE, // input 23 (0x17) + INVALID_VALUE, // input 24 (0x18) + INVALID_VALUE, // input 25 (0x19) + INVALID_VALUE, // input 26 (0x1A) + INVALID_VALUE, // input 27 (0x1B) + INVALID_VALUE, // input 28 (0x1C) + INVALID_VALUE, // input 29 (0x1D) + INVALID_VALUE, // input 30 (0x1E) + INVALID_VALUE, // input 31 (0x1F) + INVALID_VALUE, // input 32 (0x20) + INVALID_VALUE, // input 33 (0x21) + INVALID_VALUE, // input 34 (0x22) + INVALID_VALUE, // input 35 (0x23) + INVALID_VALUE, // input 36 (0x24) + INVALID_VALUE, // input 37 (0x25) + INVALID_VALUE, // input 38 (0x26) + INVALID_VALUE, // input 39 (0x27) + INVALID_VALUE, // input 40 (0x28) + INVALID_VALUE, // input 41 (0x29) + INVALID_VALUE, // input 42 (0x2A) + INVALID_VALUE, // input 43 (0x2B) + INVALID_VALUE, // input 44 (0x2C) + INVALID_VALUE, // input 45 (0x2D) + 0, // input 46 (0x2E char '.') => 0 (0x0) + 1, // input 47 (0x2F char '/') => 1 (0x1) + 54, // input 48 (0x30 char '0') => 54 (0x36) + 55, // input 49 (0x31 char '1') => 55 (0x37) + 56, // input 50 (0x32 char '2') => 56 (0x38) + 57, // input 51 (0x33 char '3') => 57 (0x39) + 58, // input 52 (0x34 char '4') => 58 (0x3A) + 59, // input 53 (0x35 char '5') => 59 (0x3B) + 60, // input 54 (0x36 char '6') => 60 (0x3C) + 61, // input 55 (0x37 char '7') => 61 (0x3D) + 62, // input 56 (0x38 char '8') => 62 (0x3E) + 63, // input 57 (0x39 char '9') => 63 (0x3F) + INVALID_VALUE, // input 58 (0x3A) + INVALID_VALUE, // input 59 (0x3B) + INVALID_VALUE, // input 60 (0x3C) + INVALID_VALUE, // input 61 (0x3D) + INVALID_VALUE, // input 62 (0x3E) + INVALID_VALUE, // input 63 (0x3F) + INVALID_VALUE, // input 64 (0x40) + 2, // input 65 (0x41 char 'A') => 2 (0x2) + 3, // input 66 (0x42 char 'B') => 3 (0x3) + 4, // input 67 (0x43 char 'C') => 4 (0x4) + 5, // input 68 (0x44 char 'D') => 5 (0x5) + 6, // input 69 (0x45 char 'E') => 6 (0x6) + 7, // input 70 (0x46 char 'F') => 7 (0x7) + 8, // input 71 (0x47 char 'G') => 8 (0x8) + 9, // input 72 (0x48 char 'H') => 9 (0x9) + 10, // input 73 (0x49 char 'I') => 10 (0xA) + 11, // input 74 (0x4A char 'J') => 11 (0xB) + 12, // input 75 (0x4B char 'K') => 12 (0xC) + 13, // input 76 (0x4C char 'L') => 13 (0xD) + 14, // input 77 (0x4D char 'M') => 14 (0xE) + 15, // input 78 (0x4E char 'N') => 15 (0xF) + 16, // input 79 (0x4F char 'O') => 16 (0x10) + 17, // input 80 (0x50 char 'P') => 17 (0x11) + 18, // input 81 (0x51 char 'Q') => 18 (0x12) + 19, // input 82 (0x52 char 'R') => 19 (0x13) + 20, // input 83 (0x53 char 'S') => 20 (0x14) + 21, // input 84 (0x54 char 'T') => 21 (0x15) + 22, // input 85 (0x55 char 'U') => 22 (0x16) + 23, // input 86 (0x56 char 'V') => 23 (0x17) + 24, // input 87 (0x57 char 'W') => 24 (0x18) + 25, // input 88 (0x58 char 'X') => 25 (0x19) + 26, // input 89 (0x59 char 'Y') => 26 (0x1A) + 27, // input 90 (0x5A char 'Z') => 27 (0x1B) + INVALID_VALUE, // input 91 (0x5B) + INVALID_VALUE, // input 92 (0x5C) + INVALID_VALUE, // input 93 (0x5D) + INVALID_VALUE, // input 94 (0x5E) + INVALID_VALUE, // input 95 (0x5F) + INVALID_VALUE, // input 96 (0x60) + 28, // input 97 (0x61 char 'a') => 28 (0x1C) + 29, // input 98 (0x62 char 'b') => 29 (0x1D) + 30, // input 99 (0x63 char 'c') => 30 (0x1E) + 31, // input 100 (0x64 char 'd') => 31 (0x1F) + 32, // input 101 (0x65 char 'e') => 32 (0x20) + 33, // input 102 (0x66 char 'f') => 33 (0x21) + 34, // input 103 (0x67 char 'g') => 34 (0x22) + 35, // input 104 (0x68 char 'h') => 35 (0x23) + 36, // input 105 (0x69 char 'i') => 36 (0x24) + 37, // input 106 (0x6A char 'j') => 37 (0x25) + 38, // input 107 (0x6B char 'k') => 38 (0x26) + 39, // input 108 (0x6C char 'l') => 39 (0x27) + 40, // input 109 (0x6D char 'm') => 40 (0x28) + 41, // input 110 (0x6E char 'n') => 41 (0x29) + 42, // input 111 (0x6F char 'o') => 42 (0x2A) + 43, // input 112 (0x70 char 'p') => 43 (0x2B) + 44, // input 113 (0x71 char 'q') => 44 (0x2C) + 45, // input 114 (0x72 char 'r') => 45 (0x2D) + 46, // input 115 (0x73 char 's') => 46 (0x2E) + 47, // input 116 (0x74 char 't') => 47 (0x2F) + 48, // input 117 (0x75 char 'u') => 48 (0x30) + 49, // input 118 (0x76 char 'v') => 49 (0x31) + 50, // input 119 (0x77 char 'w') => 50 (0x32) + 51, // input 120 (0x78 char 'x') => 51 (0x33) + 52, // input 121 (0x79 char 'y') => 52 (0x34) + 53, // input 122 (0x7A char 'z') => 53 (0x35) + INVALID_VALUE, // input 123 (0x7B) + INVALID_VALUE, // input 124 (0x7C) + INVALID_VALUE, // input 125 (0x7D) + INVALID_VALUE, // input 126 (0x7E) + INVALID_VALUE, // input 127 (0x7F) + INVALID_VALUE, // input 128 (0x80) + INVALID_VALUE, // input 129 (0x81) + INVALID_VALUE, // input 130 (0x82) + INVALID_VALUE, // input 131 (0x83) + INVALID_VALUE, // input 132 (0x84) + INVALID_VALUE, // input 133 (0x85) + INVALID_VALUE, // input 134 (0x86) + INVALID_VALUE, // input 135 (0x87) + INVALID_VALUE, // input 136 (0x88) + INVALID_VALUE, // input 137 (0x89) + INVALID_VALUE, // input 138 (0x8A) + INVALID_VALUE, // input 139 (0x8B) + INVALID_VALUE, // input 140 (0x8C) + INVALID_VALUE, // input 141 (0x8D) + INVALID_VALUE, // input 142 (0x8E) + INVALID_VALUE, // input 143 (0x8F) + INVALID_VALUE, // input 144 (0x90) + INVALID_VALUE, // input 145 (0x91) + INVALID_VALUE, // input 146 (0x92) + INVALID_VALUE, // input 147 (0x93) + INVALID_VALUE, // input 148 (0x94) + INVALID_VALUE, // input 149 (0x95) + INVALID_VALUE, // input 150 (0x96) + INVALID_VALUE, // input 151 (0x97) + INVALID_VALUE, // input 152 (0x98) + INVALID_VALUE, // input 153 (0x99) + INVALID_VALUE, // input 154 (0x9A) + INVALID_VALUE, // input 155 (0x9B) + INVALID_VALUE, // input 156 (0x9C) + INVALID_VALUE, // input 157 (0x9D) + INVALID_VALUE, // input 158 (0x9E) + INVALID_VALUE, // input 159 (0x9F) + INVALID_VALUE, // input 160 (0xA0) + INVALID_VALUE, // input 161 (0xA1) + INVALID_VALUE, // input 162 (0xA2) + INVALID_VALUE, // input 163 (0xA3) + INVALID_VALUE, // input 164 (0xA4) + INVALID_VALUE, // input 165 (0xA5) + INVALID_VALUE, // input 166 (0xA6) + INVALID_VALUE, // input 167 (0xA7) + INVALID_VALUE, // input 168 (0xA8) + INVALID_VALUE, // input 169 (0xA9) + INVALID_VALUE, // input 170 (0xAA) + INVALID_VALUE, // input 171 (0xAB) + INVALID_VALUE, // input 172 (0xAC) + INVALID_VALUE, // input 173 (0xAD) + INVALID_VALUE, // input 174 (0xAE) + INVALID_VALUE, // input 175 (0xAF) + INVALID_VALUE, // input 176 (0xB0) + INVALID_VALUE, // input 177 (0xB1) + INVALID_VALUE, // input 178 (0xB2) + INVALID_VALUE, // input 179 (0xB3) + INVALID_VALUE, // input 180 (0xB4) + INVALID_VALUE, // input 181 (0xB5) + INVALID_VALUE, // input 182 (0xB6) + INVALID_VALUE, // input 183 (0xB7) + INVALID_VALUE, // input 184 (0xB8) + INVALID_VALUE, // input 185 (0xB9) + INVALID_VALUE, // input 186 (0xBA) + INVALID_VALUE, // input 187 (0xBB) + INVALID_VALUE, // input 188 (0xBC) + INVALID_VALUE, // input 189 (0xBD) + INVALID_VALUE, // input 190 (0xBE) + INVALID_VALUE, // input 191 (0xBF) + INVALID_VALUE, // input 192 (0xC0) + INVALID_VALUE, // input 193 (0xC1) + INVALID_VALUE, // input 194 (0xC2) + INVALID_VALUE, // input 195 (0xC3) + INVALID_VALUE, // input 196 (0xC4) + INVALID_VALUE, // input 197 (0xC5) + INVALID_VALUE, // input 198 (0xC6) + INVALID_VALUE, // input 199 (0xC7) + INVALID_VALUE, // input 200 (0xC8) + INVALID_VALUE, // input 201 (0xC9) + INVALID_VALUE, // input 202 (0xCA) + INVALID_VALUE, // input 203 (0xCB) + INVALID_VALUE, // input 204 (0xCC) + INVALID_VALUE, // input 205 (0xCD) + INVALID_VALUE, // input 206 (0xCE) + INVALID_VALUE, // input 207 (0xCF) + INVALID_VALUE, // input 208 (0xD0) + INVALID_VALUE, // input 209 (0xD1) + INVALID_VALUE, // input 210 (0xD2) + INVALID_VALUE, // input 211 (0xD3) + INVALID_VALUE, // input 212 (0xD4) + INVALID_VALUE, // input 213 (0xD5) + INVALID_VALUE, // input 214 (0xD6) + INVALID_VALUE, // input 215 (0xD7) + INVALID_VALUE, // input 216 (0xD8) + INVALID_VALUE, // input 217 (0xD9) + INVALID_VALUE, // input 218 (0xDA) + INVALID_VALUE, // input 219 (0xDB) + INVALID_VALUE, // input 220 (0xDC) + INVALID_VALUE, // input 221 (0xDD) + INVALID_VALUE, // input 222 (0xDE) + INVALID_VALUE, // input 223 (0xDF) + INVALID_VALUE, // input 224 (0xE0) + INVALID_VALUE, // input 225 (0xE1) + INVALID_VALUE, // input 226 (0xE2) + INVALID_VALUE, // input 227 (0xE3) + INVALID_VALUE, // input 228 (0xE4) + INVALID_VALUE, // input 229 (0xE5) + INVALID_VALUE, // input 230 (0xE6) + INVALID_VALUE, // input 231 (0xE7) + INVALID_VALUE, // input 232 (0xE8) + INVALID_VALUE, // input 233 (0xE9) + INVALID_VALUE, // input 234 (0xEA) + INVALID_VALUE, // input 235 (0xEB) + INVALID_VALUE, // input 236 (0xEC) + INVALID_VALUE, // input 237 (0xED) + INVALID_VALUE, // input 238 (0xEE) + INVALID_VALUE, // input 239 (0xEF) + INVALID_VALUE, // input 240 (0xF0) + INVALID_VALUE, // input 241 (0xF1) + INVALID_VALUE, // input 242 (0xF2) + INVALID_VALUE, // input 243 (0xF3) + INVALID_VALUE, // input 244 (0xF4) + INVALID_VALUE, // input 245 (0xF5) + INVALID_VALUE, // input 246 (0xF6) + INVALID_VALUE, // input 247 (0xF7) + INVALID_VALUE, // input 248 (0xF8) + INVALID_VALUE, // input 249 (0xF9) + INVALID_VALUE, // input 250 (0xFA) + INVALID_VALUE, // input 251 (0xFB) + INVALID_VALUE, // input 252 (0xFC) + INVALID_VALUE, // input 253 (0xFD) + INVALID_VALUE, // input 254 (0xFE) + INVALID_VALUE, // input 255 (0xFF) +]; +#[rustfmt::skip] +pub const IMAP_MUTF7_ENCODE: &[u8; 64] = &[ + 65, // input 0 (0x0) => 'A' (0x41) + 66, // input 1 (0x1) => 'B' (0x42) + 67, // input 2 (0x2) => 'C' (0x43) + 68, // input 3 (0x3) => 'D' (0x44) + 69, // input 4 (0x4) => 'E' (0x45) + 70, // input 5 (0x5) => 'F' (0x46) + 71, // input 6 (0x6) => 'G' (0x47) + 72, // input 7 (0x7) => 'H' (0x48) + 73, // input 8 (0x8) => 'I' (0x49) + 74, // input 9 (0x9) => 'J' (0x4A) + 75, // input 10 (0xA) => 'K' (0x4B) + 76, // input 11 (0xB) => 'L' (0x4C) + 77, // input 12 (0xC) => 'M' (0x4D) + 78, // input 13 (0xD) => 'N' (0x4E) + 79, // input 14 (0xE) => 'O' (0x4F) + 80, // input 15 (0xF) => 'P' (0x50) + 81, // input 16 (0x10) => 'Q' (0x51) + 82, // input 17 (0x11) => 'R' (0x52) + 83, // input 18 (0x12) => 'S' (0x53) + 84, // input 19 (0x13) => 'T' (0x54) + 85, // input 20 (0x14) => 'U' (0x55) + 86, // input 21 (0x15) => 'V' (0x56) + 87, // input 22 (0x16) => 'W' (0x57) + 88, // input 23 (0x17) => 'X' (0x58) + 89, // input 24 (0x18) => 'Y' (0x59) + 90, // input 25 (0x19) => 'Z' (0x5A) + 97, // input 26 (0x1A) => 'a' (0x61) + 98, // input 27 (0x1B) => 'b' (0x62) + 99, // input 28 (0x1C) => 'c' (0x63) + 100, // input 29 (0x1D) => 'd' (0x64) + 101, // input 30 (0x1E) => 'e' (0x65) + 102, // input 31 (0x1F) => 'f' (0x66) + 103, // input 32 (0x20) => 'g' (0x67) + 104, // input 33 (0x21) => 'h' (0x68) + 105, // input 34 (0x22) => 'i' (0x69) + 106, // input 35 (0x23) => 'j' (0x6A) + 107, // input 36 (0x24) => 'k' (0x6B) + 108, // input 37 (0x25) => 'l' (0x6C) + 109, // input 38 (0x26) => 'm' (0x6D) + 110, // input 39 (0x27) => 'n' (0x6E) + 111, // input 40 (0x28) => 'o' (0x6F) + 112, // input 41 (0x29) => 'p' (0x70) + 113, // input 42 (0x2A) => 'q' (0x71) + 114, // input 43 (0x2B) => 'r' (0x72) + 115, // input 44 (0x2C) => 's' (0x73) + 116, // input 45 (0x2D) => 't' (0x74) + 117, // input 46 (0x2E) => 'u' (0x75) + 118, // input 47 (0x2F) => 'v' (0x76) + 119, // input 48 (0x30) => 'w' (0x77) + 120, // input 49 (0x31) => 'x' (0x78) + 121, // input 50 (0x32) => 'y' (0x79) + 122, // input 51 (0x33) => 'z' (0x7A) + 48, // input 52 (0x34) => '0' (0x30) + 49, // input 53 (0x35) => '1' (0x31) + 50, // input 54 (0x36) => '2' (0x32) + 51, // input 55 (0x37) => '3' (0x33) + 52, // input 56 (0x38) => '4' (0x34) + 53, // input 57 (0x39) => '5' (0x35) + 54, // input 58 (0x3A) => '6' (0x36) + 55, // input 59 (0x3B) => '7' (0x37) + 56, // input 60 (0x3C) => '8' (0x38) + 57, // input 61 (0x3D) => '9' (0x39) + 43, // input 62 (0x3E) => '+' (0x2B) + 44, // input 63 (0x3F) => ',' (0x2C) +]; +#[rustfmt::skip] +pub const IMAP_MUTF7_DECODE: &[u8; 256] = &[ + INVALID_VALUE, // input 0 (0x0) + INVALID_VALUE, // input 1 (0x1) + INVALID_VALUE, // input 2 (0x2) + INVALID_VALUE, // input 3 (0x3) + INVALID_VALUE, // input 4 (0x4) + INVALID_VALUE, // input 5 (0x5) + INVALID_VALUE, // input 6 (0x6) + INVALID_VALUE, // input 7 (0x7) + INVALID_VALUE, // input 8 (0x8) + INVALID_VALUE, // input 9 (0x9) + INVALID_VALUE, // input 10 (0xA) + INVALID_VALUE, // input 11 (0xB) + INVALID_VALUE, // input 12 (0xC) + INVALID_VALUE, // input 13 (0xD) + INVALID_VALUE, // input 14 (0xE) + INVALID_VALUE, // input 15 (0xF) + INVALID_VALUE, // input 16 (0x10) + INVALID_VALUE, // input 17 (0x11) + INVALID_VALUE, // input 18 (0x12) + INVALID_VALUE, // input 19 (0x13) + INVALID_VALUE, // input 20 (0x14) + INVALID_VALUE, // input 21 (0x15) + INVALID_VALUE, // input 22 (0x16) + INVALID_VALUE, // input 23 (0x17) + INVALID_VALUE, // input 24 (0x18) + INVALID_VALUE, // input 25 (0x19) + INVALID_VALUE, // input 26 (0x1A) + INVALID_VALUE, // input 27 (0x1B) + INVALID_VALUE, // input 28 (0x1C) + INVALID_VALUE, // input 29 (0x1D) + INVALID_VALUE, // input 30 (0x1E) + INVALID_VALUE, // input 31 (0x1F) + INVALID_VALUE, // input 32 (0x20) + INVALID_VALUE, // input 33 (0x21) + INVALID_VALUE, // input 34 (0x22) + INVALID_VALUE, // input 35 (0x23) + INVALID_VALUE, // input 36 (0x24) + INVALID_VALUE, // input 37 (0x25) + INVALID_VALUE, // input 38 (0x26) + INVALID_VALUE, // input 39 (0x27) + INVALID_VALUE, // input 40 (0x28) + INVALID_VALUE, // input 41 (0x29) + INVALID_VALUE, // input 42 (0x2A) + 62, // input 43 (0x2B char '+') => 62 (0x3E) + 63, // input 44 (0x2C char ',') => 63 (0x3F) + INVALID_VALUE, // input 45 (0x2D) + INVALID_VALUE, // input 46 (0x2E) + INVALID_VALUE, // input 47 (0x2F) + 52, // input 48 (0x30 char '0') => 52 (0x34) + 53, // input 49 (0x31 char '1') => 53 (0x35) + 54, // input 50 (0x32 char '2') => 54 (0x36) + 55, // input 51 (0x33 char '3') => 55 (0x37) + 56, // input 52 (0x34 char '4') => 56 (0x38) + 57, // input 53 (0x35 char '5') => 57 (0x39) + 58, // input 54 (0x36 char '6') => 58 (0x3A) + 59, // input 55 (0x37 char '7') => 59 (0x3B) + 60, // input 56 (0x38 char '8') => 60 (0x3C) + 61, // input 57 (0x39 char '9') => 61 (0x3D) + INVALID_VALUE, // input 58 (0x3A) + INVALID_VALUE, // input 59 (0x3B) + INVALID_VALUE, // input 60 (0x3C) + INVALID_VALUE, // input 61 (0x3D) + INVALID_VALUE, // input 62 (0x3E) + INVALID_VALUE, // input 63 (0x3F) + INVALID_VALUE, // input 64 (0x40) + 0, // input 65 (0x41 char 'A') => 0 (0x0) + 1, // input 66 (0x42 char 'B') => 1 (0x1) + 2, // input 67 (0x43 char 'C') => 2 (0x2) + 3, // input 68 (0x44 char 'D') => 3 (0x3) + 4, // input 69 (0x45 char 'E') => 4 (0x4) + 5, // input 70 (0x46 char 'F') => 5 (0x5) + 6, // input 71 (0x47 char 'G') => 6 (0x6) + 7, // input 72 (0x48 char 'H') => 7 (0x7) + 8, // input 73 (0x49 char 'I') => 8 (0x8) + 9, // input 74 (0x4A char 'J') => 9 (0x9) + 10, // input 75 (0x4B char 'K') => 10 (0xA) + 11, // input 76 (0x4C char 'L') => 11 (0xB) + 12, // input 77 (0x4D char 'M') => 12 (0xC) + 13, // input 78 (0x4E char 'N') => 13 (0xD) + 14, // input 79 (0x4F char 'O') => 14 (0xE) + 15, // input 80 (0x50 char 'P') => 15 (0xF) + 16, // input 81 (0x51 char 'Q') => 16 (0x10) + 17, // input 82 (0x52 char 'R') => 17 (0x11) + 18, // input 83 (0x53 char 'S') => 18 (0x12) + 19, // input 84 (0x54 char 'T') => 19 (0x13) + 20, // input 85 (0x55 char 'U') => 20 (0x14) + 21, // input 86 (0x56 char 'V') => 21 (0x15) + 22, // input 87 (0x57 char 'W') => 22 (0x16) + 23, // input 88 (0x58 char 'X') => 23 (0x17) + 24, // input 89 (0x59 char 'Y') => 24 (0x18) + 25, // input 90 (0x5A char 'Z') => 25 (0x19) + INVALID_VALUE, // input 91 (0x5B) + INVALID_VALUE, // input 92 (0x5C) + INVALID_VALUE, // input 93 (0x5D) + INVALID_VALUE, // input 94 (0x5E) + INVALID_VALUE, // input 95 (0x5F) + INVALID_VALUE, // input 96 (0x60) + 26, // input 97 (0x61 char 'a') => 26 (0x1A) + 27, // input 98 (0x62 char 'b') => 27 (0x1B) + 28, // input 99 (0x63 char 'c') => 28 (0x1C) + 29, // input 100 (0x64 char 'd') => 29 (0x1D) + 30, // input 101 (0x65 char 'e') => 30 (0x1E) + 31, // input 102 (0x66 char 'f') => 31 (0x1F) + 32, // input 103 (0x67 char 'g') => 32 (0x20) + 33, // input 104 (0x68 char 'h') => 33 (0x21) + 34, // input 105 (0x69 char 'i') => 34 (0x22) + 35, // input 106 (0x6A char 'j') => 35 (0x23) + 36, // input 107 (0x6B char 'k') => 36 (0x24) + 37, // input 108 (0x6C char 'l') => 37 (0x25) + 38, // input 109 (0x6D char 'm') => 38 (0x26) + 39, // input 110 (0x6E char 'n') => 39 (0x27) + 40, // input 111 (0x6F char 'o') => 40 (0x28) + 41, // input 112 (0x70 char 'p') => 41 (0x29) + 42, // input 113 (0x71 char 'q') => 42 (0x2A) + 43, // input 114 (0x72 char 'r') => 43 (0x2B) + 44, // input 115 (0x73 char 's') => 44 (0x2C) + 45, // input 116 (0x74 char 't') => 45 (0x2D) + 46, // input 117 (0x75 char 'u') => 46 (0x2E) + 47, // input 118 (0x76 char 'v') => 47 (0x2F) + 48, // input 119 (0x77 char 'w') => 48 (0x30) + 49, // input 120 (0x78 char 'x') => 49 (0x31) + 50, // input 121 (0x79 char 'y') => 50 (0x32) + 51, // input 122 (0x7A char 'z') => 51 (0x33) + INVALID_VALUE, // input 123 (0x7B) + INVALID_VALUE, // input 124 (0x7C) + INVALID_VALUE, // input 125 (0x7D) INVALID_VALUE, // input 126 (0x7E) INVALID_VALUE, // input 127 (0x7F) INVALID_VALUE, // input 128 (0x80) diff -Nru rust-base64-0.10.1/src/tests.rs rust-base64-0.12.1/src/tests.rs --- rust-base64-0.10.1/src/tests.rs 2018-12-16 14:44:34.000000000 +0000 +++ rust-base64-0.12.1/src/tests.rs 2020-04-29 23:19:11.000000000 +0000 @@ -1,13 +1,12 @@ -extern crate rand; - -use encode::encoded_size; -use *; +use crate::{decode_config, encode::encoded_size, encode_config_buf, CharacterSet, Config}; use std::str; -use self::rand::distributions::{Distribution, Uniform}; -use self::rand::{FromEntropy, Rng}; -use self::rand::seq::SliceRandom; +use rand::{ + distributions::{Distribution, Uniform}, + seq::SliceRandom, + FromEntropy, Rng, +}; #[test] fn roundtrip_random_config_short() { @@ -73,6 +72,7 @@ CharacterSet::UrlSafe, CharacterSet::Standard, CharacterSet::Crypt, + CharacterSet::ImapMutf7, ]; let charset = *CHARSETS.choose(rng).unwrap(); diff -Nru rust-base64-0.10.1/src/write/encoder.rs rust-base64-0.12.1/src/write/encoder.rs --- rust-base64-0.10.1/src/write/encoder.rs 2019-01-25 02:44:23.000000000 +0000 +++ rust-base64-0.12.1/src/write/encoder.rs 2019-11-21 02:08:31.000000000 +0000 @@ -1,7 +1,9 @@ -use encode::encode_to_slice; -use std::io::{ErrorKind, Result, Write}; -use std::{cmp, fmt}; -use {encode_config_slice, Config}; +use crate::encode::encode_to_slice; +use crate::{encode_config_slice, Config}; +use std::{ + cmp, fmt, + io::{ErrorKind, Result, Write}, +}; pub(crate) const BUF_SIZE: usize = 1024; /// The most bytes whose encoding will fit in `BUF_SIZE` @@ -153,7 +155,7 @@ let res = self.w.write(&self.output[..current_output_len]); self.panicked = false; - return res.map(|consumed| { + res.map(|consumed| { debug_assert!(consumed <= current_output_len); if consumed < current_output_len { @@ -165,9 +167,7 @@ } else { self.output_occupied_len = 0; } - - () - }); + }) } /// Write all buffered encoded output. If this returns `Ok`, `self.output_occupied_len` is `0`. @@ -232,10 +232,10 @@ // before reading any input, write any leftover encoded output from last time if self.output_occupied_len > 0 { let current_len = self.output_occupied_len; - return self.write_to_delegate(current_len) + return self + .write_to_delegate(current_len) // did not read any input - .map(|_| 0) - + .map(|_| 0); } debug_assert_eq!(0, self.output_occupied_len); @@ -282,7 +282,7 @@ // and don't read more than can be encoded max_input_len = MAX_INPUT_LEN - MIN_ENCODE_CHUNK_SIZE; - // fall through to normal encoding + // fall through to normal encoding } else { // `extra` and `input` are non empty, but `|extra| + |input| < 3`, so there must be // 1 byte in each. @@ -329,7 +329,7 @@ // no matter whether we wrote the full encoded buffer or not, we consumed the same // input .map(|_| extra_input_read_len + input_chunks_to_encode_len) - .map_err( |e| { + .map_err(|e| { // in case we filled and encoded `extra`, reset extra_len self.extra_input_occupied_len = orig_extra_len; diff -Nru rust-base64-0.10.1/src/write/encoder_tests.rs rust-base64-0.12.1/src/write/encoder_tests.rs --- rust-base64-0.10.1/src/write/encoder_tests.rs 2019-01-25 02:44:23.000000000 +0000 +++ rust-base64-0.12.1/src/write/encoder_tests.rs 2019-11-20 04:06:02.000000000 +0000 @@ -1,13 +1,11 @@ -extern crate rand; - use super::EncoderWriter; -use tests::random_config; -use {encode_config, encode_config_buf, STANDARD_NO_PAD, URL_SAFE}; +use crate::tests::random_config; +use crate::{encode_config, encode_config_buf, STANDARD_NO_PAD, URL_SAFE}; use std::io::{Cursor, Write}; use std::{cmp, io, str}; -use self::rand::Rng; +use rand::Rng; #[test] fn encode_three_bytes() { @@ -209,7 +207,8 @@ } #[test] -fn write_partial_then_enough_to_complete_chunk_but_not_complete_another_chunk_encodes_complete_chunk_without_consuming_remaining() { +fn write_partial_then_enough_to_complete_chunk_but_not_complete_another_chunk_encodes_complete_chunk_without_consuming_remaining( +) { let mut c = Cursor::new(Vec::new()); { let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); @@ -245,7 +244,8 @@ } #[test] -fn write_partial_then_enough_to_complete_chunk_and_another_chunk_and_another_partial_chunk_encodes_only_complete_chunks() { +fn write_partial_then_enough_to_complete_chunk_and_another_chunk_and_another_partial_chunk_encodes_only_complete_chunks( +) { let mut c = Cursor::new(Vec::new()); { let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); @@ -360,7 +360,8 @@ retry_interrupted_write_all( &mut stream_encoder, &orig_data[bytes_consumed..bytes_consumed + input_len], - ).unwrap(); + ) + .unwrap(); bytes_consumed += input_len; } @@ -411,7 +412,7 @@ w: &mut stream_encoded, rng: &mut partial_rng, full_input_fraction: 0.1, - no_interrupt_fraction: 0.1 + no_interrupt_fraction: 0.1, }; let mut stream_encoder = EncoderWriter::new(&mut partial_writer, config); @@ -420,17 +421,20 @@ // use at most medium-length inputs to exercise retry logic more aggressively let input_len: usize = cmp::min(rng.gen_range(0, 100), orig_len - bytes_consumed); - let res = stream_encoder.write(&orig_data[bytes_consumed..bytes_consumed + input_len]); + let res = + stream_encoder.write(&orig_data[bytes_consumed..bytes_consumed + input_len]); // retry on interrupt match res { Ok(len) => bytes_consumed += len, Err(e) => match e.kind() { io::ErrorKind::Interrupted => continue, - _ => { panic!("should not see other errors"); } + _ => { + panic!("should not see other errors"); + } }, } - }; + } stream_encoder.finish().unwrap(); @@ -441,7 +445,6 @@ } } - /// Retry writes until all the data is written or an error that isn't Interrupted is returned. fn retry_interrupted_write_all(w: &mut W, buf: &[u8]) -> io::Result<()> { let mut bytes_consumed = 0; @@ -453,7 +456,7 @@ Ok(len) => bytes_consumed += len, Err(e) => match e.kind() { io::ErrorKind::Interrupted => continue, - _ => { return Err(e) } + _ => return Err(e), }, } } @@ -540,12 +543,12 @@ /// In [0, 1]. If a random number in [0, 1] is `<= threshold`, `write()` will write all its /// input. Otherwise, it will write a random substring full_input_fraction: f64, - no_interrupt_fraction: f64 + no_interrupt_fraction: f64, } impl<'a, W: Write, R: Rng> Write for PartialInterruptingWriter<'a, W, R> { fn write(&mut self, buf: &[u8]) -> io::Result { - if self.rng.gen_range(0.0, 1.0) > self.no_interrupt_fraction{ + if self.rng.gen_range(0.0, 1.0) > self.no_interrupt_fraction { return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted")); } @@ -554,11 +557,12 @@ self.w.write(buf) } else { // only use a prefix of it - self.w.write(&buf[0..(self.rng.gen_range(0, buf.len() - 1))]) + self.w + .write(&buf[0..(self.rng.gen_range(0, buf.len() - 1))]) } } fn flush(&mut self) -> io::Result<()> { self.w.flush() } -} \ No newline at end of file +} diff -Nru rust-base64-0.10.1/tests/decode.rs rust-base64-0.12.1/tests/decode.rs --- rust-base64-0.10.1/tests/decode.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/tests/decode.rs 2019-11-20 04:06:02.000000000 +0000 @@ -4,7 +4,7 @@ mod helpers; -use helpers::*; +use self::helpers::*; #[test] fn decode_rfc4648_0() { diff -Nru rust-base64-0.10.1/tests/tests.rs rust-base64-0.12.1/tests/tests.rs --- rust-base64-0.10.1/tests/tests.rs 2018-11-26 16:22:08.000000000 +0000 +++ rust-base64-0.12.1/tests/tests.rs 2019-11-20 04:06:02.000000000 +0000 @@ -6,7 +6,7 @@ use base64::*; mod helpers; -use helpers::*; +use self::helpers::*; // generate random contents of the specified length and test encode/decode roundtrip fn roundtrip_random( diff -Nru rust-base64-0.10.1/.travis.yml rust-base64-0.12.1/.travis.yml --- rust-base64-0.10.1/.travis.yml 2019-01-25 02:44:23.000000000 +0000 +++ rust-base64-0.12.1/.travis.yml 2020-04-29 23:19:11.000000000 +0000 @@ -5,7 +5,7 @@ matrix: include: - - rust: 1.27.2 + - rust: 1.34.0 - rust: stable - rust: beta - rust: nightly @@ -17,16 +17,28 @@ install: # For test coverage. In install step so that it can use cache. - cargo tarpaulin --version || RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install --force cargo-tarpaulin - allow_failures: - - rust: nightly + - cargo +nightly install cargo-fuzz + + # no_std + - rust: stable + env: TARGET="--target thumbv6m-none-eabi" FEATURES="--no-default-features --features alloc" + install: + - rustup target add thumbv6m-none-eabi cache: cargo +env: + # prevent cargo fuzz list from printing with color + - TERM=dumb + script: - - cargo build --verbose - - cargo test --verbose - - cargo doc --verbose + - cargo build --verbose $TARGET --no-default-features + - cargo build --verbose $TARGET $FEATURES + - 'if [[ -z "$TARGET" ]]; then cargo test --verbose; fi' + - 'if [[ -z "$TARGET" ]]; then cargo doc --verbose; fi' - 'if [[ "$TRAVIS_RUST_VERSION" = nightly ]]; then cargo bench --no-run; fi' + # run for just a second to confirm that it can build and run ok + - 'if [[ "$TRAVIS_RUST_VERSION" = nightly ]]; then cargo fuzz list | xargs -L 1 -I FUZZER cargo fuzz run FUZZER -- -max_total_time=1; fi' after_success: | if [[ "$TRAVIS_RUST_VERSION" = nightly ]]; then