itelem 0.1.5

Parsing of iRacing .ibt telemetry file
Documentation
use crate::{headers::VarHeader, read_bytes_file, ReadSeek};

#[derive(Debug, PartialEq)]
pub enum SampleValue {
    Char(char),
    Bool(bool),
    Int(i32),
    BitField(u32),
    Float32(f32),
    Float64(f64),
}

impl SampleValue {
    pub fn char(&self) -> char {
        if let SampleValue::Char(x) = self {
            *x
        } else {
            panic!()
        }
    }

    pub fn bool(&self) -> bool {
        if let SampleValue::Bool(x) = self {
            *x
        } else {
            panic!()
        }
    }

    pub fn float_32(&self) -> f32 {
        if let SampleValue::Float32(x) = self {
            *x
        } else {
            panic!()
        }
    }

    pub fn float_64(&self) -> f64 {
        if let SampleValue::Float64(x) = self {
            *x
        } else {
            panic!()
        }
    }

    pub fn int(&self) -> i32 {
        if let SampleValue::Int(x) = self {
            *x
        } else {
            panic!()
        }
    }

    pub fn bitfield(&self) -> u32 {
        if let SampleValue::BitField(x) = self {
            *x
        } else {
            panic!()
        }
    }
}

#[derive(Debug)]
pub struct Sample {
    data: Vec<u8>,
}

pub struct Samples<'a> {
    pub file: &'a mut dyn ReadSeek,
    pub length: i32,
    pub buf_offset: i32,
    pub current: i32,
}

impl Iterator for Samples<'_> {
    type Item = Sample;

    fn next(&mut self) -> Option<Self::Item> {
        let from = self.buf_offset + (self.current * self.length);
        match read_bytes_file(&mut self.file, from as usize, self.length as usize) {
            Ok(data) => {
                self.current += 1;
                Some(Sample { data })
            }
            Err(_) => None,
        }
    }
}

impl Sample {
    pub fn get_by_header(&self, var: &VarHeader) -> Option<SampleValue> {
        let offset = var.offset as usize;
        match var.r#type {
            0 => {
                let size = 1;
                Some(SampleValue::Char(self.data[offset + size] as char))
            }
            1 => {
                let size = 1;
                Some(SampleValue::Bool(self.data[offset + size] != 0))
            }
            2 => {
                let size = 4;
                let value =
                    i32::from_le_bytes(self.data[offset..(offset + size)].try_into().unwrap());
                Some(SampleValue::Int(value))
            }
            3 => {
                let size = 4;
                let value =
                    u32::from_le_bytes(self.data[offset..(offset + size)].try_into().unwrap());
                Some(SampleValue::BitField(value))
            }
            4 => {
                let size = 4;
                let value =
                    f32::from_le_bytes(self.data[offset..(offset + size)].try_into().unwrap());
                Some(SampleValue::Float32(value))
            }
            5 => {
                let size = 8;
                let value =
                    f64::from_le_bytes(self.data[offset..(offset + size)].try_into().unwrap());
                Some(SampleValue::Float64(value))
            }
            _ => unimplemented!(),
        }
    }
}