Skip to content

Commit

Permalink
format
Browse files Browse the repository at this point in the history
  • Loading branch information
marshallpierce committed Mar 8, 2020
1 parent 5c2fee3 commit 66bc806
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 50 deletions.
1 change: 0 additions & 1 deletion src/chunked_encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,4 @@ pub mod tests {
s
}
}

}
58 changes: 34 additions & 24 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,7 @@ pub fn decode_config_slice<T: ?Sized + AsRef<[u8]>>(
) -> Result<usize, DecodeError> {
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
Expand Down Expand Up @@ -340,16 +335,17 @@ fn decode_helper(

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));
}

Expand Down Expand Up @@ -716,24 +712,35 @@ mod tests {

#[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
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));
}

Expand Down Expand Up @@ -838,6 +845,9 @@ mod tests {

#[test]
fn decode_imap() {
assert_eq!(::decode_config(b"+,,+", ::IMAP_MUTF7), ::decode_config(b"+//+", ::STANDARD_NO_PAD));
assert_eq!(
::decode_config(b"+,,+", ::IMAP_MUTF7),
::decode_config(b"+//+", ::STANDARD_NO_PAD)
);
}
}
11 changes: 7 additions & 4 deletions src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ pub fn encode_to_slice(input: &[u8], output: &mut [u8], encode_table: &[u8; 64])

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;
Expand Down Expand Up @@ -658,6 +658,9 @@ mod tests {

#[test]
fn encode_imap() {
assert_eq!(::encode_config(b"\xFB\xFF", ::IMAP_MUTF7), ::encode_config(b"\xFB\xFF", ::STANDARD_NO_PAD).replace("/", ","));
assert_eq!(
::encode_config(b"\xFB\xFF", ::IMAP_MUTF7),
::encode_config(b"\xFB\xFF", ::STANDARD_NO_PAD).replace("/", ",")
);
}
}
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ pub struct Config {
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.
Expand All @@ -146,7 +150,10 @@ impl Config {
/// 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
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use *;
use std::str;

use self::rand::distributions::{Distribution, Uniform};
use self::rand::{FromEntropy, Rng};
use self::rand::seq::SliceRandom;
use self::rand::{FromEntropy, Rng};

#[test]
fn roundtrip_random_config_short() {
Expand Down
10 changes: 5 additions & 5 deletions src/write/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,10 @@ impl<'a, W: Write> Write for EncoderWriter<'a, W> {
// 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);
Expand Down Expand Up @@ -282,7 +282,7 @@ impl<'a, W: Write> Write for EncoderWriter<'a, W> {
// 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.
Expand Down Expand Up @@ -329,7 +329,7 @@ impl<'a, W: Write> Write for EncoderWriter<'a, W> {
// 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;

Expand Down
32 changes: 19 additions & 13 deletions src/write/encoder_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ fn write_2_partials_to_exactly_complete_chunk_encodes_complete_chunk() {
}

#[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);
Expand Down Expand Up @@ -245,7 +246,8 @@ fn write_partial_then_enough_to_complete_chunk_and_another_chunk_encodes_complet
}

#[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);
Expand Down Expand Up @@ -360,7 +362,8 @@ fn retrying_writes_that_error_with_interrupted_works() {
retry_interrupted_write_all(
&mut stream_encoder,
&orig_data[bytes_consumed..bytes_consumed + input_len],
).unwrap();
)
.unwrap();

bytes_consumed += input_len;
}
Expand Down Expand Up @@ -411,7 +414,7 @@ fn writes_that_only_write_part_of_input_and_sometimes_interrupt_produce_correct_
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);
Expand All @@ -420,17 +423,20 @@ fn writes_that_only_write_part_of_input_and_sometimes_interrupt_produce_correct_
// 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();

Expand All @@ -441,7 +447,6 @@ fn writes_that_only_write_part_of_input_and_sometimes_interrupt_produce_correct_
}
}


/// Retry writes until all the data is written or an error that isn't Interrupted is returned.
fn retry_interrupted_write_all<W: Write>(w: &mut W, buf: &[u8]) -> io::Result<()> {
let mut bytes_consumed = 0;
Expand All @@ -453,7 +458,7 @@ fn retry_interrupted_write_all<W: Write>(w: &mut W, buf: &[u8]) -> io::Result<()
Ok(len) => bytes_consumed += len,
Err(e) => match e.kind() {
io::ErrorKind::Interrupted => continue,
_ => { return Err(e) }
_ => return Err(e),
},
}
}
Expand Down Expand Up @@ -540,12 +545,12 @@ struct PartialInterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> {
/// 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<usize> {
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"));
}

Expand All @@ -554,11 +559,12 @@ impl<'a, W: Write, R: Rng> Write for PartialInterruptingWriter<'a, W, R> {
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()
}
}
}

0 comments on commit 66bc806

Please sign in to comment.