1 //! All binary files generated by measureme have a simple file header that
2 //! consists of a 4 byte file magic string and a 4 byte little-endian version
5 use crate::serialization
::SerializationSink
;
6 use byteorder
::{ByteOrder, LittleEndian}
;
9 pub const CURRENT_FILE_FORMAT_VERSION
: u32 = 0;
10 pub const FILE_MAGIC_EVENT_STREAM
: &[u8; 4] = b
"MMES";
11 pub const FILE_MAGIC_STRINGTABLE_DATA
: &[u8; 4] = b
"MMSD";
12 pub const FILE_MAGIC_STRINGTABLE_INDEX
: &[u8; 4] = b
"MMSI";
14 /// The size of the file header in bytes. Note that functions in this module
15 /// rely on this size to be `8`.
16 pub const FILE_HEADER_SIZE
: usize = 8;
18 pub fn write_file_header
<S
: SerializationSink
>(s
: &S
, file_magic
: &[u8; 4]) {
19 // The implementation here relies on FILE_HEADER_SIZE to have the value 8.
20 // Let's make sure this assumption cannot be violated without being noticed.
21 assert_eq
!(FILE_HEADER_SIZE
, 8);
23 s
.write_atomic(FILE_HEADER_SIZE
, |bytes
| {
24 bytes
[0..4].copy_from_slice(file_magic
);
25 LittleEndian
::write_u32(&mut bytes
[4..8], CURRENT_FILE_FORMAT_VERSION
);
29 pub fn read_file_header(bytes
: &[u8], expected_magic
: &[u8; 4]) -> Result
<u32, Box
<dyn Error
>> {
30 // The implementation here relies on FILE_HEADER_SIZE to have the value 8.
31 // Let's make sure this assumption cannot be violated without being noticed.
32 assert_eq
!(FILE_HEADER_SIZE
, 8);
34 let actual_magic
= &bytes
[0..4];
36 if actual_magic
!= expected_magic
{
37 // FIXME: The error message should mention the file path in order to be
40 "Unexpected file magic `{:?}`. Expected `{:?}`",
41 actual_magic
, expected_magic
,
44 return Err(From
::from(msg
));
47 Ok(LittleEndian
::read_u32(&bytes
[4..8]))
50 pub fn strip_file_header(data
: &[u8]) -> &[u8] {
51 &data
[FILE_HEADER_SIZE
..]
57 use crate::serialization
::test
::TestSink
;
61 let data_sink
= TestSink
::new();
63 write_file_header(&data_sink
, FILE_MAGIC_EVENT_STREAM
);
65 let data
= data_sink
.into_bytes();
68 read_file_header(&data
, FILE_MAGIC_EVENT_STREAM
).unwrap(),
69 CURRENT_FILE_FORMAT_VERSION
75 let data_sink
= TestSink
::new();
76 write_file_header(&data_sink
, FILE_MAGIC_STRINGTABLE_DATA
);
77 let mut data
= data_sink
.into_bytes();
79 // Invalidate the filemagic
81 assert
!(read_file_header(&data
, FILE_MAGIC_STRINGTABLE_DATA
).is_err());
86 let data_sink
= TestSink
::new();
88 write_file_header(&data_sink
, FILE_MAGIC_STRINGTABLE_INDEX
);
90 let mut data
= data_sink
.into_bytes();
98 read_file_header(&data
, FILE_MAGIC_STRINGTABLE_INDEX
).unwrap(),