use super::{Encode, EncodingStrategy};
use crate::{Incompressible, Normal, Small, Sorted};
use std::io::{Read, Write};
impl<T: Encode> Encode for Vec<T> {
type Context = Context<T, Normal>;
#[inline]
fn encode<W: Write>(
&self,
writer: &mut super::Writer<W>,
ctx: &mut Self::Context,
) -> Result<(), std::io::Error> {
crate::Values::<Normal>::encode(self, writer, ctx)
}
fn millibits(&self, ctx: &mut Self::Context) -> Option<usize> {
crate::Values::<Normal>::millibits(self, ctx)
}
#[inline]
fn decode<R: Read>(
reader: &mut super::Reader<R>,
ctx: &mut Self::Context,
) -> Result<Self, std::io::Error> {
crate::Values::<Normal>::decode(reader, ctx)
}
}
#[test]
fn size() {
use super::assert_bits;
assert_bits!(Vec::<usize>::new(), 3);
for value in 0_usize..4 {
assert_bits!(vec![dbg!(value)], 6);
}
assert_bits!(dbg!((0_usize..1).collect::<Vec<_>>()), 6);
assert_bits!(dbg!((0_usize..2).collect::<Vec<_>>()), 10);
assert_bits!(dbg!((0_usize..10).collect::<Vec<_>>()), 61);
}
pub struct Context<T, S: EncodingStrategy<T>> {
len: <Small as EncodingStrategy<usize>>::Context,
values: S::Context,
}
impl<T, S: EncodingStrategy<T>> Default for Context<T, S> {
fn default() -> Self {
Self {
len: Default::default(),
values: Default::default(),
}
}
}
impl<T, S: EncodingStrategy<T>> Clone for Context<T, S> {
fn clone(&self) -> Self {
Self {
len: self.len.clone(),
values: self.values.clone(),
}
}
}
impl<T, S: EncodingStrategy<T>> EncodingStrategy<Vec<T>> for crate::Values<S> {
type Context = Context<T, S>;
fn decode<R: Read>(
reader: &mut super::Reader<R>,
ctx: &mut Self::Context,
) -> Result<Vec<T>, std::io::Error> {
let n = Small::decode(reader, &mut ctx.len)?;
let mut x = Vec::with_capacity(n);
for _ in 0..n {
x.push(S::decode(reader, &mut ctx.values)?);
}
Ok(x)
}
fn encode<W: Write>(
value: &Vec<T>,
writer: &mut super::Writer<W>,
ctx: &mut Self::Context,
) -> Result<(), std::io::Error> {
Small::encode(&value.len(), writer, &mut ctx.len)?;
for v in value {
S::encode(v, writer, &mut ctx.values)?;
}
Ok(())
}
fn millibits(value: &Vec<T>, ctx: &mut Self::Context) -> Option<usize> {
let mut tot = Small::millibits(&value.len(), &mut ctx.len)?;
for v in value {
tot += S::millibits(v, &mut ctx.values)?;
}
Some(tot)
}
}
#[derive(Clone)]
pub struct SortedContext<T: Encode> {
previous: Vec<T>,
shared_prefix: <Small as EncodingStrategy<usize>>::Context,
len: <Small as EncodingStrategy<usize>>::Context,
value: <T as Encode>::Context,
}
impl<T: Encode> Default for SortedContext<T> {
fn default() -> Self {
Self {
previous: Vec::new(),
shared_prefix: Default::default(),
len: Default::default(),
value: Default::default(),
}
}
}
impl<T: Encode + Clone + Eq> EncodingStrategy<Vec<T>> for Sorted {
type Context = SortedContext<T>;
fn decode<R: std::io::Read>(
reader: &mut super::Reader<R>,
ctx: &mut Self::Context,
) -> Result<Vec<T>, std::io::Error> {
let len: usize = Small::decode(reader, &mut ctx.len)?;
let mut out = Vec::new();
if ctx.previous.is_empty() {
out.reserve_exact(len);
} else {
let shared_prefix: usize = Small::decode(reader, &mut ctx.shared_prefix)?;
out.reserve_exact(shared_prefix + len);
debug_assert!(shared_prefix <= ctx.previous.len());
out.extend_from_slice(&ctx.previous[..shared_prefix]);
}
for _ in 0..len {
out.push(T::decode(reader, &mut ctx.value)?);
}
ctx.previous = out.clone();
Ok(out)
}
fn encode<W: std::io::Write>(
value: &Vec<T>,
writer: &mut super::Writer<W>,
ctx: &mut Self::Context,
) -> Result<(), std::io::Error> {
if ctx.previous.is_empty() {
let len = value.len();
Small::encode(&len, writer, &mut ctx.len)?;
for b in value {
b.encode(writer, &mut ctx.value)?;
}
} else {
let shared_prefix = value
.iter()
.zip(ctx.previous.iter())
.take_while(|(a, b)| a == b)
.count();
let len = value.len() - shared_prefix;
Small::encode(&len, writer, &mut ctx.len)?;
Small::encode(&shared_prefix, writer, &mut ctx.shared_prefix)?;
for b in &value[shared_prefix..] {
b.encode(writer, &mut ctx.value)?;
}
}
ctx.previous = value.clone();
Ok(())
}
fn millibits(value: &Vec<T>, ctx: &mut Self::Context) -> Option<usize> {
let mut tot = 0;
if ctx.previous.is_empty() {
let len = value.len();
tot += Small::millibits(&len, &mut ctx.len)?;
for b in value {
tot += b.millibits(&mut ctx.value)?;
}
} else {
let shared_prefix = value
.iter()
.zip(ctx.previous.iter())
.take_while(|(a, b)| a == b)
.count();
let len = value.len() - shared_prefix;
tot += Small::millibits(&len, &mut ctx.len)?;
tot += Small::millibits(&shared_prefix, &mut ctx.shared_prefix)?;
for b in &value[shared_prefix..] {
tot += b.millibits(&mut ctx.value)?;
}
}
ctx.previous = value.clone();
Some(tot)
}
}
impl EncodingStrategy<Vec<u8>> for Incompressible {
type Context = <Vec<u8> as Encode>::Context;
fn decode<R: std::io::Read>(
reader: &mut super::Reader<R>,
ctx: &mut Self::Context,
) -> Result<Vec<u8>, std::io::Error> {
<Vec<u8> as Encode>::decode(reader, ctx)
}
fn encode<W: std::io::Write>(
value: &Vec<u8>,
writer: &mut super::Writer<W>,
ctx: &mut Self::Context,
) -> Result<(), std::io::Error> {
value.encode(writer, ctx)
}
fn millibits(value: &Vec<u8>, ctx: &mut Self::Context) -> Option<usize> {
value.millibits(ctx)
}
}