Skip to content

Commit 4711530

Browse files
authored
Merge pull request #34 from njames93/extend-vbr-support
Extend support for VBR
2 parents dfc3e7f + 8040d6d commit 4711530

File tree

3 files changed

+176
-4
lines changed

3 files changed

+176
-4
lines changed

src/lib.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,16 @@ pub trait Integer {
294294
R: BitRead + ?Sized,
295295
Self: Sized;
296296

297+
/// Reads a valur of ourself from the stream using a variable width integer.
298+
///
299+
/// # Errors
300+
///
301+
/// Passes along any I/O error from the underlying stream.
302+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
303+
where
304+
R: BitRead + ?Sized,
305+
Self: Sized;
306+
297307
/// Writes ourself to the stream using the given const number of bits.
298308
///
299309
/// # Errors
@@ -319,6 +329,16 @@ pub trait Integer {
319329
writer: &mut W,
320330
bits: BitCount<MAX>,
321331
) -> io::Result<()>;
332+
333+
/// Writes ourself to the stream using a variable width integer.
334+
///
335+
/// # Errors
336+
///
337+
/// Passes along any I/O error from the underlying stream.
338+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
339+
self,
340+
writer: &mut W,
341+
) -> io::Result<()>;
322342
}
323343

324344
/// Reading and writing booleans as `Integer` requires the number of bits to be 1.
@@ -376,6 +396,15 @@ impl Integer for bool {
376396
}
377397
}
378398

399+
#[inline(always)]
400+
fn read_vbr<const FIELD_SIZE: u32, R>(_reader: &mut R) -> io::Result<Self>
401+
where
402+
R: BitRead + ?Sized,
403+
Self: Sized,
404+
{
405+
unimplemented!("Can't read a VBR boolean")
406+
}
407+
379408
#[inline(always)]
380409
fn write<const BITS: u32, W: BitWrite + ?Sized>(self, writer: &mut W) -> io::Result<()> {
381410
const {
@@ -399,6 +428,14 @@ impl Integer for bool {
399428
))
400429
}
401430
}
431+
432+
#[inline(always)]
433+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
434+
self,
435+
_writer: &mut W,
436+
) -> io::Result<()> {
437+
unimplemented!("Can't write a VBR for boolean")
438+
}
402439
}
403440

404441
impl<const SIZE: usize, I: Integer + Copy + Default> Integer for [I; SIZE] {
@@ -432,6 +469,21 @@ impl<const SIZE: usize, I: Integer + Copy + Default> Integer for [I; SIZE] {
432469

433470
Ok(a)
434471
}
472+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
473+
where
474+
R: BitRead + ?Sized,
475+
Self: Sized,
476+
{
477+
let mut a = [I::default(); SIZE];
478+
479+
a.iter_mut().try_for_each(|v| {
480+
I::read_vbr::<FIELD_SIZE, R>(reader).map(|item| {
481+
*v = item;
482+
})
483+
})?;
484+
485+
Ok(a)
486+
}
435487

436488
#[inline]
437489
fn write<const BITS: u32, W: BitWrite + ?Sized>(self, writer: &mut W) -> io::Result<()> {
@@ -446,6 +498,13 @@ impl<const SIZE: usize, I: Integer + Copy + Default> Integer for [I; SIZE] {
446498
) -> io::Result<()> {
447499
IntoIterator::into_iter(self).try_for_each(|v| writer.write_counted(count, v))
448500
}
501+
502+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
503+
self,
504+
writer: &mut W,
505+
) -> io::Result<()> {
506+
IntoIterator::into_iter(self).try_for_each(|v| I::write_vbr::<FIELD_SIZE, W>(v, writer))
507+
}
449508
}
450509

451510
/// This trait extends many common integer types (both unsigned and signed)
@@ -642,6 +701,15 @@ macro_rules! define_unsigned_integer {
642701
reader.read_unsigned_counted::<MAX, _>(bits)
643702
}
644703

