time parsing
This commit is contained in:
parent
4e5898c0c0
commit
733d2d61a3
@ -1,4 +1,4 @@
|
|||||||
use std::{convert::TryFrom, env::args, fs::File, io};
|
use std::{collections::HashMap, convert::TryFrom, env::args, fs::File, io};
|
||||||
|
|
||||||
use eyre::Context;
|
use eyre::Context;
|
||||||
use log::{error, info, trace};
|
use log::{error, info, trace};
|
||||||
@ -7,7 +7,7 @@ use regex::Regex;
|
|||||||
use ros_message::{MessagePath, Msg};
|
use ros_message::{MessagePath, Msg};
|
||||||
use rsbag::{
|
use rsbag::{
|
||||||
chunk::ChunkHeader,
|
chunk::ChunkHeader,
|
||||||
index::{BagIndex, ConnInfo},
|
index::{BagIndex, ConnInfo, IndexData},
|
||||||
reader::{BagReader, MmapReader},
|
reader::{BagReader, MmapReader},
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
@ -57,6 +57,23 @@ fn read_chunk<R: BagReader>(bag_reader: &mut R, pos: u64) -> Result<Vec<u8>> {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
color_eyre::install()?;
|
color_eyre::install()?;
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
@ -91,28 +108,30 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_size = index
|
let data = index
|
||||||
.chunks
|
.chunks
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.try_fold(
|
.try_fold(BagInfo::default, |mut data, chunk| -> rsbag::Result<_> {
|
||||||
|| 0u64,
|
let mut reader = bag_reader.clone();
|
||||||
|total_size, chunk| -> rsbag::Result<_> {
|
let chunk_header = ChunkHeader::read(&mut reader, chunk.pos)?;
|
||||||
let mut reader = bag_reader.clone();
|
data.total_uncompressed += chunk_header.uncompressed_size as u64;
|
||||||
let chunk_header = ChunkHeader::read(&mut reader, chunk.pos)?;
|
reader.skip_data()?;
|
||||||
reader.skip_data()?;
|
|
||||||
|
|
||||||
// let data = read_chunk(&mut bag_reader.clone(), chunk.pos)?;
|
for _ in &chunk.connections {
|
||||||
// chunks.push(data);
|
let index = IndexData::read(&mut reader)?;
|
||||||
Ok(total_size + chunk_header.uncompressed_size as u64)
|
*data.per_connection.entry(index.conn_id).or_insert(0) +=
|
||||||
},
|
index.entries.len() as u64;
|
||||||
)
|
}
|
||||||
.reduce(
|
|
||||||
// || Ok(Vec::new()),
|
// let data = read_chunk(&mut bag_reader.clone(), chunk.pos)?;
|
||||||
|| Ok(0),
|
// chunks.push(data);
|
||||||
|a, b| a.and_then(|a| b.map(|b| a + b)),
|
Ok(data)
|
||||||
)
|
})
|
||||||
|
.try_reduce(BagInfo::default, |a, b| Ok(a.combine(b)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
info!("bag data: {:#?}", data);
|
||||||
|
|
||||||
// let total_size = index
|
// let total_size = index
|
||||||
// .chunks
|
// .chunks
|
||||||
// .par_iter()
|
// .par_iter()
|
||||||
@ -129,7 +148,5 @@ fn main() -> Result<()> {
|
|||||||
// |a, b| a.and_then(|a| b.map(|b| a + b)),
|
// |a, b| a.and_then(|a| b.map(|b| a + b)),
|
||||||
// )?;
|
// )?;
|
||||||
|
|
||||||
info!("total uncompressed size: {}", total_size);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
56
src/index.rs
56
src/index.rs
@ -6,7 +6,7 @@ use nom::{number::streaming::le_u32, sequence::tuple, Parser};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
parse::{self, Header, Op},
|
parse::{self, header::Time, Header, Op},
|
||||||
reader::BagReader,
|
reader::BagReader,
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
@ -41,8 +41,8 @@ impl ConnInfo {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ChunkInfo {
|
pub struct ChunkInfo {
|
||||||
pub pos: u64,
|
pub pos: u64,
|
||||||
pub start_time: u64, // TODO: unpack time
|
pub start_time: Time,
|
||||||
pub end_time: u64,
|
pub end_time: Time,
|
||||||
pub connections: Vec<ChunkConnection>,
|
pub connections: Vec<ChunkConnection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ impl ChunkInfo {
|
|||||||
}
|
}
|
||||||
Ok(ChunkInfo {
|
Ok(ChunkInfo {
|
||||||
pos: header.read_u64(b"chunk_pos")?,
|
pos: header.read_u64(b"chunk_pos")?,
|
||||||
start_time: header.read_u64(b"start_time")?,
|
start_time: header.read_time(b"start_time")?,
|
||||||
end_time: header.read_u64(b"end_time")?,
|
end_time: header.read_time(b"end_time")?,
|
||||||
connections,
|
connections,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -151,3 +151,49 @@ impl BagIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IndexData {
|
||||||
|
pub conn_id: u32,
|
||||||
|
pub entries: Vec<IndexEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexData {
|
||||||
|
pub fn read<R: BagReader>(reader: &mut R) -> Result<Self> {
|
||||||
|
let header = reader.read_header_op(Op::IndexData)?;
|
||||||
|
if header.read_u32(b"ver")? != 1 {
|
||||||
|
bail!("unsupported IndexData version");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.read_data_length()?; // Data length not needed
|
||||||
|
|
||||||
|
let entry_count = header.read_u32(b"count")?;
|
||||||
|
let mut entries = Vec::with_capacity(entry_count as usize);
|
||||||
|
for _ in 0..entry_count {
|
||||||
|
let conn = IndexEntry::read(reader)?;
|
||||||
|
entries.push(conn);
|
||||||
|
}
|
||||||
|
Ok(IndexData {
|
||||||
|
conn_id: header.read_u32(b"conn")?,
|
||||||
|
entries,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IndexEntry {
|
||||||
|
pub time: Time,
|
||||||
|
pub offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexEntry {
|
||||||
|
pub fn parse(input: parse::Input) -> parse::IResult<Self> {
|
||||||
|
tuple((Time::parse, le_u32))
|
||||||
|
.map(|(time, offset)| IndexEntry { time, offset })
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<R: BagReader>(reader: &mut R) -> Result<Self> {
|
||||||
|
reader.read_parser(Self::parse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@ mod fields;
|
|||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
error::{FieldDataError, MissingFieldError},
|
error::{FieldDataError, MissingFieldError},
|
||||||
fields::Op,
|
fields::{Op, Time},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -87,19 +87,23 @@ impl Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_op(&self) -> Result<fields::Op> {
|
pub fn read_op(&self) -> Result<fields::Op> {
|
||||||
self.find_field(b"op").and_then(fields::Op::parse)
|
self.find_field(b"op").and_then(fields::Op::read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_u64(&self, field: &[u8]) -> Result<u64> {
|
pub fn read_u64(&self, field: &[u8]) -> Result<u64> {
|
||||||
self.find_field(field).and_then(fields::parse_u64)
|
self.find_field(field).and_then(fields::read_u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_time(&self, field: &[u8]) -> Result<Time> {
|
||||||
|
self.read_u64(field).map(Time::from_packed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_u32(&self, field: &[u8]) -> Result<u32> {
|
pub fn read_u32(&self, field: &[u8]) -> Result<u32> {
|
||||||
self.find_field(field).and_then(fields::parse_u32)
|
self.find_field(field).and_then(fields::read_u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_string(&self, field: &[u8]) -> Result<String> {
|
pub fn read_string(&self, field: &[u8]) -> Result<String> {
|
||||||
self.find_field(field).and_then(fields::parse_string)
|
self.find_field(field).and_then(fields::read_string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ use nom::{
|
|||||||
};
|
};
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
|
use crate::parse::IResult;
|
||||||
|
|
||||||
use super::{FieldDataError, Input, Result};
|
use super::{FieldDataError, Input, Result};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, TryFromPrimitive, PartialEq)]
|
#[derive(Clone, Copy, Debug, TryFromPrimitive, PartialEq)]
|
||||||
@ -19,7 +21,7 @@ pub enum Op {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Op {
|
impl Op {
|
||||||
pub fn parse(input: Input) -> Result<Self> {
|
pub fn read(input: Input) -> Result<Self> {
|
||||||
let (_, op) = all_consuming(le_u8)
|
let (_, op) = all_consuming(le_u8)
|
||||||
.parse(input)
|
.parse(input)
|
||||||
.map_err(FieldDataError::from)?;
|
.map_err(FieldDataError::from)?;
|
||||||
@ -27,20 +29,44 @@ impl Op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_u32(input: Input) -> Result<u32> {
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Time {
|
||||||
|
pub sec: u32,
|
||||||
|
pub nsec: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Time {
|
||||||
|
pub fn from_packed(packed: u64) -> Time {
|
||||||
|
Time {
|
||||||
|
sec: packed as u32,
|
||||||
|
nsec: (packed >> 32) as u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(input: Input) -> IResult<Self> {
|
||||||
|
le_u64.map(Time::from_packed).parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(input: Input) -> Result<Self> {
|
||||||
|
let (_, x) = Self::parse(input).map_err(FieldDataError::from)?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u32(input: Input) -> Result<u32> {
|
||||||
let (_, x) = all_consuming(le_u32)
|
let (_, x) = all_consuming(le_u32)
|
||||||
.parse(input)
|
.parse(input)
|
||||||
.map_err(FieldDataError::from)?;
|
.map_err(FieldDataError::from)?;
|
||||||
Ok(x)
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_u64(input: Input) -> Result<u64> {
|
pub fn read_u64(input: Input) -> Result<u64> {
|
||||||
let (_, x) = all_consuming(le_u64)
|
let (_, x) = all_consuming(le_u64)
|
||||||
.parse(input)
|
.parse(input)
|
||||||
.map_err(FieldDataError::from)?;
|
.map_err(FieldDataError::from)?;
|
||||||
Ok(x)
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_string(input: Input) -> Result<String> {
|
pub fn read_string(input: Input) -> Result<String> {
|
||||||
Ok(String::from_utf8(input.to_owned())?)
|
Ok(String::from_utf8(input.to_owned())?)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user