// "d" not consumed since it's not a full chunk
assert_eq!(3, enc.write(b"abcd").unwrap()); let _ = enc.finish().unwrap();
}
assert_eq!(&c.get_ref()[..], NO_PAD_ENGINE.encode("abc").as_bytes());
assert_eq!(4, c.get_ref().len());
}
assert_eq!(1, enc.write(b"a").unwrap()); // completes partial chunk, and another chunk, with one more partial chunk that's not // consumed
assert_eq!(5, enc.write(b"bcdefe").unwrap()); let _ = enc.finish().unwrap();
}
assert_eq!(&c.get_ref()[..], NO_PAD_ENGINE.encode("abcdef").as_bytes());
assert_eq!(8, c.get_ref().len());
}
for i in0..size {
orig_data.clear();
stream_encoded.clear();
normal_encoded.clear();
for _ in0..size {
orig_data.push(rng.gen());
}
let engine = random_engine(&mut rng);
engine.encode_string(&orig_data, &mut normal_encoded);
{ letmut stream_encoder = EncoderWriter::new(&mut stream_encoded, &engine); // Write the first i bytes, then the rest
stream_encoder.write_all(&orig_data[0..i]).unwrap();
stream_encoder.write_all(&orig_data[i..]).unwrap();
}
#[test] fn encode_random_config_matches_normal_encode_reasonable_input_len() { // choose up to 2 * buf size, so ~half the time it'll use a full buffer
do_encode_random_config_matches_normal_encode(super::encoder::BUF_SIZE * 2);
}
letmut stream_encoder = EncoderWriter::new(&mut interrupting_writer, &engine); letmut bytes_consumed = 0; while bytes_consumed < orig_len { // use short inputs since we want to use `extra` a lot as that's what needs rollback // when errors occur let input_len: usize = cmp::min(rng.gen_range(0..10), orig_len - bytes_consumed);
letmut stream_encoder = EncoderWriter::new(&mut partial_writer, &engine); letmut bytes_consumed = 0; while bytes_consumed < orig_len { // 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]);
// 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");
}
},
}
}
/// 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<()> { letmut bytes_consumed = 0;
while bytes_consumed < buf.len() { let res = w.write(&buf[bytes_consumed..]);
match res {
Ok(len) => bytes_consumed += len,
Err(e) => match e.kind() {
io::ErrorKind::Interrupted => continue,
_ => return Err(e),
},
}
}
/// A `Write` implementation that returns Interrupted some fraction of the time, randomly. struct InterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> {
w: &'a mut W,
rng: &'a mut R, /// In [0, 1]. If a random number in [0, 1] is `<= threshold`, `Write` methods will return /// an `Interrupted` error
fraction: f64,
}
/// A `Write` implementation that sometimes will only write part of its input. struct PartialInterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> {
w: &'a mut W,
rng: &'a mut R, /// 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,
}
ifself.rng.gen_range(0.0..1.0) <= self.full_input_fraction || buf.is_empty() { // pass through the buf untouched self.w.write(buf)
} else { // only use a prefix of it self.w
.write(&buf[0..(self.rng.gen_range(0..(buf.len() - 1)))])
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.