--- src/lib.rs.before
+++ src/lib.rs.experiment
@@ -196,6 +196,7 @@
date_at: Cell<u64>,
read_buffer: RefCell<Vec<u8>>,
header_names: RefCell<HashMap<Vec<u8>, Py<PyBytes>>>,
+ header_pairs: RefCell<HashMap<Vec<u8>, Py<pyo3::types::PyTuple>>>,
}
impl State {
fn id(&self) -> u64 {
@@ -537,7 +538,10 @@
)?;
let headers = PyList::new(
py,
- h.headers().map(|(n, v)| {
+ h.headers().map(|(n, v, key)| {
+ if let Some(pair) = self.header_pairs.borrow().get(key) {
+ return pair.clone_ref(py);
+ }
let cached = self.header_names.borrow().get(n).map(|v| v.clone_ref(py));
let name = if let Some(name) = cached {
name
@@ -550,7 +554,16 @@
}
name
};
- (name, PyBytes::new(py, v))
+ let pair = (name, PyBytes::new(py, v))
+ .into_pyobject(py)
+ .expect("tuple construction")
+ .unbind();
+ if key.len() <= 256 && self.header_pairs.borrow().len() < 512 {
+ self.header_pairs
+ .borrow_mut()
+ .insert(key.to_vec(), pair.clone_ref(py));
+ }
+ pair
}),
)?;
scope.set_item(pyo3::intern!(py, "headers"), headers)?;
@@ -1271,6 +1284,7 @@
date_at: Cell::new(0),
read_buffer: RefCell::new(vec![0; 65536]),
header_names: RefCell::new(HashMap::new()),
+ header_pairs: RefCell::new(HashMap::new()),
}),
})
}
--- src/http.rs.before
+++ src/http.rs.experiment
@@ -41,10 +41,14 @@
pub fn target(&self) -> &[u8] {
&self.wire[self.target.clone()]
}
- pub fn headers(&self) -> impl ExactSizeIterator<Item = (&[u8], &[u8])> {
- self.fields
- .iter()
- .map(|(n, v)| (&self.wire[n.clone()], &self.wire[v.clone()]))
+ pub fn headers(&self) -> impl ExactSizeIterator<Item = (&[u8], &[u8], &[u8])> {
+ self.fields.iter().map(|(n, v)| {
+ (
+ &self.wire[n.clone()],
+ &self.wire[v.clone()],
+ &self.wire[n.start..v.end],
+ )
+ })
}
}
pub enum Body {
@@ -203,9 +207,9 @@
}
fields.retain(|(n, _)| &wire[n.clone()] != b"host");
let start = wire.len();
- wire.extend_from_slice(b"host");
+ wire.extend_from_slice(b"host:");
wire.extend_from_slice(authority);
- fields.insert(0, (start..start + 4, start + 4..wire.len()));
+ fields.insert(0, (start..start + 4, start + 5..wire.len()));
let path = &rest[n..];
target_span = if path.is_empty() || path[0] == b'?' {
let start = wire.len();