barectf_parser/types/
mod.rs

1use crate::config::{PreferredDisplayBase, UnsignedIntegerFieldType};
2use derive_more::Display;
3use internment::Intern;
4use num_enum::{FromPrimitive, IntoPrimitive};
5use ordered_float::OrderedFloat;
6use serde::{Deserialize, Serialize};
7
8pub use event::Event;
9pub use packet::{Packet, PacketContext, PacketHeader};
10
11pub mod event;
12pub mod packet;
13
14pub type StreamId = u64;
15
16pub type EventId = u64;
17
18/// Timestamp in cycles
19pub type Timestamp = u64;
20
21pub type EventCount = u64;
22
23pub type SequenceNumber = u64;
24
25pub const CTF_MAGIC_NUMBER: u32 = 0xC1FC1FC1;
26
27#[derive(
28    Copy,
29    Clone,
30    Eq,
31    PartialEq,
32    Ord,
33    PartialOrd,
34    Hash,
35    Debug,
36    Display,
37    IntoPrimitive,
38    FromPrimitive,
39    Serialize,
40    Deserialize,
41)]
42#[repr(i32)]
43pub enum LogLevel {
44    #[display("EMERG")]
45    Emergency = 0,
46    #[display("ALERT")]
47    Alert = 1,
48    #[display("CRIT")]
49    Critical = 2,
50    #[display("ERR")]
51    Error = 3,
52    #[display("WARNING")]
53    Warning = 4,
54    #[display("NOTICE")]
55    Notice = 5,
56    #[display("INFO")]
57    Info = 6,
58    #[display("DEBUG_SYSTEM")]
59    DebugSystem = 7,
60    #[display("DEBUG_PROGRAM")]
61    DebugProgram = 8,
62    #[display("DEBUG_PROCESS")]
63    DebugProcess = 9,
64    #[display("DEBUG_MODULE")]
65    DebugModule = 10,
66    #[display("DEBUG_UNIT")]
67    DebugUnit = 11,
68    #[display("DEBUG_FUNCTION")]
69    DebugFunction = 12,
70    #[display("DEBUG_LINE")]
71    DebugLine = 13,
72    #[display("DEBUG")]
73    Debug = 14,
74    #[display("{_0}")]
75    #[num_enum(catch_all)]
76    Other(i32),
77}
78
79/// Stores the lower word of a [`TrackingInstant`] for
80/// keeping track of timestamp rollovers.
81#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
82enum CyclesTracker {
83    U8(u8),
84    U16(u16),
85    U32(u32),
86    U64(u64),
87}
88
89impl CyclesTracker {
90    fn size_bits(&self) -> usize {
91        match self {
92            Self::U8(_) => 8,
93            Self::U16(_) => 16,
94            Self::U32(_) => 32,
95            Self::U64(_) => 64,
96        }
97    }
98
99    fn reset(&mut self) {
100        match self {
101            Self::U8(v) => {
102                *v = 0;
103            }
104            Self::U16(v) => {
105                *v = 0;
106            }
107            Self::U32(v) => {
108                *v = 0;
109            }
110            Self::U64(v) => {
111                *v = 0;
112            }
113        }
114    }
115
116    fn set(&mut self, cycles: Timestamp) {
117        match self {
118            Self::U8(v) => {
119                *v = cycles as u8;
120            }
121            Self::U16(v) => *v = cycles as u16,
122            Self::U32(v) => *v = cycles as u32,
123            Self::U64(v) => {
124                *v = cycles;
125            }
126        }
127    }
128
129    fn as_cycles(&self) -> u64 {
130        match self {
131            Self::U8(v) => *v as u64,
132            Self::U16(v) => *v as u64,
133            Self::U32(v) => *v as u64,
134            Self::U64(v) => *v,
135        }
136    }
137
138    fn is_u64(&self) -> bool {
139        matches!(self, Self::U64(_))
140    }
141}
142
143#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, thiserror::Error)]
144#[error("Unsupported timestamp field time")]
145pub struct UnsupportedTimestampFieldType {}
146
147/// Instant, in cycles, that tracks rollovers.
148/// Supports 8, 16, and 32 bit timestamp field types.
149/// When the timestamp is a 64 bit value, then no rollover tracking is performed.
150#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
151pub struct TrackingInstant {
152    lower: CyclesTracker,
153    upper: u32,
154}
155
156impl TrackingInstant {
157    pub fn new(
158        field_type: &UnsignedIntegerFieldType,
159    ) -> Result<Self, UnsupportedTimestampFieldType> {
160        let lower = match field_type.field_type.size {
161            8 => CyclesTracker::U8(0),
162            16 => CyclesTracker::U16(0),
163            32 => CyclesTracker::U32(0),
164            64 => CyclesTracker::U64(0),
165            _ => return Err(UnsupportedTimestampFieldType {}),
166        };
167        Ok(Self { lower, upper: 0 })
168    }
169
170    pub fn reset(&mut self) {
171        self.lower.reset();
172        self.upper = 0;
173    }
174
175    pub fn reset_to(&mut self, cycles: Timestamp, upper: u32) {
176        self.lower.set(cycles);
177        self.upper = upper;
178    }
179
180    pub fn elapsed(&mut self, cycles: Timestamp) -> Timestamp {
181        if self.lower.is_u64() {
182            self.lower.set(cycles)
183        } else {
184            // Check for rollover on the lower
185            if cycles < self.lower.as_cycles() {
186                self.upper += 1;
187            }
188
189            self.lower.set(cycles);
190        }
191
192        self.as_timestamp()
193    }
194
195    pub fn as_timestamp(&self) -> Timestamp {
196        if self.lower.is_u64() {
197            self.lower.as_cycles()
198        } else {
199            (u64::from(self.upper) << self.lower.size_bits()) | self.lower.as_cycles()
200        }
201    }
202}
203
204#[derive(Clone, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
205pub enum PrimitiveFieldValue {
206    UnsignedInteger(u64, PreferredDisplayBase),
207    SignedInteger(i64, PreferredDisplayBase),
208    String(String),
209    F32(OrderedFloat<f32>),
210    F64(OrderedFloat<f64>),
211    Enumeration(i64, PreferredDisplayBase, Option<Intern<String>>),
212}
213
214#[derive(Clone, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
215pub enum FieldValue {
216    Primitive(PrimitiveFieldValue),
217    Array(Vec<PrimitiveFieldValue>),
218}
219
220impl From<PrimitiveFieldValue> for FieldValue {
221    fn from(v: PrimitiveFieldValue) -> Self {
222        Self::Primitive(v)
223    }
224}
225
226impl From<Vec<PrimitiveFieldValue>> for FieldValue {
227    fn from(v: Vec<PrimitiveFieldValue>) -> Self {
228        Self::Array(v)
229    }
230}
231
232impl From<u8> for PrimitiveFieldValue {
233    fn from(v: u8) -> Self {
234        PrimitiveFieldValue::UnsignedInteger(v.into(), PreferredDisplayBase::default())
235    }
236}
237
238impl From<u16> for PrimitiveFieldValue {
239    fn from(v: u16) -> Self {
240        PrimitiveFieldValue::UnsignedInteger(v.into(), PreferredDisplayBase::default())
241    }
242}
243
244impl From<u32> for PrimitiveFieldValue {
245    fn from(v: u32) -> Self {
246        PrimitiveFieldValue::UnsignedInteger(v.into(), PreferredDisplayBase::default())
247    }
248}
249
250impl From<u64> for PrimitiveFieldValue {
251    fn from(v: u64) -> Self {
252        PrimitiveFieldValue::UnsignedInteger(v, PreferredDisplayBase::default())
253    }
254}
255
256impl From<i8> for PrimitiveFieldValue {
257    fn from(v: i8) -> Self {
258        PrimitiveFieldValue::SignedInteger(v.into(), PreferredDisplayBase::default())
259    }
260}
261
262impl From<i16> for PrimitiveFieldValue {
263    fn from(v: i16) -> Self {
264        PrimitiveFieldValue::SignedInteger(v.into(), PreferredDisplayBase::default())
265    }
266}
267
268impl From<i32> for PrimitiveFieldValue {
269    fn from(v: i32) -> Self {
270        PrimitiveFieldValue::SignedInteger(v.into(), PreferredDisplayBase::default())
271    }
272}
273
274impl From<i64> for PrimitiveFieldValue {
275    fn from(v: i64) -> Self {
276        PrimitiveFieldValue::SignedInteger(v, PreferredDisplayBase::default())
277    }
278}
279
280impl From<String> for PrimitiveFieldValue {
281    fn from(v: String) -> Self {
282        PrimitiveFieldValue::String(v)
283    }
284}
285
286impl From<&str> for PrimitiveFieldValue {
287    fn from(v: &str) -> Self {
288        PrimitiveFieldValue::String(v.to_owned())
289    }
290}
291
292impl From<f32> for PrimitiveFieldValue {
293    fn from(v: f32) -> Self {
294        PrimitiveFieldValue::F32(OrderedFloat(v))
295    }
296}
297
298impl From<f64> for PrimitiveFieldValue {
299    fn from(v: f64) -> Self {
300        PrimitiveFieldValue::F64(OrderedFloat(v))
301    }
302}
303
304#[cfg(test)]
305mod test {
306    use super::*;
307    use crate::config::IntegerFieldType;
308
309    fn timestamp_ft(size_bits: usize) -> UnsignedIntegerFieldType {
310        UnsignedIntegerFieldType {
311            field_type: IntegerFieldType {
312                size: size_bits,
313                alignment: 8, // byte-packed
314                preferred_display_base: Default::default(),
315            },
316        }
317    }
318
319    #[test]
320    fn rollover_tracking_u8() {
321        // 5 ticks before rollover
322        let t0 = u8::MAX - 5;
323
324        // 10 ticks after rollover
325        let t1 = 10_u8;
326
327        let mut instant = TrackingInstant::new(&timestamp_ft(8)).unwrap();
328        assert_eq!(instant.elapsed(t0.into()), u64::from(t0));
329
330        let t2 = instant.elapsed(t1.into());
331        assert_eq!(u64::from(t0) + 16, t2);
332    }
333
334    #[test]
335    fn rollover_tracking_u16() {
336        // 5 ticks before rollover
337        let t0 = u16::MAX - 5;
338
339        // 10 ticks after rollover
340        let t1 = 10_u16;
341
342        let mut instant = TrackingInstant::new(&timestamp_ft(16)).unwrap();
343        assert_eq!(instant.elapsed(t0.into()), u64::from(t0));
344
345        let t2 = instant.elapsed(t1.into());
346        assert_eq!(u64::from(t0) + 16, t2);
347    }
348
349    #[test]
350    fn rollover_tracking_u32() {
351        // 5 ticks before rollover
352        let t0 = u32::MAX - 5;
353
354        // 10 ticks after rollover
355        let t1 = 10_u32;
356
357        let mut instant = TrackingInstant::new(&timestamp_ft(32)).unwrap();
358        assert_eq!(instant.elapsed(t0.into()), u64::from(t0));
359
360        let t2 = instant.elapsed(t1.into());
361        assert_eq!(u64::from(t0) + 16, t2);
362    }
363
364    #[test]
365    fn no_rollover_tracking_u64() {
366        // 5 ticks before rollover
367        let t0 = u64::MAX - 5;
368
369        // 10 ticks after rollover
370        let t1 = 10_u64;
371
372        let mut instant = TrackingInstant::new(&timestamp_ft(64)).unwrap();
373        assert_eq!(instant.elapsed(t0), t0);
374
375        let t2 = instant.elapsed(t1);
376        assert_eq!(t1, t2);
377    }
378
379    #[test]
380    fn unsupported_timestamp_field_type() {
381        assert_eq!(
382            TrackingInstant::new(&timestamp_ft(24)),
383            Err(UnsupportedTimestampFieldType {})
384        );
385    }
386}