px4_ulog/parser/
message.rs

1use models::ULogMessage;
2use std::fs::File;
3use std::io::prelude::*;
4use std::io::SeekFrom;
5
6use unpack;
7
8const HEADER_SIZE: u64 = 16;
9
10pub trait ULogMessageSource {
11    /// Creates an iterator that reads through every message in the log file
12    ///
13    /// # Examples
14    /// ```
15    /// use std::iter::*;
16    /// use px4_ulog::parser::message::*;
17    /// use px4_ulog::models::*;
18    ///
19    /// let filename = format!("{}/tests/fixtures/6ba1abc7-b433-4029-b8f5-3b2bb12d3b6c.ulg", env!("CARGO_MANIFEST_DIR"));
20    /// let mut log_file = std::fs::File::open(&filename).unwrap();
21    /// let messages: Vec<ULogMessage> = log_file.messages().collect();
22    /// assert_eq!(messages[0].position(), 19);
23    /// assert_eq!(messages[0].msg_type(), MessageType::FlagBits);
24    /// assert_eq!(messages[0].size(), 40);
25    /// assert_eq!(messages[1].position(), 62);
26    /// assert_eq!(messages[21130].position(), 973045);
27    /// assert_eq!(messages.len(), 21131);
28    /// ```
29    fn messages(&mut self) -> ULogMessageIter;
30}
31
32pub struct ULogMessageIter<'a> {
33    position: u64,
34    file: &'a mut File,
35}
36
37impl ULogMessageSource for File {
38    fn messages(&mut self) -> ULogMessageIter {
39        ULogMessageIter {
40            position: HEADER_SIZE,
41            file: self,
42        }
43    }
44}
45
46impl<'a> Iterator for ULogMessageIter<'a> {
47    type Item = ULogMessage;
48
49    fn next(&mut self) -> Option<ULogMessage> {
50        if self.file.seek(SeekFrom::Start(self.position)).is_err() {
51            return None;
52        }
53
54        let mut buffer = [0; 2];
55        if self.file.read_exact(&mut buffer).is_err() {
56            return None;
57        }
58        let msg_size = unpack::as_u16_le(&buffer);
59
60        let mut buffer = [0; 1];
61        if self.file.read_exact(&mut buffer).is_err() {
62            return None;
63        }
64        let msg_type = buffer[0];
65
66        let msg_pos = self.position + 3;
67
68        self.position += msg_size as u64 + 3;
69
70        Some(ULogMessage::new(msg_type, msg_size, msg_pos))
71    }
72}