Skip to content

Commit 105d921

Browse files
larseggertmxindenCopilot
authored
fix: Replace qpack::Data with trait (mozilla#3013)
Co-authored-by: Max Inden <mail@max-inden.de> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 5530576 commit 105d921

7 files changed

Lines changed: 165 additions & 96 deletions

File tree

neqo-common/src/codec.rs

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ impl<'b> PartialEq<Decoder<'b>> for Decoder<'_> {
211211
}
212212

213213
/// Encoder is good for building data structures.
214-
#[derive(Clone, PartialEq, Eq)]
215214
pub struct Encoder<B = Vec<u8>> {
216215
buf: B,
217216
/// Tracks the starting position of the buffer when the [`Encoder`] is created.
@@ -220,6 +219,23 @@ pub struct Encoder<B = Vec<u8>> {
220219
start: usize,
221220
}
222221

222+
impl Clone for Encoder {
223+
fn clone(&self) -> Self {
224+
Self {
225+
buf: self.as_ref().to_vec(),
226+
start: 0,
227+
}
228+
}
229+
}
230+
231+
impl<B: Buffer> PartialEq for Encoder<B> {
232+
fn eq(&self, other: &Self) -> bool {
233+
self.as_ref() == other.as_ref()
234+
}
235+
}
236+
237+
impl<B: Buffer> Eq for Encoder<B> {}
238+
223239
impl<B: Buffer> Encoder<B> {
224240
/// Get the length of the [`Encoder`].
225241
///
@@ -409,6 +425,17 @@ impl Encoder<Vec<u8>> {
409425
Self::default()
410426
}
411427

428+
/// Skip the first `n` bytes from the encoder buffer without copying.
429+
/// This advances the internal offset, making those bytes inaccessible.
430+
///
431+
/// # Panics
432+
///
433+
/// Panics if `n` is greater than the current length of the encoder.
434+
pub fn skip(&mut self, n: usize) {
435+
assert!(n <= self.len(), "Cannot skip beyond buffer length");
436+
self.start += n;
437+
}
438+
412439
/// Static helper function for previewing the results of encoding without doing it.
413440
///
414441
/// # Panics
@@ -504,8 +531,11 @@ impl From<&[u8]> for Encoder {
504531
}
505532

506533
impl From<Encoder> for Vec<u8> {
507-
fn from(buf: Encoder) -> Self {
508-
buf.buf
534+
fn from(mut enc: Encoder) -> Self {
535+
if enc.start > 0 {
536+
enc.buf.drain(..enc.start);
537+
}
538+
enc.buf
509539
}
510540
}
511541

@@ -1195,6 +1225,26 @@ mod tests {
11951225
assert_eq!(Buffer::position(&buf), 0);
11961226
}
11971227

1228+
#[test]
1229+
fn encoder_skip() {
1230+
let mut enc = Encoder::from_hex("010203040506");
1231+
1232+
enc.skip(2);
1233+
assert_eq!(enc.len(), 4);
1234+
assert_eq!(enc.as_ref(), &[0x03, 0x04, 0x05, 0x06]);
1235+
1236+
enc.skip(4);
1237+
assert_eq!(enc.len(), 0);
1238+
assert!(enc.is_empty());
1239+
}
1240+
1241+
#[test]
1242+
#[should_panic(expected = "Cannot skip beyond buffer length")]
1243+
fn encoder_skip_too_much() {
1244+
let mut enc = Encoder::from_hex("0102");
1245+
enc.skip(3);
1246+
}
1247+
11981248
/// [`Encoder::as_decoder`] should only expose the bytes actively encoded through this
11991249
/// [`Encoder`], not all bytes of the underlying [`Buffer`].
12001250
#[test]
@@ -1208,4 +1258,42 @@ mod tests {
12081258
assert_eq!(decoder.as_ref(), &[5, 6, 7]);
12091259
assert_eq!(buffer, &[1, 2, 3, 4, 5, 6, 7]);
12101260
}
1261+
1262+
/// Converting an [`Encoder`] to [`Vec<u8>`] should respect the `start` offset.
1263+
#[test]
1264+
fn into_vec_respects_skip() {
1265+
let mut enc = Encoder::from_hex("010203040506");
1266+
enc.skip(2);
1267+
let v: Vec<u8> = enc.into();
1268+
assert_eq!(v, vec![0x03, 0x04, 0x05, 0x06]);
1269+
}
1270+
1271+
/// Converting an [`Encoder`] without skip should return the full buffer.
1272+
#[test]
1273+
fn into_vec_without_skip() {
1274+
let enc = Encoder::from_hex("010203");
1275+
let v: Vec<u8> = enc.into();
1276+
assert_eq!(v, vec![0x01, 0x02, 0x03]);
1277+
}
1278+
1279+
/// [`PartialEq`] should compare the logical view.
1280+
#[test]
1281+
fn partial_eq_respects_skip() {
1282+
let mut enc1 = Encoder::from_hex("010203040506");
1283+
enc1.skip(2);
1284+
let enc2 = Encoder::from_hex("03040506");
1285+
assert_eq!(enc1, enc2);
1286+
}
1287+
1288+
/// [`Clone`] should not clone skipped bytes.
1289+
#[test]
1290+
fn clone_respects_skip() {
1291+
let mut enc = Encoder::from_hex("010203040506");
1292+
enc.skip(2);
1293+
let cloned = enc.clone();
1294+
assert_eq!(cloned.as_ref(), &[0x03, 0x04, 0x05, 0x06]);
1295+
assert_eq!(cloned.len(), 4);
1296+
let v: Vec<u8> = cloned.into();
1297+
assert_eq!(v, vec![0x03, 0x04, 0x05, 0x06]);
1298+
}
12111299
}

neqo-qpack/src/decoder.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66

77
use std::fmt::{self, Display, Formatter};
88

9-
use neqo_common::{qdebug, Header};
9+
use neqo_common::{qdebug, Encoder, Header};
1010
use neqo_transport::{Connection, StreamId};
1111

1212
use crate::{
1313
decoder_instructions::DecoderInstruction,
1414
encoder_instructions::{DecodedEncoderInstruction, EncoderInstructionReader},
1515
header_block::{HeaderDecoder, HeaderDecoderResult},
16-
qpack_send_buf::Data,
1716
reader::{ReadByte, Reader, ReceiverConnWrapper},
1817
stats::Stats,
1918
table::HeaderTable,
@@ -28,7 +27,7 @@ pub struct Decoder {
2827
table: HeaderTable,
2928
acked_inserts: u64,
3029
max_entries: u64,
31-
send_buf: Data,
30+
send_buf: Encoder,
3231
local_stream_id: Option<StreamId>,
3332
max_table_size: u64,
3433
max_blocked_streams: usize,
@@ -43,7 +42,7 @@ impl Decoder {
4342
#[must_use]
4443
pub fn new(qpack_settings: &Settings) -> Self {
4544
qdebug!("Decoder: creating a new qpack decoder");
46-
let mut send_buf = Data::default();
45+
let mut send_buf = Encoder::default();
4746
send_buf.encode_varint(QPACK_UNI_STREAM_TYPE_DECODER);
4847
let max_blocked_streams = usize::from(qpack_settings.max_blocked_streams);
4948
Self {
@@ -179,11 +178,11 @@ impl Decoder {
179178
let r = conn
180179
.stream_send(
181180
self.local_stream_id.ok_or(Error::Internal)?,
182-
&self.send_buf[..],
181+
self.send_buf.as_ref(),
183182
)
184183
.map_err(|_| Error::DecoderStream)?;
185184
qdebug!("[{self}] {r} bytes sent");
186-
self.send_buf.read(r);
185+
self.send_buf.skip(r);
187186
}
188187
Ok(())
189188
}

neqo-qpack/src/decoder_instructions.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use neqo_transport::StreamId;
1414

1515
use crate::{
1616
prefix::{DECODER_HEADER_ACK, DECODER_INSERT_COUNT_INCREMENT, DECODER_STREAM_CANCELLATION},
17-
qpack_send_buf::Data,
17+
qpack_send_buf::Encoder,
1818
reader::{IntReader, ReadByte},
1919
Res,
2020
};
@@ -44,7 +44,7 @@ impl DecoderInstruction {
4444
}
4545
}
4646

47-
pub(crate) fn marshal(&self, enc: &mut Data) {
47+
pub(crate) fn marshal<T: Encoder>(&self, enc: &mut T) {
4848
match self {
4949
Self::InsertCountIncrement { increment } => {
5050
enc.encode_prefixed_encoded_int(DECODER_INSERT_COUNT_INCREMENT, *increment);
@@ -144,16 +144,17 @@ impl DecoderInstructionReader {
144144
#[cfg_attr(coverage_nightly, coverage(off))]
145145
mod test {
146146

147+
use neqo_common::Encoder;
147148
use neqo_transport::StreamId;
148149

149-
use super::{Data, DecoderInstruction, DecoderInstructionReader};
150+
use super::{DecoderInstruction, DecoderInstructionReader};
150151
use crate::{reader::test_receiver::TestReceiver, Error};
151152

152153
fn test_encoding_decoding(instruction: DecoderInstruction) {
153-
let mut buf = Data::default();
154+
let mut buf = Encoder::default();
154155
instruction.marshal(&mut buf);
155156
let mut test_receiver: TestReceiver = TestReceiver::default();
156-
test_receiver.write(&buf);
157+
test_receiver.write(buf.as_ref());
157158
let mut decoder = DecoderInstructionReader::new();
158159
assert_eq!(
159160
decoder.read_instructions(&mut test_receiver).unwrap(),
@@ -182,18 +183,18 @@ mod test {
182183
}
183184

184185
fn test_encoding_decoding_slow_reader(instruction: DecoderInstruction) {
185-
let mut buf = Data::default();
186+
let mut buf = Encoder::default();
186187
instruction.marshal(&mut buf);
187188
let mut test_receiver: TestReceiver = TestReceiver::default();
188189
let mut decoder = DecoderInstructionReader::new();
189190
for i in 0..buf.len() - 1 {
190-
test_receiver.write(&buf[i..=i]);
191+
test_receiver.write(&buf.as_ref()[i..=i]);
191192
assert_eq!(
192193
decoder.read_instructions(&mut test_receiver),
193194
Err(Error::NeedMoreData)
194195
);
195196
}
196-
test_receiver.write(&buf[buf.len() - 1..buf.len()]);
197+
test_receiver.write(&buf.as_ref()[buf.len() - 1..buf.len()]);
197198
assert_eq!(
198199
decoder.read_instructions(&mut test_receiver).unwrap(),
199200
instruction

neqo-qpack/src/encoder.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use crate::{
2020
encoder_instructions::EncoderInstruction,
2121
header_block::HeaderEncoder,
2222
qlog,
23-
qpack_send_buf::Data,
2423
reader::ReceiverConnWrapper,
2524
stats::Stats,
2625
table::{HeaderTable, LookupResult, ADDITIONAL_TABLE_ENTRY_SIZE},
@@ -281,14 +280,14 @@ impl Encoder {
281280
return Err(Error::DynamicTableFull);
282281
}
283282

284-
let mut buf = Data::default();
283+
let mut buf = neqo_common::Encoder::default();
285284
EncoderInstruction::InsertWithNameLiteral { name, value }
286285
.marshal(&mut buf, self.use_huffman);
287286

288287
let stream_id = self.local_stream.stream_id().ok_or(Error::Internal)?;
289288

290289
let sent = conn
291-
.stream_send_atomic(stream_id, &buf)
290+
.stream_send_atomic(stream_id, buf.as_ref())
292291
.map_err(|e| map_stream_send_atomic_error(&e))?;
293292
if !sent {
294293
return Err(Error::EncoderStreamBlocked);
@@ -321,9 +320,9 @@ impl Encoder {
321320
if cap < self.table.capacity() && !self.table.can_evict_to(cap) {
322321
return Err(Error::DynamicTableFull);
323322
}
324-
let mut buf = Data::default();
323+
let mut buf = neqo_common::Encoder::default();
325324
EncoderInstruction::Capacity { value: cap }.marshal(&mut buf, self.use_huffman);
326-
if !conn.stream_send_atomic(stream_id, &buf)? {
325+
if !conn.stream_send_atomic(stream_id, buf.as_ref())? {
327326
return Err(Error::EncoderStreamBlocked);
328327
}
329328
if self.table.set_capacity(cap).is_err() {
@@ -351,9 +350,9 @@ impl Encoder {
351350
Ok(())
352351
}
353352
LocalStreamState::Uninitialized(stream_id) => {
354-
let mut buf = Data::default();
353+
let mut buf = neqo_common::Encoder::default();
355354
buf.encode_varint(QPACK_UNI_STREAM_TYPE_ENCODER);
356-
if !conn.stream_send_atomic(stream_id, &buf[..])? {
355+
if !conn.stream_send_atomic(stream_id, buf.as_ref())? {
357356
return Err(Error::EncoderStreamBlocked);
358357
}
359358
self.local_stream = LocalStreamState::Initialized(stream_id);
@@ -596,7 +595,7 @@ mod tests {
596595
let buf = self
597596
.encoder
598597
.encode_header_block(&mut self.conn, headers, stream_id);
599-
assert_eq!(&buf[..], expected_encoding);
598+
assert_eq!(buf.as_ref(), expected_encoding);
600599
self.send_instructions(inst);
601600
}
602601

@@ -822,7 +821,7 @@ mod tests {
822821
let buf = encoder
823822
.encoder
824823
.encode_header_block(&mut encoder.conn, &t.headers, STREAM_1);
825-
assert_eq!(&buf[..], t.header_block);
824+
assert_eq!(buf.as_ref(), t.header_block);
826825
encoder.send_instructions(t.encoder_inst);
827826
}
828827
}
@@ -896,7 +895,7 @@ mod tests {
896895
let buf = encoder
897896
.encoder
898897
.encode_header_block(&mut encoder.conn, &t.headers, STREAM_1);
899-
assert_eq!(&buf[..], t.header_block);
898+
assert_eq!(buf.as_ref(), t.header_block);
900899
encoder.send_instructions(t.encoder_inst);
901900
}
902901
}
@@ -968,7 +967,7 @@ mod tests {
968967
&[Header::new("content-length", "1234")],
969968
STREAM_1,
970969
);
971-
assert_eq!(&buf[..], ENCODE_INDEXED_REF_DYNAMIC);
970+
assert_eq!(buf.as_ref(), ENCODE_INDEXED_REF_DYNAMIC);
972971
encoder.send_instructions(&[]);
973972

974973
// insert "content-length: 12345 which will fail because the entry in the table cannot be

neqo-qpack/src/encoder_instructions.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
ENCODER_CAPACITY, ENCODER_DUPLICATE, ENCODER_INSERT_WITH_NAME_LITERAL,
1717
ENCODER_INSERT_WITH_NAME_REF_DYNAMIC, ENCODER_INSERT_WITH_NAME_REF_STATIC, NO_PREFIX,
1818
},
19-
qpack_send_buf::Data,
19+
qpack_send_buf::Encoder,
2020
reader::{IntReader, LiteralReader, ReadByte, Reader},
2121
Res,
2222
};
@@ -52,7 +52,7 @@ pub enum EncoderInstruction<'a> {
5252
}
5353

5454
impl EncoderInstruction<'_> {
55-
pub(crate) fn marshal(&self, enc: &mut Data, use_huffman: bool) {
55+
pub(crate) fn marshal<T: Encoder>(&self, enc: &mut T, use_huffman: bool) {
5656
match self {
5757
Self::Capacity { value } => {
5858
enc.encode_prefixed_encoded_int(ENCODER_CAPACITY, *value);
@@ -297,14 +297,14 @@ impl EncoderInstructionReader {
297297
#[cfg_attr(coverage_nightly, coverage(off))]
298298
mod test {
299299

300-
use super::{Data, EncoderInstruction, EncoderInstructionReader};
300+
use super::{EncoderInstruction, EncoderInstructionReader};
301301
use crate::{reader::test_receiver::TestReceiver, Error};
302302

303303
fn test_encoding_decoding(instruction: &EncoderInstruction, use_huffman: bool) {
304-
let mut buf = Data::default();
304+
let mut buf = neqo_common::Encoder::default();
305305
instruction.marshal(&mut buf, use_huffman);
306306
let mut test_receiver: TestReceiver = TestReceiver::default();
307-
test_receiver.write(&buf);
307+
test_receiver.write(buf.as_ref());
308308
let mut reader = EncoderInstructionReader::new();
309309
assert_eq!(
310310
reader.read_instructions(&mut test_receiver).unwrap(),
@@ -395,18 +395,18 @@ mod test {
395395
}
396396

397397
fn test_encoding_decoding_slow_reader(instruction: &EncoderInstruction, use_huffman: bool) {
398-
let mut buf = Data::default();
398+
let mut buf = neqo_common::Encoder::default();
399399
instruction.marshal(&mut buf, use_huffman);
400400
let mut test_receiver: TestReceiver = TestReceiver::default();
401401
let mut decoder = EncoderInstructionReader::new();
402402
for i in 0..buf.len() - 1 {
403-
test_receiver.write(&buf[i..=i]);
403+
test_receiver.write(&buf.as_ref()[i..=i]);
404404
assert_eq!(
405405
decoder.read_instructions(&mut test_receiver),
406406
Err(Error::NeedMoreData)
407407
);
408408
}
409-
test_receiver.write(&buf[buf.len() - 1..buf.len()]);
409+
test_receiver.write(&buf.as_ref()[buf.len() - 1..buf.len()]);
410410
assert_eq!(
411411
decoder.read_instructions(&mut test_receiver).unwrap(),
412412
instruction.into()

0 commit comments

Comments
 (0)