242 lines
6.9 KiB
Rust
242 lines
6.9 KiB
Rust
use rmp::{Marker, decode::{ExtMeta, RmpRead, ValueReadError}, encode::{RmpWrite, ValueWriteError}};
|
|
|
|
pub trait RmpData: Sized {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>>;
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>>;
|
|
}
|
|
|
|
pub trait EventRecord: RmpData {
|
|
fn field_count() -> usize;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum SimDataError<E> {
|
|
StreamIndexMissing,
|
|
InvalidChunkSize { expected: usize, found: usize },
|
|
MissingTimecode,
|
|
BadString,
|
|
DecodeError(E),
|
|
EndOfStream,
|
|
UnsupportedStreamType(ExtMeta),
|
|
EventHeaderMissing,
|
|
PartitionNotFound
|
|
}
|
|
|
|
impl<E> From<E> for SimDataError<E> {
|
|
fn from(value: E) -> Self {
|
|
SimDataError::DecodeError(value)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum StreamType {
|
|
IMU,
|
|
GPS,
|
|
Annotations
|
|
}
|
|
|
|
impl TryFrom<i8> for StreamType {
|
|
type Error = ();
|
|
|
|
fn try_from(value: i8) -> Result<Self, Self::Error> {
|
|
match value {
|
|
1 => Ok(StreamType::IMU),
|
|
2 => Ok(StreamType::GPS),
|
|
3 => Ok(StreamType::Annotations),
|
|
_ => Err(())
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<StreamType> for i8 {
|
|
fn from(value: StreamType) -> Self {
|
|
match value {
|
|
StreamType::IMU => 1,
|
|
StreamType::GPS => 2,
|
|
StreamType::Annotations => 3
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct StreamIndex {
|
|
pub count: usize
|
|
}
|
|
|
|
impl RmpData for StreamIndex {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
rmp::decode::read_array_len(reader).map(|count| {
|
|
Self {
|
|
count: count as usize
|
|
}
|
|
}).map_err(|_| { SimDataError::StreamIndexMissing })
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_array_len(writer, self.count as u32)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct StreamHeader {
|
|
pub id: StreamType,
|
|
pub size: usize,
|
|
}
|
|
|
|
impl RmpData for StreamHeader {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
let meta = rmp::decode::read_ext_meta(reader)?;
|
|
if let Ok(id) = meta.typeid.try_into() {
|
|
Ok(Self {
|
|
id,
|
|
size: meta.size as usize
|
|
})
|
|
} else {
|
|
Err(SimDataError::UnsupportedStreamType(meta))
|
|
}
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, _writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct EventStreamHeader {
|
|
pub count: usize
|
|
}
|
|
|
|
impl RmpData for EventStreamHeader {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
Ok(Self {
|
|
count: rmp::decode::read_array_len(reader)? as usize
|
|
})
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_array_len(writer, self.count as u32)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Default, Debug)]
|
|
pub struct StreamEvent<Event: EventRecord> {
|
|
pub timecode: f64,
|
|
pub data: Event
|
|
}
|
|
|
|
impl<Event: EventRecord> RmpData for StreamEvent<Event> {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
let chunk_len = rmp::decode::read_array_len(reader).map_err(|_| { SimDataError::EventHeaderMissing })? as usize;
|
|
// Add 1 to the field count for the timestamp
|
|
if chunk_len != Event::field_count() + 1 {
|
|
Err(SimDataError::InvalidChunkSize { expected: Event::field_count(), found: chunk_len })
|
|
} else {
|
|
let timecode = rmp::decode::read_f64(reader).map_err(|_| { SimDataError::MissingTimecode })?;
|
|
Ok(Self {
|
|
timecode,
|
|
data: Event::from_rmp(reader)?
|
|
})
|
|
}
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_array_len(writer, Event::field_count() as u32 + 1)?;
|
|
rmp::encode::write_f64(writer, self.timecode)?;
|
|
self.data.write_rmp(writer)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct GPSReading {
|
|
pub lat: f64,
|
|
pub lon: f64
|
|
}
|
|
|
|
impl EventRecord for GPSReading {
|
|
fn field_count() -> usize {
|
|
2
|
|
}
|
|
}
|
|
|
|
impl EventRecord for IMUReading {
|
|
fn field_count() -> usize {
|
|
6
|
|
}
|
|
}
|
|
|
|
impl RmpData for GPSReading {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
Ok(Self {
|
|
lat: rmp::decode::read_f64(reader)?,
|
|
lon: rmp::decode::read_f64(reader)?
|
|
})
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_f64(writer, self.lat)?;
|
|
rmp::encode::write_f64(writer, self.lon)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct IMUReading {
|
|
pub accel_x: f64,
|
|
pub accel_y: f64,
|
|
pub accel_z: f64,
|
|
pub gyro_x: f64,
|
|
pub gyro_y: f64,
|
|
pub gyro_z: f64
|
|
}
|
|
|
|
impl RmpData for IMUReading {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
Ok(Self {
|
|
accel_x: rmp::decode::read_f64(reader)?,
|
|
accel_y: rmp::decode::read_f64(reader)?,
|
|
accel_z: rmp::decode::read_f64(reader)?,
|
|
|
|
gyro_x: rmp::decode::read_f64(reader)?,
|
|
gyro_y: rmp::decode::read_f64(reader)?,
|
|
gyro_z: rmp::decode::read_f64(reader)?,
|
|
})
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_f64(writer, self.accel_x)?;
|
|
rmp::encode::write_f64(writer, self.accel_y)?;
|
|
rmp::encode::write_f64(writer, self.accel_z)?;
|
|
|
|
rmp::encode::write_f64(writer, self.gyro_x)?;
|
|
rmp::encode::write_f64(writer, self.gyro_y)?;
|
|
rmp::encode::write_f64(writer, self.gyro_z)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct AnnotationReading {
|
|
pub buf: [u8;32]
|
|
}
|
|
|
|
impl RmpData for AnnotationReading {
|
|
fn from_rmp<Reader: RmpRead>(reader: &mut Reader) -> Result<Self, SimDataError<ValueReadError<Reader::Error>>> {
|
|
let mut buf = [0; 32];
|
|
rmp::decode::read_str(reader, &mut buf).map_err(|_| { SimDataError::BadString })?;
|
|
Ok(Self {
|
|
buf
|
|
})
|
|
}
|
|
|
|
fn write_rmp<Writer: RmpWrite>(&self, writer: &mut Writer) -> Result<(), ValueWriteError<Writer::Error>> {
|
|
rmp::encode::write_str(writer, core::str::from_utf8(&self.buf).unwrap())?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl EventRecord for AnnotationReading {
|
|
fn field_count() -> usize {
|
|
1
|
|
}
|
|
} |