Add `put_bytes_min` and `space_remaining` methods
Pnicking on oversized slice is useful to catch errors in code that's supposed to know the exact sizes but this is undesirable in code that doesn't. These two methods help with handling the case when `buf.len()` is not known upfront.
This commit is contained in:
parent
55b93e95f5
commit
a6ecc58a5e
|
@ -177,15 +177,25 @@ impl<T: AsOutBytes> BufEncoder<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(rust_v_1_46, track_caller)]
|
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||||
pub fn put_bytes(&mut self, bytes: &[u8], case: Case) {
|
pub fn put_bytes(&mut self, bytes: &[u8], case: Case) {
|
||||||
// Panic if the result wouldn't fit address space to not waste time and give the optimizer
|
assert!(bytes.len() <= self.space_remaining());
|
||||||
// more opportunities.
|
|
||||||
let double_len = bytes.len().checked_mul(2).expect("overflow");
|
|
||||||
assert!(double_len <= self.buf.as_out_bytes().len() - self.pos);
|
|
||||||
for byte in bytes {
|
for byte in bytes {
|
||||||
self.put_byte(*byte, case);
|
self.put_byte(*byte, case);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encodes as many `bytes` as fit into the buffer as hex and return the remainder.
|
||||||
|
///
|
||||||
|
/// This method works just like `put_bytes` but instead of panicking it returns the unwritten
|
||||||
|
/// bytes. The method returns an empty slice if all bytes were written
|
||||||
|
#[must_use = "this may write only part of the input buffer"]
|
||||||
|
#[inline]
|
||||||
|
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||||
|
pub fn put_bytes_min<'a>(&mut self, bytes: &'a [u8], case: Case) -> &'a [u8] {
|
||||||
|
let to_write = self.space_remaining().min(bytes.len());
|
||||||
|
self.put_bytes(&bytes[..to_write], case);
|
||||||
|
&bytes[to_write..]
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if no more bytes can be written into the buffer.
|
/// Returns true if no more bytes can be written into the buffer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_full(&self) -> bool { self.pos == self.buf.as_out_bytes().len() }
|
pub fn is_full(&self) -> bool { self.pos == self.buf.as_out_bytes().len() }
|
||||||
|
@ -200,6 +210,14 @@ impl<T: AsOutBytes> BufEncoder<T> {
|
||||||
/// Resets the buffer to become empty.
|
/// Resets the buffer to become empty.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear(&mut self) { self.pos = 0; }
|
pub fn clear(&mut self) { self.pos = 0; }
|
||||||
|
|
||||||
|
/// How many bytes can be written to this buffer.
|
||||||
|
///
|
||||||
|
/// Note that this returns the number of bytes before encoding, not number of hex digits.
|
||||||
|
#[inline]
|
||||||
|
pub fn space_remaining(&self) -> usize {
|
||||||
|
(self.buf.as_out_bytes().len() - self.pos) / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -218,13 +236,17 @@ mod tests {
|
||||||
fn single_byte_exact_buf() {
|
fn single_byte_exact_buf() {
|
||||||
let mut buf = [0u8; 2];
|
let mut buf = [0u8; 2];
|
||||||
let mut encoder = BufEncoder::new(&mut buf);
|
let mut encoder = BufEncoder::new(&mut buf);
|
||||||
|
assert_eq!(encoder.space_remaining(), 1);
|
||||||
encoder.put_byte(42, Case::Lower);
|
encoder.put_byte(42, Case::Lower);
|
||||||
assert_eq!(encoder.as_str(), "2a");
|
assert_eq!(encoder.as_str(), "2a");
|
||||||
|
assert_eq!(encoder.space_remaining(), 0);
|
||||||
assert!(encoder.is_full());
|
assert!(encoder.is_full());
|
||||||
encoder.clear();
|
encoder.clear();
|
||||||
|
assert_eq!(encoder.space_remaining(), 1);
|
||||||
assert!(!encoder.is_full());
|
assert!(!encoder.is_full());
|
||||||
encoder.put_byte(42, Case::Upper);
|
encoder.put_byte(42, Case::Upper);
|
||||||
assert_eq!(encoder.as_str(), "2A");
|
assert_eq!(encoder.as_str(), "2A");
|
||||||
|
assert_eq!(encoder.space_remaining(), 0);
|
||||||
assert!(encoder.is_full());
|
assert!(encoder.is_full());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,12 +254,16 @@ mod tests {
|
||||||
fn single_byte_oversized_buf() {
|
fn single_byte_oversized_buf() {
|
||||||
let mut buf = [0u8; 4];
|
let mut buf = [0u8; 4];
|
||||||
let mut encoder = BufEncoder::new(&mut buf);
|
let mut encoder = BufEncoder::new(&mut buf);
|
||||||
|
assert_eq!(encoder.space_remaining(), 2);
|
||||||
encoder.put_byte(42, Case::Lower);
|
encoder.put_byte(42, Case::Lower);
|
||||||
|
assert_eq!(encoder.space_remaining(), 1);
|
||||||
assert_eq!(encoder.as_str(), "2a");
|
assert_eq!(encoder.as_str(), "2a");
|
||||||
assert!(!encoder.is_full());
|
assert!(!encoder.is_full());
|
||||||
encoder.clear();
|
encoder.clear();
|
||||||
|
assert_eq!(encoder.space_remaining(), 2);
|
||||||
encoder.put_byte(42, Case::Upper);
|
encoder.put_byte(42, Case::Upper);
|
||||||
assert_eq!(encoder.as_str(), "2A");
|
assert_eq!(encoder.as_str(), "2A");
|
||||||
|
assert_eq!(encoder.space_remaining(), 1);
|
||||||
assert!(!encoder.is_full());
|
assert!(!encoder.is_full());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +272,9 @@ mod tests {
|
||||||
let mut buf = [0u8; 4];
|
let mut buf = [0u8; 4];
|
||||||
let mut encoder = BufEncoder::new(&mut buf);
|
let mut encoder = BufEncoder::new(&mut buf);
|
||||||
encoder.put_byte(42, Case::Lower);
|
encoder.put_byte(42, Case::Lower);
|
||||||
|
assert_eq!(encoder.space_remaining(), 1);
|
||||||
encoder.put_byte(255, Case::Lower);
|
encoder.put_byte(255, Case::Lower);
|
||||||
|
assert_eq!(encoder.space_remaining(), 0);
|
||||||
assert_eq!(encoder.as_str(), "2aff");
|
assert_eq!(encoder.as_str(), "2aff");
|
||||||
assert!(encoder.is_full());
|
assert!(encoder.is_full());
|
||||||
encoder.clear();
|
encoder.clear();
|
||||||
|
@ -257,6 +285,22 @@ mod tests {
|
||||||
assert!(encoder.is_full());
|
assert!(encoder.is_full());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn put_bytes_min() {
|
||||||
|
let mut buf = [0u8; 2];
|
||||||
|
let mut encoder = BufEncoder::new(&mut buf);
|
||||||
|
let remainder = encoder.put_bytes_min(b"", Case::Lower);
|
||||||
|
assert_eq!(remainder, b"");
|
||||||
|
assert_eq!(encoder.as_str(), "");
|
||||||
|
let remainder = encoder.put_bytes_min(b"*", Case::Lower);
|
||||||
|
assert_eq!(remainder, b"");
|
||||||
|
assert_eq!(encoder.as_str(), "2a");
|
||||||
|
encoder.clear();
|
||||||
|
let remainder = encoder.put_bytes_min(&[42, 255], Case::Lower);
|
||||||
|
assert_eq!(remainder, &[255]);
|
||||||
|
assert_eq!(encoder.as_str(), "2a");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn same_as_fmt() {
|
fn same_as_fmt() {
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
|
|
Loading…
Reference in New Issue