tracing_tape/
intro.rs

1use zerocopy::{little_endian, AsBytes, FromBytes, FromZeroes};
2
3/// The magic sequence identifying the file type.
4pub type Magic = [u8; 8];
5
6/// The magic sequence identifying the tapfile format.
7pub const MAGIC: Magic = *b"TAPEFILE";
8
9/// The version of the tapfile format.
10#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
11#[repr(C)]
12pub struct Version {
13    pub major: u8,
14    pub minor: u8,
15}
16
17pub const VERSION: Version = Version { major: 0, minor: 1 };
18
19/// The size of a chapter in the tapfile.
20///
21/// This represents the number of bytes in a chapter, i.e., the chunk size. This must be a power of
22/// two, thus it is stored as a `u8` representing the exponent of the power of two.
23#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
24#[repr(transparent)]
25pub struct ChapterSize(pub u8);
26
27impl Into<usize> for ChapterSize {
28    fn into(self) -> usize {
29        1 << self.0 as usize
30    }
31}
32
33/// The introductory header of the tapfile.
34#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
35#[repr(C)]
36pub struct Intro {
37    pub magic: [u8; 8],
38    pub version: Version,
39    pub chapter_size: ChapterSize,
40    _padding: [u8; 5],
41    pub timestamp_base: little_endian::I128,
42}
43
44impl Intro {
45    pub fn new(chapter_size: u8, timestamp_base: i128) -> Self {
46        Self {
47            magic: MAGIC,
48            version: VERSION,
49            chapter_size: ChapterSize(chapter_size),
50            _padding: [0; 5],
51            timestamp_base: timestamp_base.into(),
52        }
53    }
54}
55
56#[test]
57fn test_intro_size() {
58    assert_eq!(std::mem::size_of::<Intro>(), 32);
59}