historypack: add serialization logic for FileSectionHeaders

Summary:
In an upcoming diff we'll start writing the actual history pack data
file. The file section headers are part of that file, so let's implement the
serialization logic and unit test it.

Reviewed By: markbt

Differential Revision: D9231400

fbshipit-source-id: eb1494e3b8fe3419f77edcaab25f640b48f16e4b
This commit is contained in:
Durham Goode 2018-08-15 15:05:55 -07:00 committed by Facebook Github Bot
parent 1d19243ea1
commit 6158355747
2 changed files with 61 additions and 3 deletions

View File

@ -72,7 +72,7 @@ pub struct NodeLocation {
}
#[derive(PartialEq, Debug)]
struct FileIndexEntry {
pub(crate) struct FileIndexEntry {
pub node: Node,
pub file_section_offset: u64,
pub file_section_size: u64,
@ -107,7 +107,7 @@ impl FileIndexEntry {
}
#[derive(Debug, PartialEq)]
struct NodeIndexEntry {
pub(crate) struct NodeIndexEntry {
pub node: Node,
pub offset: u64,
}
@ -132,7 +132,7 @@ impl NodeIndexEntry {
}
}
pub struct HistoryIndex {
pub(crate) struct HistoryIndex {
mmap: Mmap,
version: HistoryPackVersion,
fanout_size: usize,

View File

@ -1,3 +1,6 @@
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Cursor, Read, Write};
use error::Result;
#[derive(Debug, Fail)]
@ -31,3 +34,58 @@ impl From<HistoryPackVersion> for u8 {
}
}
}
#[derive(Debug, PartialEq)]
struct FileSectionHeader<'a> {
pub file_name: &'a [u8],
pub count: u32,
}
fn read_slice<'a, 'b>(cur: &'a mut Cursor<&[u8]>, buf: &'b [u8], size: usize) -> Result<&'b [u8]> {
let start = cur.position() as usize;
let end = start + size;
let file_name = &buf.get(start..end).ok_or_else(|| {
HistoryPackError(format!(
"buffer (length {:?}) not long enough to read {:?} bytes",
buf.len(),
size
))
})?;
cur.set_position(end as u64);
Ok(file_name)
}
impl<'a> FileSectionHeader<'a> {
pub(crate) fn read(buf: &[u8]) -> Result<FileSectionHeader> {
let mut cur = Cursor::new(buf);
let file_name_len = cur.read_u16::<BigEndian>()? as usize;
let file_name = read_slice(&mut cur, &buf, file_name_len)?;
let count = cur.read_u32::<BigEndian>()?;
Ok(FileSectionHeader { file_name, count })
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<()> {
writer.write_u16::<BigEndian>(self.file_name.len() as u16)?;
writer.write_all(self.file_name)?;
writer.write_u32::<BigEndian>(self.count)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
quickcheck! {
fn test_file_section_header_serialization(name: Vec<u8>, count: u32) -> bool {
let header = FileSectionHeader {
file_name: name.as_ref(),
count: count,
};
let mut buf = vec![];
header.write(&mut buf).unwrap();
header == FileSectionHeader::read(&buf).unwrap()
}
}
}