bitstream/
padding.rs

1//! A module for `padding` bits into bytes
2//!
3//! This module contains the trait for defining a padding strategy for `BitReader` and `BitWriter`.
4
5use std::io::{Write};
6use std::io::Result as IOResult;
7
8/// **Padding** specifies what sort of padding should be used by
9/// [BitReader](../struct.BitReader.html)/[BitWriter](../struct.BitWriter.html)
10///
11/// This trait can be used to implement custom padding of bits to a whole byte.
12pub trait Padding {
13    /// Get the maximum size of the padding.
14    ///
15    /// This is used to determine how many bytes should be passed to
16    /// [bits_left](#tymethod.bits_left)
17    fn max_size(&self) -> usize;
18
19    /// Pad the last bits of the stream.
20    ///
21    /// This is called by [BitWriter](../struct.BitWriter.html) on drop to make sure the last bits are
22    /// written to the output, using the specified padding. The padding is responsible for writing
23    /// the last byte, or else it may lead to unintended loss of data.
24    fn pad<W: Write>(&self, last_byte: u8, byte_fill: u8, writer: &mut W) -> IOResult<()>;
25
26    /// Determine how many bits are left to read.
27    ///
28    /// This is called by [BitReader](../struct.BitReader.html) when encountering the last byte in the
29    /// input stream. This will be called with the last `n` bytes of the input stream, where `n`
30    /// is [`max_size()`](#tymethod.max_size), or fewer, if there are fewer bytes in the whole input
31    /// stream.
32    fn bits_left(&self, last_bytes: &[u8]) -> IOResult<usize>;
33}
34
35/// **NoPadding** is the default [Padding](trait.Padding.html) used by
36/// [BitReader](../struct.BitReader.html)/[BitWriter](../struct.BitWriter.html)
37///
38/// This does not add any padding to the output stream, apart from filling up the the stream
39/// with 0s until the next byte is full.
40#[derive(Default, Debug)]
41pub struct NoPadding {}
42
43impl NoPadding {
44    /// Create a new instance
45    pub fn new() -> Self {
46        NoPadding {}
47    }
48}
49
50impl Padding for NoPadding {
51    fn max_size(&self) -> usize {
52        0
53    }
54
55    fn pad<W: Write>(&self, last_byte: u8, byte_fill: u8, writer: &mut W) -> IOResult<()> {
56        if byte_fill > 0 {
57            writer.write_all(&[last_byte])
58        } else {
59            Ok(())
60        }
61    }
62
63    fn bits_left(&self, _: &[u8]) -> IOResult<usize> {
64        Ok(0)
65    }
66}
67
68/// **LengthPadding** can be used encode the number of bits in the bit stream.
69///
70/// When using this padding, an extra byte is appended at the end of the stream. This byte
71/// indicates how many bots in the previous byte are valid.
72#[derive(Debug, Default)]
73pub struct LengthPadding {}
74
75impl LengthPadding {
76    /// Create a new instance
77    pub fn new() -> Self {
78        LengthPadding {}
79    }
80}
81
82impl Padding for LengthPadding {
83    fn max_size(&self) -> usize {
84        2
85    }
86
87    fn pad<W: Write>(&self, last_byte: u8, byte_fill: u8, writer: &mut W) -> IOResult<()> {
88        if byte_fill > 0 {
89            writer.write_all(&[last_byte, byte_fill])
90        } else {
91            writer.write_all(&[8u8])
92        }
93    }
94
95    fn bits_left(&self, last_bytes: &[u8]) -> IOResult<usize> {
96        if last_bytes.len() == 2 {
97            Ok(last_bytes[1] as usize)
98        } else {
99            Ok(0)
100        }
101    }
102}