1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#[macro_use]
extern crate log;

#[cfg(test)]
mod test;

pub const HEADER: u8 = 0b00001111;
const SHORTENED: u8 = 0b01000000;

const DEFAULT_MIME: &'static str = "image/jpg";
const ILLEGALS: [u8; 6] = [0, 10, 13, 34, 38, 92];

pub struct Encoder<'a> {
    data: &'a [u8],
    bit_index: usize,
    byte_index: usize,
}

fn is_illegal(byte: u8) -> Option<u8> {
    for (index, illegal_byte) in ILLEGALS.iter().enumerate() {
        if *illegal_byte == byte {
            return Some(index as u8);
        }
    }

    None
}

fn fmt_buf(data: &[u8]) -> String {
    let mut s = String::with_capacity(data.len() * 8);
    for byte in data.iter() {
        s.push_str(&format!("{:08b}", byte));
    }
    s
}

impl<'a> Encoder<'a> {
    pub fn new(data: &[u8]) -> Encoder {
        Encoder {
            data: data,
            bit_index: 0,
            byte_index: 0,
        }
    }

    fn get7(&mut self) -> Result<u8, ()> {
        if self.byte_index < self.data.len() {
            let first_byte = self.data[self.byte_index];
            let first_part = (((0b11111110 >> self.bit_index) & first_byte) << self.bit_index) >> 1;

            self.bit_index += 7;
            if self.bit_index < 8 {
                Ok(first_part)
            } else {
                self.bit_index -= 8;
                self.byte_index += 1;

                if self.byte_index >= self.data.len() {
                    Ok(first_part)
                } else {
                    let second_byte = self.data[self.byte_index];
                    let second_part = (((0xFF00u16 >> self.bit_index) as u8 & second_byte) &
                                       0xFF) >>
                                      8 - self.bit_index;

                    Ok(first_part | second_part)
                }
            }
        } else {
            Err(())
        }
    }

    pub fn encode(&mut self) -> Vec<u8> {
        let mut buf = Vec::new();
        let mut header = HEADER;
        buf.push(header);

        while let Ok(bits) = self.get7() {
            if let Some(illegal_index) = is_illegal(bits) {
                debug!("Handle illegal sequence: {:08b}", bits);
                let mut b1: u8 = 0b11000010 | (0b111 & illegal_index) << 2;
                let mut b2: u8 = 0b10000000;
                if let Ok(next_bits) = self.get7() {
                    debug!("Additional bits to two - byte character {:08b}", next_bits);

                    let first_bit: u8 = if (next_bits & 0b01000000) > 0 { 1 } else { 0 };
                    b1 |= first_bit;
                    b2 |= next_bits & 0b00111111;
                } else {
                    debug!("Last seven bits are an illegal sequence, and there are no more bits \
                            left");

                    header |= SHORTENED;
                }
                debug!("Adding to buffer: {:08b}{:08b}", b1, b2);
                buf.push(b1);
                buf.push(b2);
            } else {
                debug!("Adding to buffer: {:08b}", bits);
                buf.push(bits);
            }
        }

        debug!("Adding header to buffer: {:08b}", header);
        buf[0] = header;

        debug!("Returning buffer: {}", fmt_buf(&buf));
        buf
    }
}