Skip to content

Commit 4324ead

Browse files
committed
Test this and that
1 parent f1f19a9 commit 4324ead

1 file changed

Lines changed: 45 additions & 16 deletions

File tree

src/lib.rs

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,18 @@ impl<'de> dec::Read<'de> for SliceReader<'de> {
5353

5454
#[inline]
5555
fn fill<'b>(&'b mut self, want: usize) -> Result<dec::Reference<'de, 'b>, Self::Error> {
56-
let len = core::cmp::min(self.buf.len(), want);
57-
Ok(dec::Reference::Long(&self.buf[..len]))
56+
let buf = self.buf;
57+
let buf_len = buf.len();
58+
let len = if buf_len < want { buf_len } else { want };
59+
Ok(dec::Reference::Long(&buf[..len]))
5860
}
5961

6062
#[inline]
6163
fn advance(&mut self, n: usize) {
62-
let len = core::cmp::min(self.buf.len(), n);
63-
self.buf = &self.buf[len..];
64+
let buf = self.buf;
65+
let buf_len = buf.len();
66+
let len = if buf_len < n { buf_len } else { n };
67+
self.buf = &buf[len..];
6468
}
6569
}
6670

@@ -221,9 +225,9 @@ where
221225
}
222226
major::MAP => {
223227
let len = types::Map::len(r)?.expect("contains length");
224-
let dict = PyDict::new(py);
225-
226228
let mut prev_key: Option<&[u8]> = None;
229+
230+
let mut items: Vec<(Py<PyAny>, Py<PyAny>)> = Vec::with_capacity(len);
227231
for _ in 0..len {
228232
// DAG-CBOR keys are always strings. Python does the UTF-8 validation when creating
229233
// the string.
@@ -242,9 +246,17 @@ where
242246
prev_key = Some(key);
243247

244248
let value_py = decode_dag_cbor_to_pyobject(py, r, depth + 1)?;
245-
dict.set_item(key_py, value_py)?;
249+
250+
items.push((key_py.unbind().into(), value_py));
251+
}
252+
253+
let seq = PyList::empty(py);
254+
for (key, value) in items {
255+
let pair = PyTuple::new(py, &[key, value])?;
256+
seq.append(pair)?;
246257
}
247258

259+
let dict = PyDict::from_sequence(&seq)?;
248260
dict.into_pyobject(py)?.into()
249261
}
250262
major::TAG => {
@@ -429,18 +441,35 @@ where
429441
let mut shift = 0;
430442

431443
loop {
432-
let byte =
433-
peek_one(r).map_err(|_| anyhow!("Unexpected EOF while reading ULEB128 number."))?;
434-
r.advance(1);
444+
// Read up to 10 bytes at once (max length of u64 LEB128)
445+
let reference = r
446+
.fill(10)
447+
.map_err(|_| anyhow!("Unexpected EOF while reading ULEB128 number."))?;
448+
let buf = reference.as_ref();
449+
450+
if buf.is_empty() {
451+
return Err(anyhow!("Unexpected EOF while reading ULEB128 number."));
452+
}
435453

436-
if (byte & 0x80) == 0 {
437-
result |= (byte as u64) << shift;
438-
return Ok(result);
439-
} else {
440-
result |= (byte as u64 & 0x7F) << shift;
454+
let mut consumed = 0;
455+
for &byte in buf {
456+
consumed += 1;
457+
458+
if (byte & 0x80) == 0 {
459+
result |= (byte as u64) << shift;
460+
r.advance(consumed);
461+
return Ok(result);
462+
} else {
463+
result |= (byte as u64 & 0x7F) << shift;
464+
shift += 7;
465+
if shift >= 64 {
466+
return Err(anyhow!("ULEB128 is too large for u64"));
467+
}
468+
}
441469
}
442470

443-
shift += 7;
471+
// All bytes in this chunk had continuation bit set; advance and continue
472+
r.advance(consumed);
444473
}
445474
}
446475

0 commit comments

Comments
 (0)