Handle chunked HTTP correctly
This commit is contained in:
parent
dc2819e028
commit
1d62dae785
6 changed files with 799 additions and 198 deletions
130
src/util.rs
130
src/util.rs
|
|
@ -0,0 +1,130 @@
|
|||
use std::iter::Peekable;
|
||||
|
||||
use crate::record::Direction;
|
||||
|
||||
fn hex_digit(c: u8) -> u32 {
|
||||
((c & !(16 | 32 | 64)) + ((c & 64) >> 6) * 9) as _
|
||||
}
|
||||
|
||||
pub fn parse_hex(s: &[u8]) -> u32 {
|
||||
let mut r = 0;
|
||||
for i in s.iter() {
|
||||
r <<= 4;
|
||||
r |= hex_digit(*i);
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
pub fn is_hex(s: &[u8]) -> bool {
|
||||
s.iter().all(|c| {
|
||||
let c = *c | 32;
|
||||
(c >= b'a' && c <= b'f') || (c >= b'0' && c <= b'9')
|
||||
})
|
||||
}
|
||||
|
||||
/// Print ASCII if possible
|
||||
pub fn print_bin(s: &[u8]) {
|
||||
if let Ok(s) = str::from_utf8(s) {
|
||||
println!("{s}");
|
||||
} else {
|
||||
let mut buf = String::new();
|
||||
for c in s {
|
||||
if c.is_ascii_control() && *c != b'\n' {
|
||||
continue;
|
||||
}
|
||||
if let Some(c) = c.as_ascii() {
|
||||
buf.push_str(c.as_str());
|
||||
} else {
|
||||
for c in std::ascii::escape_default(*c) {
|
||||
buf.push(c.as_ascii().unwrap().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{buf}");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResponseStreamer<I: Iterator>(Peekable<I>);
|
||||
|
||||
impl<'a, I: Iterator> ResponseStreamer<I> {
|
||||
pub fn new(inner: I) -> Self {
|
||||
Self(inner.peekable())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Iterator<Item = &'a (Direction, Vec<u8>)>> Iterator for ResponseStreamer<I> {
|
||||
type Item = (&'a Direction, Vec<&'a Vec<u8>>);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let (direction, first_item) = self.0.next()?;
|
||||
let mut items = vec![first_item];
|
||||
while let Some((item_direction, _item)) = self.0.peek()
|
||||
&& item_direction == direction
|
||||
{
|
||||
items.push(&self.0.next().unwrap().1);
|
||||
}
|
||||
Some((direction, items))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_hex_digit() {
|
||||
assert_eq!(hex_digit(b'0'), 0);
|
||||
assert_eq!(hex_digit(b'1'), 1);
|
||||
assert_eq!(hex_digit(b'2'), 2);
|
||||
assert_eq!(hex_digit(b'3'), 3);
|
||||
assert_eq!(hex_digit(b'4'), 4);
|
||||
assert_eq!(hex_digit(b'5'), 5);
|
||||
assert_eq!(hex_digit(b'6'), 6);
|
||||
assert_eq!(hex_digit(b'7'), 7);
|
||||
assert_eq!(hex_digit(b'8'), 8);
|
||||
assert_eq!(hex_digit(b'9'), 9);
|
||||
assert_eq!(hex_digit(b'a'), 10);
|
||||
assert_eq!(hex_digit(b'b'), 11);
|
||||
assert_eq!(hex_digit(b'c'), 12);
|
||||
assert_eq!(hex_digit(b'd'), 13);
|
||||
assert_eq!(hex_digit(b'e'), 14);
|
||||
assert_eq!(hex_digit(b'f'), 15);
|
||||
assert_eq!(hex_digit(b'A'), 10);
|
||||
assert_eq!(hex_digit(b'B'), 11);
|
||||
assert_eq!(hex_digit(b'C'), 12);
|
||||
assert_eq!(hex_digit(b'D'), 13);
|
||||
assert_eq!(hex_digit(b'E'), 14);
|
||||
assert_eq!(hex_digit(b'F'), 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_hex() {
|
||||
assert_eq!(parse_hex(b"abc123"), 0xabc123);
|
||||
assert_eq!(parse_hex(b"1"), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_hex() {
|
||||
assert!(is_hex(b"0"));
|
||||
assert!(is_hex(b"1"));
|
||||
assert!(is_hex(b"2"));
|
||||
assert!(is_hex(b"3"));
|
||||
assert!(is_hex(b"4"));
|
||||
assert!(is_hex(b"5"));
|
||||
assert!(is_hex(b"6"));
|
||||
assert!(is_hex(b"7"));
|
||||
assert!(is_hex(b"8"));
|
||||
assert!(is_hex(b"9"));
|
||||
assert!(is_hex(b"a"));
|
||||
assert!(is_hex(b"b"));
|
||||
assert!(is_hex(b"c"));
|
||||
assert!(is_hex(b"d"));
|
||||
assert!(is_hex(b"e"));
|
||||
assert!(is_hex(b"f"));
|
||||
assert!(is_hex(b"A"));
|
||||
assert!(is_hex(b"B"));
|
||||
assert!(is_hex(b"C"));
|
||||
assert!(is_hex(b"D"));
|
||||
assert!(is_hex(b"E"));
|
||||
assert!(is_hex(b"F"));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue