Skip to content

Instantly share code, notes, and snippets.

@lffg
Created February 20, 2023 01:56
Show Gist options
  • Save lffg/77d21c45026bd482f083f99699c7c466 to your computer and use it in GitHub Desktop.
Save lffg/77d21c45026bd482f083f99699c7c466 to your computer and use it in GitHub Desktop.
use std::{
io::{Cursor, Seek, SeekFrom},
ops::RangeBounds,
};
/// Tries to get a UTF-8 string from the given buffer at the provided range.
fn str_from_utf8_range(buf: &[u8], range: impl RangeBounds<usize>) -> Option<&str> {
buf.get((range.start_bound().cloned(), range.end_bound().cloned()))
.map(|slice| std::str::from_utf8(slice).expect("valid utf8"))
}
/// Returns the remaining slice as a string slice. Panics if encounters invalid
/// UTF-8 bytes.
fn rem_str<T: AsRef<[u8]>>(cur: &mut Cursor<T>) -> Option<&str> {
str_from_utf8_range(cur.get_ref().as_ref(), (cur.position() as usize)..)
}
/// Gets `n` bytes from the cursor and advances `n`. Panics if the underlying
/// value doesn't have enough capacity for a +n seek.
fn get_str<T: AsRef<[u8]>>(cur: &mut Cursor<T>, n: usize) -> String {
let buf = cur.get_ref().as_ref();
let hi = cur.position() as usize + n;
assert!(hi <= buf.len()); // high bound must be within buf's bounds
let eaten = str_from_utf8_range(buf, (cur.position() as usize)..hi)
// SAFETY: The assertion above ensures one is always within bounds.
.unwrap()
.to_owned();
// SAFETY: No I/O is involved.
cur.seek(SeekFrom::Current(n as i64)).unwrap();
eaten
}
fn main() {
let buf = b"hello world";
let mut cur = Cursor::new(buf);
println!("remaining is [{:?}]", rem_str(&mut cur));
println!(
"got [{}], remaining is [{:?}]",
get_str(&mut cur, 5),
rem_str(&mut cur)
);
println!(
"got [{}], remaining is [{:?}]",
get_str(&mut cur, 1),
rem_str(&mut cur)
);
println!(
"got [{}], remaining is [{:?}]",
get_str(&mut cur, 5),
rem_str(&mut cur)
);
println!(
"got [{}], remaining is [{:?}]",
get_str(&mut cur, 0),
rem_str(&mut cur)
);
// Assuming one never seeks past the end of the buffer, `rem_str` will
// always return `Some("")`.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment