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
18pub 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#[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#[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 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, preferred_display_base: Default::default(),
315 },
316 }
317 }
318
319 #[test]
320 fn rollover_tracking_u8() {
321 let t0 = u8::MAX - 5;
323
324 let t1 = 10_u8;
326
327 let mut instant = TrackingInstant::new(×tamp_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 let t0 = u16::MAX - 5;
338
339 let t1 = 10_u16;
341
342 let mut instant = TrackingInstant::new(×tamp_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 let t0 = u32::MAX - 5;
353
354 let t1 = 10_u32;
356
357 let mut instant = TrackingInstant::new(×tamp_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 let t0 = u64::MAX - 5;
368
369 let t1 = 10_u64;
371
372 let mut instant = TrackingInstant::new(×tamp_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(×tamp_ft(24)),
383 Err(UnsupportedTimestampFieldType {})
384 );
385 }
386}