704+
#[inline(always)]
705+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
706+
where
707+
R: BitRead + ?Sized,
708+
Self: Sized,
709+
{
710+
reader.read_unsigned_vbr::<FIELD_SIZE, _>()
711+
}
712+
645713
#[inline(always)]
646714
fn write<const BITS: u32, W: BitWrite + ?Sized>(
647715
self,
@@ -658,6 +726,14 @@ macro_rules! define_unsigned_integer {
658726
) -> io::Result<()> {
659727
writer.write_unsigned_counted(bits, self)
660728
}
729+
730+
#[inline(always)]
731+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
732+
self,
733+
writer: &mut W,
734+
) -> io::Result<()> {
735+
writer.write_unsigned_vbr::<FIELD_SIZE, _>(self)
736+
}
661737
}
662738

663739
/// Unsigned NonZero types increment their value by 1
@@ -728,6 +804,16 @@ macro_rules! define_unsigned_integer {
728804
}
729805
}
730806

807+
#[inline]
808+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
809+
where
810+
R: BitRead + ?Sized,
811+
Self: Sized,
812+
{
813+
<$t as Integer>::read_vbr::<FIELD_SIZE, R>(reader)
814+
.map(|u| NonZero::new(u + 1).unwrap())
815+
}
816+
731817
#[inline]
732818
fn write<const BITS: u32, W: BitWrite + ?Sized>(
733819
self,
@@ -758,6 +844,14 @@ macro_rules! define_unsigned_integer {
758844
))
759845
}
760846
}
847+
848+
#[inline]
849+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
850+
self,
851+
writer: &mut W,
852+
) -> io::Result<()> {
853+
<$t as Integer>::write_vbr::<FIELD_SIZE, W>(self.get() - 1, writer)
854+
}
761855
}
762856

763857
impl Integer for Option<NonZero<$t>> {
@@ -778,6 +872,15 @@ macro_rules! define_unsigned_integer {
778872
<$t as Integer>::read_var::<MAX, R>(reader, count).map(NonZero::new)
779873
}
780874

875+
#[inline(always)]
876+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
877+
where
878+
R: BitRead + ?Sized,
879+
Self: Sized,
880+
{
881+
<$t as Integer>::read_vbr::<FIELD_SIZE, _>(reader).map(NonZero::new)
882+
}
883+
781884
#[inline]
782885
fn write<const BITS: u32, W: BitWrite + ?Sized>(
783886
self,
@@ -798,6 +901,17 @@ macro_rules! define_unsigned_integer {
798901
count,
799902
)
800903
}
904+
905+
#[inline]
906+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
907+
self,
908+
writer: &mut W,
909+
) -> io::Result<()> {
910+
<$t as Integer>::write_vbr::<FIELD_SIZE, W>(
911+
self.map(|n| n.get()).unwrap_or(0),
912+
writer,
913+
)
914+
}
801915
}
802916
};
803917
}
@@ -896,6 +1010,15 @@ macro_rules! define_signed_integer {
8961010
reader.read_signed_counted::<MAX, _>(bits)
8971011
}
8981012

1013+
#[inline(always)]
1014+
fn read_vbr<const FIELD_SIZE: u32, R>(reader: &mut R) -> io::Result<Self>
1015+
where
1016+
R: BitRead + ?Sized,
1017+
Self: Sized,
1018+
{
1019+
reader.read_signed_vbr::<FIELD_SIZE, _>()
1020+
}
1021+
8991022
#[inline(always)]
9001023
fn write<const BITS: u32, W: BitWrite + ?Sized>(
9011024
self,
@@ -912,6 +1035,14 @@ macro_rules! define_signed_integer {
9121035
) -> io::Result<()> {
9131036
writer.write_signed_counted::<MAX, _>(bits, self)
9141037
}
1038+
1039+
#[inline(always)]
1040+
fn write_vbr<const FIELD_SIZE: u32, W: BitWrite + ?Sized>(
1041+
self,
1042+
writer: &mut W,
1043+
) -> io::Result<()> {
1044+
writer.write_signed_vbr::<FIELD_SIZE, _>(self)
1045+
}
9151046
}
9161047
};
9171048
}

