use super::v2_serializer::{V2SerializeError, V2Serializer};
use super::{Serializer, V2_COMPRESSED_COOKIE};
use crate::core::counter::Counter;
use crate::Histogram;
use byteorder::{BigEndian, WriteBytesExt};
use flate2::write::ZlibEncoder;
use flate2::Compression;
use std::io::{self, Write};
use std::{self, error, fmt};
#[derive(Debug)]
pub enum V2DeflateSerializeError {
InternalSerializationError(V2SerializeError),
IoError(io::Error),
}
impl std::convert::From<std::io::Error> for V2DeflateSerializeError {
fn from(e: std::io::Error) -> Self {
V2DeflateSerializeError::IoError(e)
}
}
impl fmt::Display for V2DeflateSerializeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
V2DeflateSerializeError::InternalSerializationError(e) => {
write!(f, "The underlying serialization failed: {}", e)
}
V2DeflateSerializeError::IoError(e) => {
write!(f, "The underlying serialization failed: {}", e)
}
}
}
}
impl error::Error for V2DeflateSerializeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
V2DeflateSerializeError::InternalSerializationError(e) => Some(e),
V2DeflateSerializeError::IoError(e) => Some(e),
}
}
}
pub struct V2DeflateSerializer {
uncompressed_buf: Vec<u8>,
compressed_buf: Vec<u8>,
v2_serializer: V2Serializer,
}
impl Default for V2DeflateSerializer {
fn default() -> Self {
Self::new()
}
}
impl V2DeflateSerializer {
pub fn new() -> V2DeflateSerializer {
V2DeflateSerializer {
uncompressed_buf: Vec::new(),
compressed_buf: Vec::new(),
v2_serializer: V2Serializer::new(),
}
}
}
impl Serializer for V2DeflateSerializer {
type SerializeError = V2DeflateSerializeError;
fn serialize<T: Counter, W: Write>(
&mut self,
h: &Histogram<T>,
writer: &mut W,
) -> Result<usize, V2DeflateSerializeError> {
self.uncompressed_buf.clear();
self.compressed_buf.clear();
let uncompressed_len = self
.v2_serializer
.serialize(h, &mut self.uncompressed_buf)
.map_err(V2DeflateSerializeError::InternalSerializationError)?;
debug_assert_eq!(self.uncompressed_buf.len(), uncompressed_len);
self.compressed_buf.reserve(self.uncompressed_buf.len() / 2);
self.compressed_buf
.write_u32::<BigEndian>(V2_COMPRESSED_COOKIE)?;
self.compressed_buf.write_u32::<BigEndian>(0)?;
{
let mut compressor = ZlibEncoder::new(&mut self.compressed_buf, Compression::default());
compressor.write_all(&self.uncompressed_buf[0..uncompressed_len])?;
let _ = compressor.finish()?;
}
let total_compressed_len = self.compressed_buf.len();
(&mut self.compressed_buf[4..8])
.write_u32::<BigEndian>((total_compressed_len as u32) - 8)?;
writer.write_all(&self.compressed_buf)?;
Ok(total_compressed_len)
}
}