More header encoding work
This commit is contained in:
@@ -92,18 +92,21 @@ impl Encoder {
|
|||||||
if let Some(resume) = resume {
|
if let Some(resume) = resume {
|
||||||
let len = dst.len();
|
let len = dst.len();
|
||||||
|
|
||||||
if let Some(ref value) = resume.value {
|
let res = match resume.value {
|
||||||
unimplemented!();
|
Some(ref value) => {
|
||||||
} else {
|
self.encode_header_without_name(
|
||||||
// Encode the header
|
&resume.index,
|
||||||
match self.encode_header(&resume.index, dst) {
|
value,
|
||||||
Err(EncoderError::BufferOverflow) => {
|
dst)
|
||||||
dst.truncate(len);
|
|
||||||
return Ok(Encode::Partial(resume));
|
|
||||||
}
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
Ok(_) => {}
|
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
self.encode_header(&resume.index, dst)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if try!(is_buffer_overflow(res)) {
|
||||||
|
dst.truncate(len);
|
||||||
|
return Ok(Encode::Partial(resume));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,11 +232,13 @@ impl Encoder {
|
|||||||
-> Result<(), EncoderError>
|
-> Result<(), EncoderError>
|
||||||
{
|
{
|
||||||
match *last {
|
match *last {
|
||||||
Index::Indexed(idx, ..) |
|
Index::Indexed(..) |
|
||||||
Index::Name(idx, ..) |
|
Index::Name(..) |
|
||||||
Index::Inserted(idx) |
|
Index::Inserted(..) |
|
||||||
Index::InsertedValue(idx, ..) =>
|
Index::InsertedValue(..) =>
|
||||||
{
|
{
|
||||||
|
let idx = self.table.resolve_idx(last);
|
||||||
|
|
||||||
try!(encode_not_indexed(
|
try!(encode_not_indexed(
|
||||||
idx,
|
idx,
|
||||||
value.as_ref(),
|
value.as_ref(),
|
||||||
@@ -744,6 +749,70 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
fn test_nameless_header() {
|
||||||
|
let mut encoder = Encoder::default();
|
||||||
|
|
||||||
|
let res = encode(&mut encoder, vec![
|
||||||
|
Header::Field {
|
||||||
|
name: Some("hello".parse().unwrap()),
|
||||||
|
value: HeaderValue::try_from_bytes(b"world").unwrap(),
|
||||||
|
},
|
||||||
|
Header::Field {
|
||||||
|
name: None,
|
||||||
|
value: HeaderValue::try_from_bytes(b"zomg").unwrap(),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(&[0x40, 0x80 | 4], &res[0..2]);
|
||||||
|
assert_eq!("hello", huff_decode(&res[2..6]));
|
||||||
|
assert_eq!(0x80 | 4, res[6]);
|
||||||
|
assert_eq!("world", huff_decode(&res[7..11]));
|
||||||
|
|
||||||
|
// Next is not indexed
|
||||||
|
assert_eq!(&[15, 47, 0x80 | 3], &res[11..14]);
|
||||||
|
assert_eq!("zomg", huff_decode(&res[14..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nameless_header_at_resume() {
|
||||||
|
let mut encoder = Encoder::default();
|
||||||
|
let mut dst = BytesMut::from(Vec::with_capacity(11));
|
||||||
|
|
||||||
|
let mut input = vec![
|
||||||
|
Header::Field {
|
||||||
|
name: Some("hello".parse().unwrap()),
|
||||||
|
value: HeaderValue::try_from_bytes(b"world").unwrap(),
|
||||||
|
},
|
||||||
|
Header::Field {
|
||||||
|
name: None,
|
||||||
|
value: HeaderValue::try_from_bytes(b"zomg").unwrap(),
|
||||||
|
},
|
||||||
|
].into_iter();
|
||||||
|
|
||||||
|
let resume = match encoder.encode(None, &mut input, &mut dst).unwrap() {
|
||||||
|
Encode::Partial(r) => r,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(&[0x40, 0x80 | 4], &dst[0..2]);
|
||||||
|
assert_eq!("hello", huff_decode(&dst[2..6]));
|
||||||
|
assert_eq!(0x80 | 4, dst[6]);
|
||||||
|
assert_eq!("world", huff_decode(&dst[7..11]));
|
||||||
|
|
||||||
|
dst.clear();
|
||||||
|
|
||||||
|
match encoder.encode(Some(resume), &mut input, &mut dst).unwrap() {
|
||||||
|
Encode::Full => {}
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next is not indexed
|
||||||
|
assert_eq!(&[15, 47, 0x80 | 3], &dst[0..3]);
|
||||||
|
assert_eq!("zomg", huff_decode(&dst[3..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn test_evicted_overflow() {
|
fn test_evicted_overflow() {
|
||||||
// Not sure what the best way to do this is.
|
// Not sure what the best way to do this is.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,6 +120,18 @@ impl Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_idx(&self, index: &Index) -> usize {
|
||||||
|
use self::Index::*;
|
||||||
|
|
||||||
|
match *index {
|
||||||
|
Indexed(idx, ..) => idx,
|
||||||
|
Name(idx, ..) => idx,
|
||||||
|
Inserted(idx) => idx + DYN_OFFSET,
|
||||||
|
InsertedValue(idx, _) => idx,
|
||||||
|
NotIndexed(_) => panic!("cannot resolve index"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Index the header in the HPACK table.
|
/// Index the header in the HPACK table.
|
||||||
pub fn index(&mut self, header: Header) -> Index {
|
pub fn index(&mut self, header: Header) -> Index {
|
||||||
// Check the static table
|
// Check the static table
|
||||||
|
|||||||
Reference in New Issue
Block a user