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}