src/read.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ pub trait BitRead {
902902
T::from_bits(|| self.read_bit())
903903
}
904904

905-
/// Reads a number using a variable using a variable-width integer.
905+
/// Reads a number using a variable using a variable width integer.
906906
/// This optimises the case when the number is small.
907907
///
908908
/// The integer is mapped to an unsigned value using zigzag encoding.
@@ -961,7 +961,7 @@ pub trait BitRead {
961961
}
962962
}
963963

964-
/// Reads a number using a variable using a variable-width integer.
964+
/// Reads a number using a variable using a variable width integer.
965965
/// This optimises the case when the number is small.
966966
///
967967
/// The integer is mapped to an unsigned value using zigzag encoding.
@@ -993,6 +993,27 @@ pub trait BitRead {
993993
})
994994
}
995995

996+
/// Reads a signed or unsigned variable width integer from the stream.
997+
///
998+
/// # Errors
999+
///
1000+
/// Passes along any I/O error from the underlying stream.
1001+
/// Returns an error if the data read would overflow the size of the result
1002+
///
1003+
/// # Example
1004+
/// ```
1005+
/// use bitstream_io::{BitReader, BitRead, BigEndian};
1006+
///
1007+
/// let bytes: &[u8] = &[0b0110_1011, 0b1100_0001];
1008+
/// let mut r = BitReader::endian(bytes, BigEndian);
1009+
/// assert_eq!(r.read_vbr::<4, u32>().unwrap(), 6);
1010+
/// assert_eq!(r.read_vbr::<4, i32>().unwrap(), -50);
1011+
/// ```
1012+
#[inline]
1013+
fn read_vbr<const FIELD_SIZE: u32, I: Integer>(&mut self) -> io::Result<I> {
1014+
I::read_vbr::<FIELD_SIZE, _>(self)
1015+
}
1016+
9961017
/// Creates a "by reference" adaptor for this `BitRead`
9971018
///
9981019
/// The returned adapter also implements `BitRead`

src/write.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ pub trait BitWrite {
962962
T::to_bits(value, |b| self.write_bit(b))
963963
}
964964

965-
/// Writes a number using a variable using a variable-width integer.
965+
/// Writes a number using a variable using a variable width integer.
966966
/// This optimises the case when the number is small.
967967
///
968968
/// Given a 4-bit VBR field, any 3-bit value (0 through 7) is encoded directly, with the high bit set to zero.
@@ -1004,7 +1004,7 @@ pub trait BitWrite {
10041004
Ok(())
10051005
}
10061006

1007-
/// Writes a number using a variable using a variable-width integer.
1007+
/// Writes a number using a variable using a variable width integer.
10081008
/// This optimises the case when the number is small.
10091009
///
10101010
/// The integer is mapped to an unsigned value using zigzag encoding.
@@ -1034,6 +1034,26 @@ pub trait BitWrite {
10341034
self.write_unsigned_vbr::<FIELD_SIZE, _>(zig_zag.as_non_negative())
10351035
}
10361036

1037+
/// Writes a signed or unsigned variable width integer to the stream
1038+
///
1039+
/// # Errors
1040+
///
1041+
/// Passes along any I/O error from the underlying stream.
1042+
///
1043+
/// # Example
1044+
/// ```
1045+
/// use std::io::Write;
1046+
/// use bitstream_io::{BigEndian, BitWriter, BitWrite};
1047+
/// let mut writer = BitWriter::endian(Vec::new(), BigEndian);
1048+
/// writer.write_vbr::<4,_>(6u32);
1049+
/// writer.write_vbr::<4,_>(-50i32);
1050+
/// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]);
1051+
/// ```
1052+
#[inline]
1053+
fn write_vbr<const FIELD_SIZE: u32, I: Integer>(&mut self, value: I) -> io::Result<()> {
1054+
I::write_vbr::<FIELD_SIZE, _>(value, self)
1055+
}
1056+
10371057
/// Creates a "by reference" adaptor for this `BitWrite`
10381058
///
10391059
/// The returned adapter also implements `BitWrite`

0 commit comments

Comments
 (0)