rsbag/src/index.rs

125 lines
3.2 KiB
Rust

use std::io::SeekFrom;
use log::trace;
use crate::{
parse::{Header, Op},
reader::BagReader,
Error, Result,
};
#[derive(Debug)]
pub struct ConnInfo {
pub id: u32,
pub topic: String,
pub conn_header: Header,
}
impl ConnInfo {
pub fn from_headers(record_header: Header, conn_header: Header) -> Result<Self> {
Ok(ConnInfo {
id: record_header.read_u32(b"conn")?,
topic: record_header.read_string(b"topic")?,
conn_header,
})
}
pub fn message_definition(&self) -> Result<String> {
self.conn_header.read_string(b"message_definition")
}
pub fn datatype(&self) -> Result<String> {
self.conn_header.read_string(b"type")
}
pub fn md5sum(&self) -> Result<String> {
self.conn_header.read_string(b"md5sum")
}
}
#[derive(Debug)]
pub struct ChunkInfo {
pub pos: u64,
pub start_time: u64, // TODO: unpack time
pub end_time: u64,
pub conn_count: u32,
}
impl ChunkInfo {
pub fn from_header(header: Header) -> Result<Self> {
if header.read_u32(b"ver")? != 1 {
return Err(Error::other("unsupported ChunkInfo version"));
}
Ok(ChunkInfo {
pos: header.read_u64(b"chunk_pos")?,
start_time: header.read_u64(b"start_time")?,
end_time: header.read_u64(b"end_time")?,
conn_count: header.read_u32(b"count")?,
})
}
}
#[derive(Debug)]
pub struct BagIndex {
pub connections: Vec<ConnInfo>,
pub chunks: Vec<ChunkInfo>,
}
impl BagIndex {
fn read_v2<R: BagReader>(reader: &mut R) -> Result<Self> {
let file_header = reader.read_header_op(Op::FileHeader)?;
let data_length = reader.read_data_length()?;
trace!("data length: {}", data_length);
let index_pos = file_header.read_u64(b"index_pos")?;
trace!("index pos: {}", index_pos);
if index_pos == 0 {
return Err(Error::Unindexed);
}
if let Ok(encryptor) = file_header.read_string(b"encryptor") {
return Err(Error::UnsupportedEncryptor(encryptor));
}
reader.seek(SeekFrom::Start(index_pos))?;
let conn_count = file_header.read_u32(b"conn_count")?;
trace!("connection count: {}", conn_count);
let mut connections = Vec::with_capacity(conn_count as usize);
for _ in 0..conn_count {
let conn = reader.read_conn_info()?;
trace!("connection: id={}, topic={}", conn.id, conn.topic);
connections.push(conn);
}
let chunk_count = file_header.read_u32(b"chunk_count")?;
trace!("chunk count: {}", chunk_count);
let mut chunks = Vec::with_capacity(chunk_count as usize);
for _ in 0..chunk_count {
let chunk = reader.read_chunk_info()?;
chunks.push(chunk);
}
Ok(BagIndex {
connections,
chunks,
})
}
pub fn read_all<R: BagReader>(reader: &mut R) -> Result<Self> {
let version = reader.read_version()?;
trace!("bag version: {}", version);
if (version.major, version.minor) == (2, 0) {
Self::read_v2(reader)
} else {
Err(Error::UnsupportedVersion(version))
}
}
}