use crate::compression::gzwrapper::deflate_bytes;
use crate::compression::gzwrapper::inflate_bytes;
use std::io::Read;
use bincode::{Encode, Decode};
use bincode::encode_into_std_write;
use bincode::decode_from_slice;
use crate::compression::MetadataCompression;
type E = Box<dyn std::error::Error>;
#[derive(Clone, Debug, Decode, Encode, PartialEq)]
pub struct BlockHeader {
pub num_records: u32,
pub metadata_compression: u8,
pub bitmap_type: u16,
pub placeholder1: u8,
pub block_len: u32,
pub flags_len: u64,
pub fields_present: u16,
pub placeholder2: u16,
pub placeholder3: u64,
}
impl BlockHeader {
pub fn promises_query_names(
&self,
) -> bool {
(self.fields_present & crate::MASK_QUERIES) != 0
}
pub fn promises_query_ids(
&self,
) -> bool {
(self.fields_present & crate::MASK_QUERY_IDS) != 0
}
}
impl Default for BlockHeader {
fn default() -> BlockHeader {
BlockHeader {
num_records: 0_u32,
metadata_compression: MetadataCompression::default().to_u8(),
bitmap_type: crate::compression::BitmapType::default().to_u16(),
block_len: 0_u32,
flags_len: 0_u64,
fields_present: crate::MASK_QUERY_IDS | crate::MASK_QUERIES,
placeholder1: 0,
placeholder2: 0,
placeholder3: 0,
}
}
}
#[derive(Clone, Decode, Debug, Encode, PartialEq)]
pub struct BlockFlags {
pub queries: Option<Vec<Vec<u8>>>,
pub query_ids: Option<Vec<u32>>,
}
impl BlockFlags {
pub fn fields_present(
&self,
) -> u16 {
let mut flags = 0_u16;
if self.queries.is_some() {
flags |= crate::MASK_QUERIES;
}
if self.query_ids.is_some() {
flags |= crate::MASK_QUERY_IDS;
}
flags
}
}
pub fn encode_block_header(
header: &BlockHeader,
) -> Result<Vec<u8>, E> {
let mut bytes: Vec<u8> = Vec::new();
let nbytes = encode_into_std_write(
header,
&mut bytes,
bincode::config::standard().with_fixed_int_encoding(),
)?;
assert_eq!(nbytes, 32);
Ok(bytes)
}
pub fn decode_block_header(
header_bytes: &[u8],
) -> Result<BlockHeader, E> {
Ok(decode_from_slice(header_bytes, bincode::config::standard().with_fixed_int_encoding())?.0)
}
pub fn read_block_header<R: Read>(
conn: &mut R,
) -> Result<BlockHeader, E> {
let mut header_bytes: [u8; 32] = [0_u8; 32];
conn.read_exact(&mut header_bytes)?;
let res = decode_block_header(&header_bytes)?;
Ok(res)
}
pub fn read_block_flags<R: Read>(
header: &BlockHeader,
conn: &mut R,
) -> Result<BlockFlags, E> {
let mut flags_bytes: Vec<u8> = vec![0; header.flags_len as usize];
conn.read_exact(&mut flags_bytes)?;
let metadata_compression = MetadataCompression::from_u8(header.metadata_compression)?;
let res = decode_block_flags(&flags_bytes, &metadata_compression)?;
Ok(res)
}
pub fn read_block_header_and_flags<R: Read>(
conn: &mut R,
) -> Result<(BlockHeader, BlockFlags), E> {
let header = read_block_header(conn)?;
let flags = read_block_flags(&header, conn)?;
Ok((header, flags))
}
pub fn encode_block_flags(
flags: &BlockFlags,
compression: &MetadataCompression,
) -> Result<Vec<u8>, E> {
let mut bytes: Vec<u8> = Vec::new();
match compression {
MetadataCompression::BincodeStandard => {
let _ = encode_into_std_write(
flags,
&mut bytes,
bincode::config::standard(),
)?;
},
MetadataCompression::Flate2 => {
let _ = encode_into_std_write(
flags,
&mut bytes,
bincode::config::standard(),
)?;
bytes = deflate_bytes(&bytes)?;
},
}
Ok(bytes)
}
pub fn decode_block_flags(
bytes: &[u8],
compression: &MetadataCompression,
) -> Result<BlockFlags, E> {
let flags: BlockFlags = match compression {
MetadataCompression::BincodeStandard => {
decode_from_slice(
bytes,
bincode::config::standard(),
)?.0
},
MetadataCompression::Flate2 => {
let inflated = inflate_bytes(bytes)?;
decode_from_slice(
&inflated,
bincode::config::standard(),
)?.0
},
};
Ok(flags)
}
pub fn encode_block_header_and_flags(
header: &mut BlockHeader,
flags: &BlockFlags,
) -> Result<Vec<u8>, E> {
let mut flags_bytes = encode_block_flags(flags, &MetadataCompression::from_u8(header.metadata_compression)?)?;
header.flags_len = flags_bytes.len() as u64;
let mut bytes = encode_block_header(header)?;
bytes.append(&mut flags_bytes);
Ok(bytes)
}
#[cfg(test)]
mod tests {
#[test]
fn encode_block_header() {
use super::encode_block_header;
use super::BlockHeader;
let data = BlockHeader{ num_records: 31, placeholder1: 0, block_len: 65511, flags_len: 921, fields_present: 0, placeholder2: 0, placeholder3: 0, bitmap_type: 0, metadata_compression: 0 };
let expected: Vec<u8> = vec![31, 0, 0, 0, 0, 0, 0, 0, 231, 255, 0, 0, 153, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let got = encode_block_header(&data).unwrap();
assert_eq!(got, expected);
}
#[test]
fn decode_block_header() {
use super::decode_block_header;
use super::BlockHeader;
let expected = BlockHeader{ num_records: 31, placeholder1: 0, block_len: 65511, flags_len: 921, fields_present: 0, placeholder2: 0, placeholder3: 0, bitmap_type: 0, metadata_compression: 0 };
let data: Vec<u8> = vec![31, 0, 0, 0, 0, 0, 0, 0, 231, 255, 0, 0, 153, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let got = decode_block_header(&data).unwrap();
assert_eq!(got, expected);
}
#[test]
fn read_block_header() {
use super::read_block_header;
use super::BlockHeader;
use std::io::Cursor;
let expected = BlockHeader{ num_records: 31, placeholder1: 0, block_len: 65511, flags_len: 921, fields_present: 0, placeholder2: 0, placeholder3: 0, bitmap_type: 0, metadata_compression: 0 };
let data_bytes: Vec<u8> = vec![31, 0, 0, 0, 0, 0, 0, 0, 231, 255, 0, 0, 153, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let mut data: Cursor<Vec<u8>> = Cursor::new(data_bytes);
let got = read_block_header(&mut data).unwrap();
assert_eq!(got, expected);
}
#[test]
fn encode_block_flags() {
use super::encode_block_flags;
use super::BlockFlags;
use crate::MetadataCompression;
let data = BlockFlags{ queries: Some(vec!["a".as_bytes().to_vec(), "b".as_bytes().to_vec(), "c".as_bytes().to_vec()]), query_ids: Some(vec![1, 0, 2]) };
let expected: Vec<u8> = vec![31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 99, 100, 102, 76, 100, 76, 98, 76, 102, 100, 102, 100, 96, 2, 0, 249, 181, 108, 55, 13, 0, 0, 0];
let got = encode_block_flags(&data, &MetadataCompression::Flate2).unwrap();
assert_eq!(got, expected);
}
#[test]
fn decode_block_flags() {
use super::decode_block_flags;
use super::BlockFlags;
use crate::compression::MetadataCompression;
let expected = BlockFlags{ queries: Some(vec!["a".as_bytes().to_vec(), "b".as_bytes().to_vec(), "c".as_bytes().to_vec()]), query_ids: Some(vec![1, 0, 2]) };
let data: Vec<u8> = vec![31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 99, 100, 102, 76, 100, 76, 98, 76, 102, 100, 102, 100, 96, 2, 0, 249, 181, 108, 55, 13, 0, 0, 0];
let got = decode_block_flags(&data, &MetadataCompression::Flate2).unwrap();
assert_eq!(got, expected);
}
#[test]
fn read_block_flags() {
use super::read_block_flags;
use super::BlockFlags;
use super::BlockHeader;
use std::io::Cursor;
let expected = BlockFlags{ queries: Some(vec!["a".as_bytes().to_vec(), "b".as_bytes().to_vec(), "c".as_bytes().to_vec()]), query_ids: Some(vec![1, 0, 2]) };
let data_bytes: Vec<u8> = vec![31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 99, 100, 102, 76, 100, 76, 98, 76, 102, 100, 102, 100, 96, 2, 0, 249, 181, 108, 55, 13, 0, 0, 0];
let header = BlockHeader {
num_records: 31,
placeholder1: 0,
block_len: 65511,
flags_len: data_bytes.len() as u64,
fields_present: 0,
placeholder2: 0,
placeholder3: 0,
bitmap_type: 0,
metadata_compression: 1,
};
let mut data: Cursor<Vec<u8>> = Cursor::new(data_bytes);
let got = read_block_flags(&header, &mut data).unwrap();
assert_eq!(got, expected);
}
#[test]
fn read_block_header_and_flags() {
use super::read_block_header_and_flags;
use super::BlockFlags;
use super::BlockHeader;
use std::io::Cursor;
let data_bytes: Vec<u8> = vec![31, 0, 0, 0, 0, 0, 0, 0, 231, 255, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 97, 1, 98, 1, 99, 1, 3, 1, 0, 2];
let mut data: Cursor<Vec<u8>> = Cursor::new(data_bytes);
let expected_header = BlockHeader{ num_records: 31, placeholder1: 0, block_len: 65511, flags_len: 13, fields_present: 0, placeholder2: 0, placeholder3: 0, bitmap_type: 0, metadata_compression: 0 };
let expected_flags = BlockFlags{ queries: Some(vec!["a".as_bytes().to_vec(), "b".as_bytes().to_vec(), "c".as_bytes().to_vec()]), query_ids: Some(vec![1, 0, 2]) };
let (got_header, got_flags) = read_block_header_and_flags(&mut data).unwrap();
assert_eq!(got_header, expected_header);
assert_eq!(got_flags, expected_flags);
}
}