diff --git a/examples/bag_info.rs b/examples/bag_info.rs index a4a0aac..b757cfe 100644 --- a/examples/bag_info.rs +++ b/examples/bag_info.rs @@ -5,7 +5,7 @@ use regex::Regex; use ros_message::{MessagePath, Msg}; use rsbag::{ index::{BagIndex, ConnInfo}, - reader::IoReader, + reader::{BagReader, MmapReader}, }; fn parse_msgdef(message_name: &str, msgdef: &str) -> rsbag::Result { @@ -53,28 +53,40 @@ fn main() { let bag_path = &args[1]; let bag_file = File::open(bag_path).expect("Could not open bag file"); - let mut bag_reader = IoReader::new(bag_file); + let mut bag_reader = MmapReader::new(bag_file).unwrap(); - match BagIndex::read_all(&mut bag_reader) { - Ok(index) => { - for conn in &index.connections { - match parse_message_definitions(conn) { - Ok(msgs) => { - for msg in &msgs { - info!( - "message definition parsed: {:#?}", - msg.fields() - .iter() - .filter(|field| !field.is_constant()) - .map(ToString::to_string) - .collect::>() - ); - } - } - Err(err) => error!("could not parse message definition: {}", err), + let index = match BagIndex::read_all(&mut bag_reader) { + Ok(index) => index, + Err(err) => { + error!("bag parse error: {}", err); + return; + } + }; + + for conn in &index.connections { + match parse_message_definitions(conn) { + Ok(msgs) => { + for msg in &msgs { + info!( + "message definition parsed: {:#?}", + msg.fields() + .iter() + .filter(|field| !field.is_constant()) + .map(ToString::to_string) + .collect::>() + ); } } + Err(err) => error!("could not parse message definition: {}", err), } - Err(err) => error!("bag parse error: {}", err), } + + let mut total_size = 0; + + for chunk in &index.chunks { + let chunk_header = bag_reader.read_chunk_header(chunk.pos).unwrap(); + total_size += chunk_header.uncompressed_size; + } + + info!("total uncompressed size: {}", total_size); } diff --git a/src/chunk.rs b/src/chunk.rs new file mode 100644 index 0000000..c141226 --- /dev/null +++ b/src/chunk.rs @@ -0,0 +1,38 @@ +use std::str::FromStr; + +use crate::{parse::Header, Error, Result}; + +#[derive(Clone, Copy, Debug)] +pub enum Compression { + None, + Bz2, + Lz4, +} + +impl FromStr for Compression { + type Err = Error; + + fn from_str(s: &str) -> Result { + Ok(match s { + "none" => Compression::None, + "bz2" => Compression::Bz2, + "lz4" => Compression::Lz4, + _ => return Err(Error::UnsupportedCompression(s.to_string())), + }) + } +} + +#[derive(Debug)] +pub struct ChunkHeader { + pub compression: Compression, + pub uncompressed_size: u32, +} + +impl ChunkHeader { + pub fn from_header(header: Header) -> Result { + Ok(Self { + compression: header.read_string(b"compression")?.parse()?, + uncompressed_size: header.read_u32(b"size")?, + }) + } +} diff --git a/src/error.rs b/src/error.rs index ad7f55e..8fbb6b0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -13,6 +13,8 @@ pub enum Error { UnsupportedVersion(parse::Version), #[error("unsupported encryptor: {0}")] UnsupportedEncryptor(String), + #[error("unsupported compression: {0}")] + UnsupportedCompression(String), #[error("unexpected EOF")] Eof, #[error("invalid header op: {0}")] diff --git a/src/lib.rs b/src/lib.rs index a9f05f5..50a6cb2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,5 +2,6 @@ mod error; pub mod index; pub mod parse; pub mod reader; +pub mod chunk; pub use error::{Error, Result}; diff --git a/src/reader.rs b/src/reader.rs index ebc0065..5652fe1 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -2,6 +2,7 @@ use std::io::SeekFrom; use nom::number::streaming::le_u32; +use crate::chunk::ChunkHeader; use crate::error::{Error, Result}; use crate::index::{ChunkInfo, ConnInfo}; use crate::parse::{self, Header, Op, Version}; @@ -59,4 +60,10 @@ pub trait BagReader { self.skip_data()?; ChunkInfo::from_header(header) } + + fn read_chunk_header(&mut self, pos: u64) -> Result { + self.seek(SeekFrom::Start(pos))?; + let header = self.read_header_op(Op::Chunk)?; + ChunkHeader::from_header(header) + } }