Skip to main content

dlt_parse/storage/
dlt_storage_writer.rs

1#[cfg(feature = "std")]
2use std::io::{Error, Write};
3
4use crate::{storage::StorageHeader, DltPacketSlice};
5
6/// Allows the writing of dlt storage files.
7///
8/// # Example
9///
10/// ```no_run
11/// use std::{fs::File, io::BufWriter};
12/// use dlt_parse::storage::{DltStorageWriter, StorageHeader};
13///
14/// let dlt_file = File::create("out.dlt").expect("failed to open output file");
15/// let mut dlt_writer = DltStorageWriter::new(BufWriter::new(dlt_file));
16///
17/// // ...
18/// # use dlt_parse::{DltHeader, DltPacketSlice};
19/// # use std::io::Write;
20/// # let packet0 = {
21/// #    let mut packet = Vec::<u8>::new();
22/// #    let mut header = DltHeader{
23/// #        is_big_endian: true,
24/// #        message_counter: 0,
25/// #        length: 0,
26/// #        ecu_id: None,
27/// #        session_id: None,
28/// #        timestamp: None,
29/// #        extended_header: None,
30/// #    };
31/// #    header.length = header.header_len() + 4;
32/// #    header.write(&mut packet).unwrap();
33/// #    packet.write_all(&[1,2,3,4]).unwrap();
34/// #    packet
35/// # };
36/// # let dlt_slice = DltPacketSlice::from_slice(&packet0).unwrap();
37/// # let timestamp_seconds = 0;
38/// # let timestamp_microseconds = 0;
39/// # let ecu_id = [0u8;4];
40///
41/// // write a dlt message
42/// dlt_writer.write_slice(
43///     StorageHeader{
44///         timestamp_seconds,
45///         timestamp_microseconds,
46///         ecu_id
47///     },
48///     dlt_slice
49/// ).expect("failed to write dlt packet");
50/// ```
51#[cfg(feature = "std")]
52#[derive(Debug)]
53pub struct DltStorageWriter<W: Write> {
54    writer: W,
55}
56
57#[cfg(feature = "std")]
58impl<W: Write> DltStorageWriter<W> {
59    /// Creates a new writer that allows writing dlt packets to a storage file.
60    pub fn new(writer: W) -> DltStorageWriter<W> {
61        DltStorageWriter { writer }
62    }
63
64    /// Writes a sliced packet into a storage file.
65    pub fn write_slice(
66        &mut self,
67        storage_header: StorageHeader,
68        dlt_slice: DltPacketSlice<'_>,
69    ) -> Result<(), Error> {
70        storage_header.write(&mut self.writer)?;
71        self.writer.write_all(dlt_slice.slice())
72    }
73}
74
75#[cfg(feature = "std")]
76#[cfg(test)]
77mod dlt_storage_writer_tests {
78    use super::*;
79    use crate::DltHeader;
80    use std::format;
81    use std::vec::Vec;
82
83    #[test]
84    fn debug() {
85        let mut buffer = Vec::<u8>::new();
86        let writer = DltStorageWriter::new(&mut buffer);
87        assert!(format!("{:?}", writer).len() > 0);
88    }
89
90    #[test]
91    fn new() {
92        let mut buffer = Vec::<u8>::new();
93        let _writer = DltStorageWriter::new(&mut buffer);
94        assert_eq!(0, buffer.len());
95    }
96
97    #[test]
98    fn write_slice() {
99        // ok
100        {
101            let mut buffer = Vec::<u8>::new();
102            let mut writer = DltStorageWriter::new(&mut buffer);
103
104            let packet0 = {
105                let mut packet = Vec::<u8>::new();
106                let mut header = DltHeader {
107                    is_big_endian: true,
108                    message_counter: 0,
109                    length: 0,
110                    ecu_id: None,
111                    session_id: None,
112                    timestamp: None,
113                    extended_header: None,
114                };
115                header.length = header.header_len() + 4;
116                header.write(&mut packet).unwrap();
117                packet.write_all(&[1, 2, 3, 4]).unwrap();
118                packet
119            };
120            let header0 = StorageHeader {
121                timestamp_seconds: 1234,
122                timestamp_microseconds: 2345,
123                ecu_id: [b'A', b'B', b'C', b'D'],
124            };
125            writer
126                .write_slice(
127                    header0.clone(),
128                    DltPacketSlice::from_slice(&packet0).unwrap(),
129                )
130                .unwrap();
131
132            // add a secondary packet
133            let packet1 = {
134                let mut packet = Vec::<u8>::new();
135                let mut header = DltHeader {
136                    is_big_endian: false,
137                    message_counter: 0,
138                    length: 0,
139                    ecu_id: None,
140                    session_id: None,
141                    timestamp: None,
142                    extended_header: None,
143                };
144                header.length = header.header_len() + 4;
145                header.write(&mut packet).unwrap();
146                packet.write_all(&[9, 0, 1, 2]).unwrap();
147                packet
148            };
149            let header1 = StorageHeader {
150                timestamp_seconds: 3456,
151                timestamp_microseconds: 4567,
152                ecu_id: [b'B', b'C', b'D', b'E'],
153            };
154            writer
155                .write_slice(
156                    header1.clone(),
157                    DltPacketSlice::from_slice(&packet1).unwrap(),
158                )
159                .unwrap();
160
161            // check contents
162            {
163                let mut expected = Vec::new();
164                expected.extend_from_slice(&header0.to_bytes());
165                expected.extend_from_slice(&packet0);
166                expected.extend_from_slice(&header1.to_bytes());
167                expected.extend_from_slice(&packet1);
168                assert_eq!(expected, buffer);
169            }
170        }
171
172        // check write error because of size error
173        {
174            let packet = {
175                let mut packet = Vec::<u8>::new();
176                let mut header = DltHeader {
177                    is_big_endian: true,
178                    message_counter: 0,
179                    length: 0,
180                    ecu_id: None,
181                    session_id: None,
182                    timestamp: None,
183                    extended_header: None,
184                };
185                header.length = header.header_len() + 4;
186                header.write(&mut packet).unwrap();
187                packet.write_all(&[1, 2, 3, 4]).unwrap();
188                packet
189            };
190            let header = StorageHeader {
191                timestamp_seconds: 1234,
192                timestamp_microseconds: 2345,
193                ecu_id: [b'A', b'B', b'C', b'D'],
194            };
195
196            // writer with not enough memory for the storage header
197            {
198                let mut buffer = [0u8; StorageHeader::BYTE_LEN - 1];
199                let mut cursor = std::io::Cursor::new(&mut buffer[..]);
200                let mut writer = DltStorageWriter::new(&mut cursor);
201                assert!(writer
202                    .write_slice(header.clone(), DltPacketSlice::from_slice(&packet).unwrap())
203                    .is_err());
204            }
205            // write with not enough memory for the packet
206            {
207                let mut buffer = [0u8; StorageHeader::BYTE_LEN + 1];
208                let mut cursor = std::io::Cursor::new(&mut buffer[..]);
209                let mut writer = DltStorageWriter::new(&mut cursor);
210                assert!(writer
211                    .write_slice(header, DltPacketSlice::from_slice(&packet).unwrap())
212                    .is_err());
213            }
214        }
215    }
216}