fxt/
init.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{trace_header, ParseResult, INIT_RECORD_TYPE};
6use nom::combinator::all_consuming;
7use nom::number::complete::le_u64;
8use nom::Parser;
9use std::time::Duration;
10
11#[derive(Clone, Copy, Debug, PartialEq)]
12pub(crate) struct Ticks(pub(crate) u64);
13
14impl Ticks {
15    pub(crate) fn parse(buf: &[u8]) -> ParseResult<'_, Self> {
16        nom::combinator::map(nom::number::complete::le_u64, Ticks).parse(buf)
17    }
18
19    pub(crate) fn scale(self, ticks_per_second: u64) -> i64 {
20        const NANOS_PER_SECOND: u128 = Duration::from_secs(1).as_nanos() as _;
21        ((self.0 as u128 * NANOS_PER_SECOND) / ticks_per_second as u128)
22            .try_into()
23            .expect("overflowing a signed monotonic timestamp would take ~292 years of uptime")
24    }
25}
26
27#[derive(Clone, Debug, PartialEq)]
28pub(super) struct InitRecord {
29    pub ticks_per_second: u64,
30}
31
32trace_header! {
33    InitHeader (INIT_RECORD_TYPE) {}
34}
35
36impl InitRecord {
37    pub(super) fn parse(buf: &[u8]) -> ParseResult<'_, Self> {
38        let (buf, header) = InitHeader::parse(buf)?;
39        let (rem, payload) = header.take_payload(buf)?;
40        let (empty, ticks_per_second) = all_consuming(le_u64).parse(payload)?;
41        assert!(empty.is_empty(), "all_consuming must not return any remaining buffer");
42        Ok((rem, Self { ticks_per_second }))
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::fxt_builder::FxtBuilder;
50    use crate::RawTraceRecord;
51
52    #[test]
53    fn basic_ticks_to_monotonic() {
54        assert_eq!(
55            Ticks(1024).scale(2_000_000_000),
56            512,
57            "2 billion ticks/sec is twice the rate of the monotonic clock, half as many nanos",
58        );
59
60        assert_eq!(
61            Ticks(1024).scale(500_000_000),
62            2048,
63            "500mm ticks/sec is half the rate of the monotonic clock, twice as many nanos",
64        );
65    }
66
67    #[test]
68    fn init_record() {
69        assert_parses_to_record!(
70            FxtBuilder::new(InitHeader::empty()).atom(2u64.to_le_bytes()).build(),
71            RawTraceRecord::Init(InitRecord { ticks_per_second: 2 }),
72        );
73    }
74}