Skip to content

Instantly share code, notes, and snippets.

@niksaak
Created December 1, 2018 02:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niksaak/2998407a331ac5751b5d7b20826d3ba2 to your computer and use it in GitHub Desktop.
Save niksaak/2998407a331ac5751b5d7b20826d3ba2 to your computer and use it in GitHub Desktop.
pub fn encode(data: &[u8]) -> Vec<u8> {
Encoder::new(data).encode()
}
pub fn decode(data: &[u8]) -> Vec<u8> {
Decoder::new(data).decode()
}
const ILLEGALS: [u8; 6] = [0, 10, 13, 34, 38, 92];
const SHORT_MARK: u8 = 0b111;
struct Encoder<'a> {
data: &'a [u8],
bit: u8,
}
fn get_illegal(byte: u8) -> Option<u8> {
ILLEGALS.iter().position(|x| *x == byte).map(|n| n as u8)
}
impl<'a> Encoder<'a> {
fn new(data: &'a [u8]) -> Self {
Self {
data: data,
bit: 0,
}
}
fn pop7(&mut self) -> Option<u8> {
if self.data.len() == 0 {
return None;
}
let first_part = (((0b1111_1110 >> self.bit) & self.data[0]) << self.bit) >> 1;
self.bit += 7;
if self.bit < 8 {
return Some(first_part);
}
self.bit -= 8;
self.data = &self.data[1..];
if self.data.len() == 0 {
return Some(first_part);
}
let second_part = ((0xFF00u16 >> self.bit) as u8 & self.data[0]) >> (8 - self.bit);
Some(first_part | second_part)
}
fn encode(mut self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.data.len() + self.data.len() / 8 + 1);
while let Some(bits) = self.pop7() {
if let Some(illegal_id) = get_illegal(bits) {
let mut b1: u8 = 0b1100_0010;
let mut b2: u8 = 0b1000_0000;
let next_bits = match self.pop7() {
Some(next_bits) => {
b1 |= (0b111 & illegal_id) << 2;
next_bits
},
None => {
b1 |= SHORT_MARK << 2;
bits
},
};
b1 |= (next_bits & 0b0100_0000) >> 6;
b2 |= next_bits & 0b0011_1111;
buf.push(b1);
buf.push(b2);
} else {
buf.push(bits);
}
}
return buf;
}
}
struct Decoder<'a> {
buf: Vec<u8>,
data: &'a [u8],
byte: u16,
bit: u16,
}
impl<'a> Decoder<'a> {
fn new(data: &'a [u8]) -> Self {
Decoder {
buf: Vec::new(),
data: data,
byte: 0,
bit: 0,
}
}
fn push7(&mut self, bits: u8) {
let mut bits = bits as u16;
bits <<= 1;
self.byte |= bits >> self.bit;
self.bit += 7;
if self.bit >= 8 {
self.buf.push(self.byte as u8);
self.bit -= 8;
self.byte = (bits << (7 - self.bit)) & 255;
}
}
fn decode(mut self) -> Vec<u8> {
loop {
if self.data.len() == 0 {
break;
}
let c1 = self.data[0];
if c1 & 0b1000_0000 != 0 {
let c2 = self.data[1];
let illegal_id = (c1 >> 2) & 0b111;
if illegal_id != SHORT_MARK {
self.push7(ILLEGALS[illegal_id as usize]);
}
self.push7((c2 & 0b0011_1111) | ((c1 & 1) << 6));
if self.data.len() < 2 {
break;
} else {
self.data = &self.data[2..];
}
} else {
self.push7(c1);
self.data = &self.data[1..];
}
}
self.buf
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment