1const CONTINUATION_BIT: u8 = 1 << 7;
45#[cfg(feature = "read-core")]
46const SIGN_BIT: u8 = 1 << 6;
47
48#[inline]
49fn low_bits_of_byte(byte: u8) -> u8 {
50 byte & !CONTINUATION_BIT
51}
52
53#[inline]
54#[allow(dead_code)]
55fn low_bits_of_u64(val: u64) -> u8 {
56 let byte = val & u64::from(u8::MAX);
57 low_bits_of_byte(byte as u8)
58}
59
60#[cfg(feature = "read-core")]
63pub mod read {
64 use super::{CONTINUATION_BIT, SIGN_BIT, low_bits_of_byte};
65 use crate::read::{Error, Reader, Result};
66
67 pub fn skip<R: Reader>(r: &mut R) -> Result<()> {
69 loop {
70 let byte = r.read_u8()?;
71 if byte & CONTINUATION_BIT == 0 {
72 return Ok(());
73 }
74 }
75 }
76
77 pub fn unsigned<R: Reader>(r: &mut R) -> Result<u64> {
80 let byte = r.read_u8()?;
83 if byte & CONTINUATION_BIT == 0 {
84 return Ok(u64::from(byte));
85 }
86 let mut result = u64::from(low_bits_of_byte(byte));
87 let mut shift = 7;
88
89 loop {
90 let byte = r.read_u8()?;
91 if shift == 63 && byte != 0x00 && byte != 0x01 {
92 return Err(Error::BadUnsignedLeb128);
93 }
94
95 let low_bits = u64::from(low_bits_of_byte(byte));
96 result |= low_bits << shift;
97
98 if byte & CONTINUATION_BIT == 0 {
99 return Ok(result);
100 }
101
102 shift += 7;
103 }
104 }
105
106 pub fn u16<R: Reader>(r: &mut R) -> Result<u16> {
109 let byte = r.read_u8()?;
110 if byte & CONTINUATION_BIT == 0 {
111 return Ok(u16::from(byte));
112 }
113
114 let mut result = u16::from(low_bits_of_byte(byte));
115 let byte = r.read_u8()?;
116 result |= u16::from(low_bits_of_byte(byte)) << 7;
117 if byte & CONTINUATION_BIT == 0 {
118 return Ok(result);
119 }
120
121 let byte = r.read_u8()?;
122 if byte > 0x03 {
123 return Err(Error::BadUnsignedLeb128);
124 }
125 result += u16::from(byte) << 14;
126 Ok(result)
127 }
128
129 pub fn signed<R: Reader>(r: &mut R) -> Result<i64> {
132 let mut result = 0;
133 let mut shift = 0;
134 let size = 64;
135 let mut byte;
136
137 loop {
138 byte = r.read_u8()?;
139 if shift == 63 && byte != 0x00 && byte != 0x7f {
140 return Err(Error::BadSignedLeb128);
141 }
142
143 let low_bits = i64::from(low_bits_of_byte(byte));
144 result |= low_bits << shift;
145 shift += 7;
146
147 if byte & CONTINUATION_BIT == 0 {
148 break;
149 }
150 }
151
152 if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
153 result |= !0 << shift;
155 }
156
157 Ok(result)
158 }
159}
160
161pub mod write {
163 use super::{CONTINUATION_BIT, low_bits_of_u64};
164
165 #[derive(Debug, Clone, Copy)]
169 pub struct Leb128 {
170 bytes: [u8; 10],
171 len: u8,
172 }
173
174 impl Leb128 {
175 pub fn bytes(&self) -> &[u8] {
177 &self.bytes[..self.len as usize]
178 }
179
180 #[allow(clippy::len_without_is_empty)]
182 pub fn len(&self) -> usize {
183 self.len as usize
184 }
185
186 pub fn unsigned(mut val: u64) -> Self {
188 let mut bytes = [0; 10];
189 let mut len = 0;
190 loop {
191 let mut byte = low_bits_of_u64(val);
192 val >>= 7;
193 if val != 0 {
194 byte |= CONTINUATION_BIT;
196 }
197
198 bytes[len] = byte;
199 len += 1;
200
201 if val == 0 {
202 return Leb128 {
203 bytes,
204 len: len as u8,
205 };
206 }
207 }
208 }
209
210 pub fn signed(mut val: i64) -> Self {
212 let mut bytes = [0; 10];
213 let mut len = 0;
214 loop {
215 let mut byte = val as u8;
216 val >>= 6;
218 let done = val == 0 || val == -1;
219 if done {
220 byte &= !CONTINUATION_BIT;
221 } else {
222 val >>= 1;
224 byte |= CONTINUATION_BIT;
226 }
227
228 bytes[len] = byte;
229 len += 1;
230
231 if done {
232 return Leb128 {
233 bytes,
234 len: len as u8,
235 };
236 }
237 }
238 }
239
240 #[cfg(feature = "std")]
244 pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<usize> {
245 w.write_all(self.bytes())?;
246 Ok(self.len())
247 }
248 }
249
250 #[cfg(feature = "std")]
254 pub fn unsigned<W>(w: &mut W, val: u64) -> Result<usize, std::io::Error>
255 where
256 W: std::io::Write,
257 {
258 Leb128::unsigned(val).write(w)
259 }
260
261 pub fn uleb128_size(mut val: u64) -> usize {
263 let mut size = 0;
264 loop {
265 val >>= 7;
266 size += 1;
267 if val == 0 {
268 return size;
269 }
270 }
271 }
272
273 #[cfg(feature = "std")]
277 pub fn signed<W>(w: &mut W, val: i64) -> Result<usize, std::io::Error>
278 where
279 W: std::io::Write,
280 {
281 Leb128::signed(val).write(w)
282 }
283
284 pub fn sleb128_size(mut val: i64) -> usize {
286 let mut size = 0;
287 loop {
288 val >>= 6;
289 let done = val == 0 || val == -1;
290 val >>= 1;
291 size += 1;
292 if done {
293 return size;
294 }
295 }
296 }
297}
298
299#[cfg(test)]
300#[cfg(all(feature = "read", feature = "write"))]
301mod tests {
302 use super::{CONTINUATION_BIT, low_bits_of_byte, low_bits_of_u64, read, write};
303 use crate::endianity::NativeEndian;
304 use crate::read::{EndianSlice, Error, ReaderOffsetId};
305 use alloc::vec::Vec;
306
307 trait ResultExt {
308 fn map_eof(self, input: &[u8]) -> Self;
309 }
310
311 impl<T> ResultExt for Result<T, Error> {
312 fn map_eof(self, input: &[u8]) -> Self {
313 match self {
314 Err(Error::UnexpectedEof(id)) => {
315 let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
316 Err(Error::UnexpectedEof(id))
317 }
318 r => r,
319 }
320 }
321 }
322
323 #[test]
324 fn test_low_bits_of_byte() {
325 for i in 0..127 {
326 assert_eq!(i, low_bits_of_byte(i));
327 assert_eq!(i, low_bits_of_byte(i | CONTINUATION_BIT));
328 }
329 }
330
331 #[test]
332 fn test_low_bits_of_u64() {
333 for i in 0u64..127 {
334 assert_eq!(i as u8, low_bits_of_u64(1 << 16 | i));
335 assert_eq!(
336 i as u8,
337 low_bits_of_u64(i << 16 | i | (u64::from(CONTINUATION_BIT)))
338 );
339 }
340 }
341
342 #[test]
344 fn test_read_unsigned() {
345 let buf = [2u8];
346 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
347 assert_eq!(
348 2,
349 read::unsigned(&mut readable).expect("Should read number")
350 );
351
352 let buf = [127u8];
353 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
354 assert_eq!(
355 127,
356 read::unsigned(&mut readable).expect("Should read number")
357 );
358
359 let buf = [CONTINUATION_BIT, 1];
360 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
361 assert_eq!(
362 128,
363 read::unsigned(&mut readable).expect("Should read number")
364 );
365
366 let buf = [1u8 | CONTINUATION_BIT, 1];
367 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
368 assert_eq!(
369 129,
370 read::unsigned(&mut readable).expect("Should read number")
371 );
372
373 let buf = [2u8 | CONTINUATION_BIT, 1];
374 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
375 assert_eq!(
376 130,
377 read::unsigned(&mut readable).expect("Should read number")
378 );
379
380 let buf = [57u8 | CONTINUATION_BIT, 100];
381 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
382 assert_eq!(
383 12857,
384 read::unsigned(&mut readable).expect("Should read number")
385 );
386 }
387
388 #[test]
389 fn test_read_unsigned_invalid() {
390 let buf = &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 2][..];
391 let mut readable = EndianSlice::new(buf, NativeEndian);
392 let err = read::unsigned(&mut readable).unwrap_err();
393 assert!(matches!(err, Error::BadUnsignedLeb128), "{}", err);
394 }
395
396 #[test]
398 fn test_read_signed() {
399 let buf = [2u8];
400 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
401 assert_eq!(2, read::signed(&mut readable).expect("Should read number"));
402
403 let buf = [0x7eu8];
404 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
405 assert_eq!(-2, read::signed(&mut readable).expect("Should read number"));
406
407 let buf = [127u8 | CONTINUATION_BIT, 0];
408 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
409 assert_eq!(
410 127,
411 read::signed(&mut readable).expect("Should read number")
412 );
413
414 let buf = [1u8 | CONTINUATION_BIT, 0x7f];
415 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
416 assert_eq!(
417 -127,
418 read::signed(&mut readable).expect("Should read number")
419 );
420
421 let buf = [CONTINUATION_BIT, 1];
422 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
423 assert_eq!(
424 128,
425 read::signed(&mut readable).expect("Should read number")
426 );
427
428 let buf = [CONTINUATION_BIT, 0x7f];
429 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
430 assert_eq!(
431 -128,
432 read::signed(&mut readable).expect("Should read number")
433 );
434
435 let buf = [1u8 | CONTINUATION_BIT, 1];
436 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
437 assert_eq!(
438 129,
439 read::signed(&mut readable).expect("Should read number")
440 );
441
442 let buf = [0x7fu8 | CONTINUATION_BIT, 0x7e];
443 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
444 assert_eq!(
445 -129,
446 read::signed(&mut readable).expect("Should read number")
447 );
448 }
449
450 #[test]
451 fn test_read_signed_63_bits() {
452 let buf = [
453 CONTINUATION_BIT,
454 CONTINUATION_BIT,
455 CONTINUATION_BIT,
456 CONTINUATION_BIT,
457 CONTINUATION_BIT,
458 CONTINUATION_BIT,
459 CONTINUATION_BIT,
460 CONTINUATION_BIT,
461 0x40,
462 ];
463 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
464 assert_eq!(
465 -0x4000_0000_0000_0000,
466 read::signed(&mut readable).expect("Should read number")
467 );
468 }
469
470 #[test]
471 fn test_read_unsigned_not_enough_data() {
472 let buf = [CONTINUATION_BIT];
473 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
474 assert_eq!(
475 read::unsigned(&mut readable).map_eof(&buf),
476 Err(Error::UnexpectedEof(ReaderOffsetId(1)))
477 );
478 }
479
480 #[test]
481 fn test_read_signed_not_enough_data() {
482 let buf = [CONTINUATION_BIT];
483 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
484 assert_eq!(
485 read::signed(&mut readable).map_eof(&buf),
486 Err(Error::UnexpectedEof(ReaderOffsetId(1)))
487 );
488 }
489
490 #[test]
491 #[cfg(feature = "std")]
492 fn test_write_unsigned_not_enough_space() {
493 let mut buf = [0; 1];
494 let mut writable = &mut buf[..];
495 match write::unsigned(&mut writable, 128) {
496 Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
497 otherwise => panic!("Unexpected: {:?}", otherwise),
498 }
499 }
500
501 #[test]
502 #[cfg(feature = "std")]
503 fn test_write_signed_not_enough_space() {
504 let mut buf = [0; 1];
505 let mut writable = &mut buf[..];
506 match write::signed(&mut writable, 128) {
507 Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
508 otherwise => panic!("Unexpected: {:?}", otherwise),
509 }
510 }
511
512 #[test]
513 fn dogfood_signed() {
514 fn inner(i: i64) {
515 let mut buf = Vec::new();
516 buf.extend(write::Leb128::signed(i).bytes());
517 buf.resize(1024, 0u8);
518
519 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
520 let result = read::signed(&mut readable).expect("Should be able to read it back again");
521 assert_eq!(i, result);
522 }
523 for i in -513..513 {
524 inner(i);
525 }
526 inner(i64::MIN);
527 }
528
529 #[test]
530 fn dogfood_unsigned() {
531 for i in 0..1025 {
532 let mut buf = Vec::new();
533 buf.extend(write::Leb128::unsigned(i).bytes());
534 buf.resize(1024, 0u8);
535
536 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
537 let result =
538 read::unsigned(&mut readable).expect("Should be able to read it back again");
539 assert_eq!(i, result);
540 }
541 }
542
543 #[test]
544 fn test_read_unsigned_overflow() {
545 let buf = [
546 2u8 | CONTINUATION_BIT,
547 2 | CONTINUATION_BIT,
548 2 | CONTINUATION_BIT,
549 2 | CONTINUATION_BIT,
550 2 | CONTINUATION_BIT,
551 2 | CONTINUATION_BIT,
552 2 | CONTINUATION_BIT,
553 2 | CONTINUATION_BIT,
554 2 | CONTINUATION_BIT,
555 2 | CONTINUATION_BIT,
556 2 | CONTINUATION_BIT,
557 2 | CONTINUATION_BIT,
558 2 | CONTINUATION_BIT,
559 2 | CONTINUATION_BIT,
560 2 | CONTINUATION_BIT,
561 2 | CONTINUATION_BIT,
562 2 | CONTINUATION_BIT,
563 2 | CONTINUATION_BIT,
564 2 | CONTINUATION_BIT,
565 2 | CONTINUATION_BIT,
566 2 | CONTINUATION_BIT,
567 2 | CONTINUATION_BIT,
568 2 | CONTINUATION_BIT,
569 2 | CONTINUATION_BIT,
570 2 | CONTINUATION_BIT,
571 2 | CONTINUATION_BIT,
572 2 | CONTINUATION_BIT,
573 2 | CONTINUATION_BIT,
574 2 | CONTINUATION_BIT,
575 2 | CONTINUATION_BIT,
576 1,
577 ];
578 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
579 assert!(read::unsigned(&mut readable).is_err());
580 }
581
582 #[test]
583 fn test_read_signed_overflow() {
584 let buf = [
585 2u8 | CONTINUATION_BIT,
586 2 | CONTINUATION_BIT,
587 2 | CONTINUATION_BIT,
588 2 | CONTINUATION_BIT,
589 2 | CONTINUATION_BIT,
590 2 | CONTINUATION_BIT,
591 2 | CONTINUATION_BIT,
592 2 | CONTINUATION_BIT,
593 2 | CONTINUATION_BIT,
594 2 | CONTINUATION_BIT,
595 2 | CONTINUATION_BIT,
596 2 | CONTINUATION_BIT,
597 2 | CONTINUATION_BIT,
598 2 | CONTINUATION_BIT,
599 2 | CONTINUATION_BIT,
600 2 | CONTINUATION_BIT,
601 2 | CONTINUATION_BIT,
602 2 | CONTINUATION_BIT,
603 2 | CONTINUATION_BIT,
604 2 | CONTINUATION_BIT,
605 2 | CONTINUATION_BIT,
606 2 | CONTINUATION_BIT,
607 2 | CONTINUATION_BIT,
608 2 | CONTINUATION_BIT,
609 2 | CONTINUATION_BIT,
610 2 | CONTINUATION_BIT,
611 2 | CONTINUATION_BIT,
612 2 | CONTINUATION_BIT,
613 2 | CONTINUATION_BIT,
614 2 | CONTINUATION_BIT,
615 1,
616 ];
617 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
618 assert!(read::signed(&mut readable).is_err());
619 }
620
621 #[test]
622 fn test_read_multiple() {
623 let buf = [2u8 | CONTINUATION_BIT, 1u8, 1u8];
624
625 let mut readable = EndianSlice::new(&buf[..], NativeEndian);
626 assert_eq!(
627 read::unsigned(&mut readable).expect("Should read first number"),
628 130u64
629 );
630 assert_eq!(
631 read::unsigned(&mut readable).expect("Should read first number"),
632 1u64
633 );
634 }
635
636 #[test]
637 fn test_read_u16() {
638 for (buf, val) in [
639 (&[2][..], 2),
640 (&[0x7f][..], 0x7f),
641 (&[0x80, 1][..], 0x80),
642 (&[0x81, 1][..], 0x81),
643 (&[0x82, 1][..], 0x82),
644 (&[0xff, 0x7f][..], 0x3fff),
645 (&[0x80, 0x80, 1][..], 0x4000),
646 (&[0xff, 0xff, 1][..], 0x7fff),
647 (&[0xff, 0xff, 3][..], 0xffff),
648 ]
649 .iter()
650 {
651 let mut readable = EndianSlice::new(buf, NativeEndian);
652 assert_eq!(*val, read::u16(&mut readable).expect("Should read number"));
653 }
654
655 for buf in [
656 &[0x80][..],
657 &[0x80, 0x80][..],
658 &[0x80, 0x80, 4][..],
659 &[0x80, 0x80, 0x80, 3][..],
660 ]
661 .iter()
662 {
663 let mut readable = EndianSlice::new(buf, NativeEndian);
664 assert!(read::u16(&mut readable).is_err(), "{:?}", buf);
665 }
666 }
667}