use super::*;
use internal::errors::*;
use stream::*;
pub struct Comma(pub u8);
pub const COMMA: Comma = Comma(2);
impl UniversalCode for Comma {
fn encode<W: BitWrite>(&self, sink: &mut W, mut value: u64) -> Result<()> {
let base = (1 << self.0) - 1;
let mut stack: Vec<u64> = Vec::new();
while value > 0 {
stack.push(value % base);
value /= base;
}
while let Some(digit) = stack.pop() {
try!(sink.write_int(self.0 as usize, digit));
}
try!(sink.write_int(self.0 as usize, base));
Ok(())
}
fn decode<R: BitRead>(&self, source: &mut R) -> Result<Option<u64>> {
let base = (1 << self.0) - 1;
let mut result = 0;
let mut consumed = false;
loop {
if let Some(digit) = try!(source.read_int::<u64>(self.0 as usize)) {
if digit == base { return Ok(Some(result)) }
consumed = true;
result = result * base + digit;
} else if consumed {
return out_of_bits("Comma::decode");
} else {
return Ok(None);
}
}
}
}
#[cfg(test)]
mod test {
use std::collections::VecDeque;
use quickcheck::quickcheck;
use coding::*;
use coding::properties;
#[test]
fn enc234() {
let mut dv = VecDeque::<bool>::new();
COMMA.encode(&mut dv, 2).unwrap();
COMMA.encode(&mut dv, 3).unwrap();
COMMA.encode(&mut dv, 4).unwrap();
assert_eq!(Some(2), COMMA.decode(&mut dv).unwrap());
assert_eq!(Some(3), COMMA.decode(&mut dv).unwrap());
assert_eq!(Some(4), COMMA.decode(&mut dv).unwrap());
assert_eq!(None::<u64>, COMMA.decode(&mut dv).unwrap());
}
#[test]
fn qc_comma2() {
fn prop(v: Vec<u64>) -> bool {
properties::code_decode(&Comma(2), v)
}
quickcheck(prop as fn(Vec<u64>) -> bool);
}
#[test]
fn qc_comma3() {
fn prop(v: Vec<u64>) -> bool {
properties::code_decode(&Comma(3), v)
}
quickcheck(prop as fn(Vec<u64>) -> bool);
}
#[test]
fn qc_comma4() {
fn prop(v: Vec<u64>) -> bool {
properties::code_decode(&Comma(4), v)
}
quickcheck(prop as fn(Vec<u64>) -> bool);
}
}