rsbag/examples/bag_info.rs

153 lines
4.5 KiB
Rust
Raw Normal View History

2021-11-19 15:19:35 -08:00
use std::{collections::HashMap, convert::TryFrom, env::args, fs::File, io};
2021-11-18 15:11:56 -08:00
2021-11-19 14:15:15 -08:00
use eyre::Context;
2021-11-18 15:11:56 -08:00
use log::{error, info, trace};
2021-11-18 22:50:42 -08:00
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use regex::Regex;
use ros_message::{MessagePath, Msg};
use rsbag::{
2021-11-19 14:15:15 -08:00
chunk::ChunkHeader,
2021-11-19 15:19:35 -08:00
index::{BagIndex, ConnInfo, IndexData},
2021-11-18 21:05:46 -08:00
reader::{BagReader, MmapReader},
2021-11-19 14:15:15 -08:00
Result,
};
2021-11-19 14:15:15 -08:00
fn parse_msgdef(message_name: &str, msgdef: &str) -> Result<Msg> {
trace!("message definition: {}", msgdef);
2021-11-19 14:15:15 -08:00
let path = MessagePath::try_from(message_name)?;
let msgtype = Msg::new(path, msgdef)?;
Ok(msgtype)
}
2021-11-19 14:15:15 -08:00
fn parse_message_definitions(conn: &ConnInfo) -> Result<Vec<Msg>> {
let msgdefs = &conn.message_definition;
let boundary_re = Regex::new(r"\r?\n==+\r?\nMSG: ([^\r\n]+)\r?\n")?;
let mut name = conn.datatype.clone();
let mut begin = 0usize;
let mut msgs = Vec::new();
2021-11-19 14:15:15 -08:00
for cap in boundary_re.captures_iter(msgdefs) {
let boundary_range = cap.get(0).unwrap();
let end = boundary_range.start();
let msgdef = &msgdefs[begin..end];
let msgtype = parse_msgdef(&name, msgdef)?;
msgs.push(msgtype);
name = cap[1].to_string();
begin = boundary_range.end();
}
let msgdef = &msgdefs[begin..];
let msg = parse_msgdef(&name, msgdef)?;
msgs.push(msg);
Ok(msgs)
}
2021-11-18 15:11:56 -08:00
2021-11-19 14:15:15 -08:00
fn read_chunk<R: BagReader>(bag_reader: &mut R, pos: u64) -> Result<Vec<u8>> {
let chunk_header = ChunkHeader::read(bag_reader, pos)?;
2021-11-18 22:50:42 -08:00
2021-11-19 14:15:15 -08:00
let compressed_data = bag_reader.read_data()?;
2021-11-18 22:50:42 -08:00
let mut data = Vec::with_capacity(chunk_header.uncompressed_size as usize);
let mut decompresor = chunk_header.compression.decompress(compressed_data);
2021-11-19 14:15:15 -08:00
io::copy(&mut decompresor, &mut data)?;
2021-11-18 22:50:42 -08:00
Ok(data)
}
2021-11-19 15:19:35 -08:00
#[derive(Default, Debug)]
struct BagInfo {
total_uncompressed: u64,
per_connection: HashMap<u32, u64>,
}
impl BagInfo {
fn combine(mut self, other: BagInfo) -> BagInfo {
self.total_uncompressed += other.total_uncompressed;
for (conn, count) in other.per_connection {
*self.per_connection.entry(conn).or_insert(0) += count;
}
self
}
}
2021-11-19 14:15:15 -08:00
fn main() -> Result<()> {
color_eyre::install()?;
2021-11-18 15:11:56 -08:00
env_logger::init();
let args: Vec<_> = args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <bag path>", args[0]);
2021-11-19 14:15:15 -08:00
return Ok(());
2021-11-18 15:11:56 -08:00
}
let bag_path = &args[1];
let bag_file = File::open(bag_path).expect("Could not open bag file");
2021-11-19 14:15:15 -08:00
let mut bag_reader = MmapReader::new(bag_file)?;
2021-11-18 21:05:46 -08:00
2021-11-19 14:15:15 -08:00
let index = BagIndex::read_all(&mut bag_reader).wrap_err("bag parse error")?;
2021-11-18 21:05:46 -08:00
for conn in &index.connections {
match parse_message_definitions(conn) {
Ok(msgs) => {
for msg in &msgs {
2021-11-18 22:50:42 -08:00
trace!(
2021-11-18 21:05:46 -08:00
"message definition parsed: {:#?}",
msg.fields()
.iter()
.filter(|field| !field.is_constant())
.map(ToString::to_string)
.collect::<Vec<_>>()
);
2021-11-18 15:11:56 -08:00
}
}
2021-11-18 21:05:46 -08:00
Err(err) => error!("could not parse message definition: {}", err),
}
2021-11-18 15:11:56 -08:00
}
2021-11-18 21:05:46 -08:00
2021-11-19 15:19:35 -08:00
let data = index
2021-11-18 22:50:42 -08:00
.chunks
.par_iter()
2021-11-19 15:19:35 -08:00
.try_fold(BagInfo::default, |mut data, chunk| -> rsbag::Result<_> {
let mut reader = bag_reader.clone();
let chunk_header = ChunkHeader::read(&mut reader, chunk.pos)?;
data.total_uncompressed += chunk_header.uncompressed_size as u64;
reader.skip_data()?;
for _ in &chunk.connections {
let index = IndexData::read(&mut reader)?;
*data.per_connection.entry(index.conn_id).or_insert(0) +=
index.entries.len() as u64;
}
// let data = read_chunk(&mut bag_reader.clone(), chunk.pos)?;
// chunks.push(data);
Ok(data)
})
.try_reduce(BagInfo::default, |a, b| Ok(a.combine(b)))
2021-11-19 14:15:15 -08:00
.unwrap();
2021-11-19 15:19:35 -08:00
info!("bag data: {:#?}", data);
2021-11-19 14:15:15 -08:00
// let total_size = index
// .chunks
// .par_iter()
// .try_fold(
// || 0u64,
// |total_size, chunk| -> Result<_> {
// let data = read_chunk(&mut bag_reader.clone(), chunk.pos)?;
// Ok(total_size + data.len() as u64)
// },
// )
// .reduce(
// // || Ok(Vec::new()),
// || Ok(0),
// |a, b| a.and_then(|a| b.map(|b| a + b)),
// )?;
2021-11-18 21:05:46 -08:00
2021-11-19 14:15:15 -08:00
Ok(())
2021-11-18 15:11:56 -08:00
}