Hi all.
A few months ago I was implementing an LZW variant for compressing executables for an 8 bit platform, and needed to be able to output a few distinct bitstreams to cut down on byte boundary tests in the decoder (reading bitpairs should only require half as many checks).
I ran into an issue with not being able to pass a mutable reference to self to methods on instance variables. At the time, I worked around it by shifting the bit-writing code from the cursors into the encoder, and just switched on a stream index to determine which cursor to use, but I'm wondering if there was a better way, or if this is something that the borrow checker may become less strict about in the future now that the MIR is almost online.
Here's a small test program that illustrates the issue:
#[derive(Debug)]
struct BitStreamCursor {
bits_written: usize,
bits_index: usize,
}
#[derive(Debug)]
struct Encoder {
encoded_stream:Vec<u8>,
bit_cursor:BitStreamCursor,
pair_cursor:BitStreamCursor,
}
impl BitStreamCursor {
fn new() -> BitStreamCursor {
BitStreamCursor {
bits_written:8,
bits_index:0,
}
}
fn push_bit(&mut self, parent:&mut Encoder, b:u8) {
if self.bits_written==8 {
self.bits_index=parent.encoded_stream.len();
parent.encoded_stream.push(b<<7);
self.bits_written=1
}
else {
parent.encoded_stream[self.bits_index]+=b*(128>>self.bits_written);
self.bits_written+=1
}
}
}
impl Encoder {
fn new() -> Encoder {
Encoder {
encoded_stream: Vec::new(),
bit_cursor:BitStreamCursor::new(),
pair_cursor:BitStreamCursor::new(),
}
}
fn push_byte(&mut self, b:u8) {
self.encoded_stream.push(b);
}
fn push_bit(&mut self, b:u8) {
self.bit_cursor.push_bit(self, b);
}
fn push_bitpair(&mut self, b:u8) {
self.pair_cursor.push_bit(self, (b>>1));
self.pair_cursor.push_bit(self, (b&1));
}
}
fn main() {
let mut e= Encoder::new();
e.push_bit(1);
e.push_bitpair(2);
e.push_byte(42);
println!("stream contents: {:?}",e);
}