barectf_parser/
config.rs

1use byteordered::Endianness;
2use serde::{Deserialize, Deserializer, Serialize};
3use serde_yaml::Value;
4use std::collections::BTreeMap;
5use uuid::Uuid;
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
8#[serde(rename_all = "kebab-case")]
9pub enum NativeByteOrder {
10    #[serde(alias = "little")]
11    #[serde(alias = "le")]
12    LittleEndian,
13    #[serde(alias = "big")]
14    #[serde(alias = "be")]
15    BigEndian,
16}
17
18impl From<NativeByteOrder> for Endianness {
19    fn from(value: NativeByteOrder) -> Self {
20        match value {
21            NativeByteOrder::LittleEndian => Endianness::Little,
22            NativeByteOrder::BigEndian => Endianness::Big,
23        }
24    }
25}
26
27#[derive(
28    Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Deserialize, Serialize,
29)]
30#[serde(rename_all = "kebab-case")]
31pub enum PreferredDisplayBase {
32    #[serde(alias = "bin")]
33    Binary,
34    #[serde(alias = "oct")]
35    Octal,
36    #[default]
37    #[serde(alias = "dec")]
38    Decimal,
39    #[serde(alias = "hex")]
40    Hexadecimal,
41}
42
43/// Integer field type objects are the types of integer data fields, found in data streams.
44#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
45#[serde(rename_all = "kebab-case")]
46pub struct IntegerFieldType {
47    /// Size of this field type’s instances (bits).
48    pub size: usize,
49    /// Alignment of the first bit of this field type’s instances within a CTF packet (bits).
50    #[serde(default = "default_alignment_bits")]
51    pub alignment: usize,
52    /// The preferred base (radix) to use when displaying this field type’s instances.
53    #[serde(default)]
54    pub preferred_display_base: PreferredDisplayBase,
55}
56
57impl FieldType for IntegerFieldType {
58    fn size(&self) -> usize {
59        self.size
60    }
61
62    fn alignment(&self) -> usize {
63        self.alignment
64    }
65
66    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
67        Some(self.preferred_display_base)
68    }
69}
70
71/// Integer field type objects are the types of integer data fields, found in data streams.
72#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
73#[serde(rename_all = "kebab-case")]
74#[serde(tag = "class", rename = "unsigned-integer")]
75pub struct UnsignedIntegerFieldType {
76    #[serde(flatten)]
77    pub field_type: IntegerFieldType,
78}
79
80/// Integer field type objects are the types of integer data fields, found in data streams.
81#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
82#[serde(rename_all = "kebab-case")]
83#[serde(tag = "class", rename = "signed-integer")]
84pub struct SignedIntegerFieldType {
85    #[serde(flatten)]
86    pub field_type: IntegerFieldType,
87}
88
89/// A real field type object is the type of floating point number data fields, found in data streams.
90#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
91#[serde(rename_all = "kebab-case")]
92pub struct RealFieldType {
93    /// Size of this field type’s instances (bits).
94    pub size: usize,
95    /// Alignment of the first bit of this field type’s instances within a CTF packet (bits).
96    #[serde(default = "default_alignment_bits")]
97    pub alignment: usize,
98}
99
100impl FieldType for RealFieldType {
101    fn size(&self) -> usize {
102        self.size
103    }
104
105    fn alignment(&self) -> usize {
106        self.alignment
107    }
108
109    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
110        None
111    }
112}
113
114/// Mapping sequence type of enumeration field types.
115#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
116#[serde(rename_all = "kebab-case")]
117#[serde(untagged)]
118pub enum EnumerationFieldTypeMappingSequence {
119    InclusiveRange(i64, i64),
120    Value(i64),
121}
122
123impl EnumerationFieldTypeMappingSequence {
124    /// Returns true if the mapping sequence element contains the value
125    pub fn contains(&self, value: i64) -> bool {
126        match self {
127            Self::InclusiveRange(min, max) => (value >= *min) && (value <= *max),
128            Self::Value(v) => *v == value,
129        }
130    }
131}
132
133/// Enumeration field type objects are the types of enumeration data fields, found in data streams.
134#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
135#[serde(rename_all = "kebab-case")]
136pub struct EnumerationFieldType {
137    /// Size of this field type’s instances (bits).
138    pub size: usize,
139    /// Alignment of the first bit of this field type’s instances within a CTF packet (bits).
140    #[serde(default = "default_alignment_bits")]
141    pub alignment: usize,
142    /// The preferred base (radix) to use when displaying this field type’s instances.
143    #[serde(default)]
144    pub preferred_display_base: PreferredDisplayBase,
145    /// Mappings of this enumeration field type.
146    pub mappings: BTreeMap<String, Vec<EnumerationFieldTypeMappingSequence>>,
147}
148
149impl FieldType for EnumerationFieldType {
150    fn size(&self) -> usize {
151        self.size
152    }
153
154    fn alignment(&self) -> usize {
155        self.alignment
156    }
157
158    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
159        Some(self.preferred_display_base)
160    }
161}
162
163/// Primitive field types supported by [`StaticArrayFieldType`] and [`DynamicArrayFieldType`].
164#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
165#[serde(rename_all = "kebab-case")]
166#[serde(tag = "class")]
167pub enum PrimitiveFieldType {
168    UnsignedInteger(IntegerFieldType),
169    SignedInteger(IntegerFieldType),
170    String,
171    Real(RealFieldType),
172    UnsignedEnumeration(EnumerationFieldType),
173    SignedEnumeration(EnumerationFieldType),
174}
175
176impl FieldType for PrimitiveFieldType {
177    fn size(&self) -> usize {
178        match self {
179            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.size,
180            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.size,
181            Self::Real(t) => t.size,
182            Self::String => 8,
183        }
184    }
185
186    fn alignment(&self) -> usize {
187        match self {
188            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.alignment,
189            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.alignment,
190            Self::Real(t) => t.alignment,
191            Self::String => 8,
192        }
193    }
194
195    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
196        Some(match self {
197            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.preferred_display_base,
198            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.preferred_display_base,
199            Self::String | Self::Real(_) => return None,
200        })
201    }
202}
203
204/// A static array field type object is the type of static array data fields, found in data streams.
205#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
206#[serde(rename_all = "kebab-case")]
207pub struct StaticArrayFieldType {
208    /// Number of elements in this field type’s instances.
209    pub length: usize,
210    /// Type of each element (data fields) in this field type’s instances.
211    pub element_field_type: PrimitiveFieldType,
212}
213
214impl FieldType for StaticArrayFieldType {
215    fn size(&self) -> usize {
216        self.element_field_type.size()
217    }
218
219    fn alignment(&self) -> usize {
220        self.element_field_type.alignment()
221    }
222
223    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
224        self.element_field_type.preferred_display_base()
225    }
226}
227
228/// A dynamic array field type object is the type of dynamic (variable-length) array data fields, found in data streams.
229#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
230#[serde(rename_all = "kebab-case")]
231pub struct DynamicArrayFieldType {
232    /// Type of each element (data fields) in this field type’s instances.
233    pub element_field_type: PrimitiveFieldType,
234}
235
236impl FieldType for DynamicArrayFieldType {
237    fn size(&self) -> usize {
238        self.element_field_type.size()
239    }
240
241    fn alignment(&self) -> usize {
242        self.element_field_type.alignment()
243    }
244
245    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
246        self.element_field_type.preferred_display_base()
247    }
248}
249
250/// Field types supported by [`StructureFieldTypeMember`]
251#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
252#[serde(rename_all = "kebab-case")]
253#[serde(tag = "class")]
254pub enum StructureMemberFieldType {
255    UnsignedInteger(IntegerFieldType),
256    SignedInteger(IntegerFieldType),
257    String,
258    Real(RealFieldType),
259    UnsignedEnumeration(EnumerationFieldType),
260    SignedEnumeration(EnumerationFieldType),
261    StaticArray(StaticArrayFieldType),
262    DynamicArray(DynamicArrayFieldType),
263}
264
265impl FieldType for StructureMemberFieldType {
266    fn size(&self) -> usize {
267        match self {
268            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.size,
269            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.size,
270            Self::Real(t) => t.size,
271            Self::String => 8, // Min size bits
272            Self::StaticArray(t) => t.size(),
273            Self::DynamicArray(t) => t.size(),
274        }
275    }
276
277    fn alignment(&self) -> usize {
278        match self {
279            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.alignment,
280            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.alignment,
281            Self::Real(t) => t.alignment,
282            Self::String => 8,
283            Self::StaticArray(t) => t.alignment(),
284            Self::DynamicArray(t) => t.alignment(),
285        }
286    }
287
288    fn preferred_display_base(&self) -> Option<PreferredDisplayBase> {
289        Some(match self {
290            Self::UnsignedInteger(t) | Self::SignedInteger(t) => t.preferred_display_base,
291            Self::UnsignedEnumeration(t) | Self::SignedEnumeration(t) => t.preferred_display_base,
292            Self::StaticArray(t) => return t.preferred_display_base(),
293            Self::DynamicArray(t) => return t.preferred_display_base(),
294            Self::String | Self::Real(_) => return None,
295        })
296    }
297}
298
299/// A member within a structure field type object.
300#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
301#[serde(rename_all = "kebab-case")]
302pub struct StructureFieldTypeMember {
303    /// Member’s field type.
304    pub field_type: StructureMemberFieldType,
305}
306
307/// A structure field type object is the type of structure data fields, found in data streams.
308#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
309#[serde(rename_all = "kebab-case")]
310#[serde(tag = "class", rename = "structure")]
311pub struct StructureFieldType {
312    /// Minimum alignment of the first bit of this field type’s instances within a CTF packet (bits).
313    #[serde(default = "default_struct_min_alignment")]
314    pub minimum_alignment: usize,
315    /// Members of this structure field type.
316    pub members: Vec<BTreeMap<String, StructureFieldTypeMember>>,
317}
318
319impl StructureFieldType {
320    /// Return the largest alignment of the event payload members (bits)
321    pub(crate) fn alignment(&self) -> usize {
322        self.members
323            .iter()
324            .flat_map(|m| m.values())
325            .map(|ftm| ftm.field_type.alignment())
326            .max()
327            .unwrap_or_else(default_alignment_bits)
328    }
329}
330
331/// Field type for `$features` fields that can either be set to `false` or
332/// an [`UnsignedIntegerFieldType`]
333#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
334#[serde(rename_all = "kebab-case")]
335#[serde(untagged)]
336pub enum FeaturesUnsignedIntegerFieldType {
337    #[serde(deserialize_with = "de_false")]
338    False(bool),
339    UnsignedInteger(UnsignedIntegerFieldType),
340}
341
342impl FeaturesUnsignedIntegerFieldType {
343    /// Return the alignment of the field type (bits)
344    pub(crate) fn alignment(&self) -> usize {
345        match self {
346            Self::False(_) => 0,
347            Self::UnsignedInteger(ft) => ft.field_type.alignment,
348        }
349    }
350
351    pub(crate) fn as_ft(&self) -> Option<&UnsignedIntegerFieldType> {
352        match self {
353            FeaturesUnsignedIntegerFieldType::False(_) => None,
354            FeaturesUnsignedIntegerFieldType::UnsignedInteger(ft) => Some(ft),
355        }
356    }
357}
358
359/// Offset information of a clock type’s instances.
360#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
361#[serde(rename_all = "kebab-case")]
362pub struct ClockTypeOffset {
363    /// Offset in seconds.
364    pub seconds: i64,
365    /// Offset in cycles.
366    pub cycles: u64,
367}
368
369/// A clock type object is the type of data stream clocks.
370#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
371#[serde(rename_all = "kebab-case")]
372pub struct ClockType {
373    /// Frequency of instances (Hz).
374    pub frequency: u64,
375    /// Offset of instances.
376    pub offset: Option<ClockTypeOffset>,
377    /// True if the origin of instances is the Unix epoch.
378    pub origin_is_unix_epoch: bool,
379    /// Precision of instances (cycles).
380    pub precision: u64,
381    /// Clock type’s UUID.
382    pub uuid: Option<Uuid>,
383    /// Clock type’s description.
384    pub description: Option<String>,
385    /// Return C type of the clock source function for this clock type.
386    #[serde(alias = "$c-type")]
387    pub c_type: String,
388}
389
390/// An event record type object is the type of an event record.
391#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
392#[serde(rename_all = "kebab-case")]
393pub struct EventRecordType {
394    /// Numeric log level of this event record type’s instances.
395    pub log_level: Option<i32>,
396    /// Specific context field type of this event record type.
397    pub specific_context_field_type: Option<StructureFieldType>,
398    /// Payload field type of this event record type.
399    pub payload_field_type: Option<StructureFieldType>,
400}
401
402/// The packet features of a data stream type object.
403#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
404#[serde(rename_all = "kebab-case")]
405pub struct DataStreamTypePacketFeatures {
406    /// Type of packet context’s total size field.
407    pub total_size_field_type: UnsignedIntegerFieldType,
408    /// Type of packet context’s content size field.
409    pub content_size_field_type: UnsignedIntegerFieldType,
410    /// Type of packet context’s beginning timestamp field.
411    pub beginning_timestamp_field_type: FeaturesUnsignedIntegerFieldType,
412    /// Type of packet context’s end timestamp field.
413    pub end_timestamp_field_type: FeaturesUnsignedIntegerFieldType,
414    /// Type of packet context’s discarded event record counter snapshot field.
415    pub discarded_event_records_counter_snapshot_field_type: FeaturesUnsignedIntegerFieldType,
416    /// Type of packet context’s sequence number field.
417    pub sequence_number_field_type: FeaturesUnsignedIntegerFieldType,
418}
419
420impl DataStreamTypePacketFeatures {
421    /// Return the largest alignment of the CTF packet context (bits)
422    pub(crate) fn alignment(&self) -> usize {
423        let aligns = [
424            self.total_size_field_type.field_type.alignment,
425            self.content_size_field_type.field_type.alignment,
426            self.beginning_timestamp_field_type.alignment(),
427            self.end_timestamp_field_type.alignment(),
428            self.discarded_event_records_counter_snapshot_field_type
429                .alignment(),
430            self.sequence_number_field_type.alignment(),
431        ];
432        *aligns.iter().max().unwrap() // SAFETY: always non-empty
433    }
434}
435
436/// The event records features of a data stream type object.
437#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
438#[serde(rename_all = "kebab-case")]
439pub struct DataStreamTypeEventRecordFeatures {
440    /// Type of event header’s event record type ID field.
441    pub type_id_field_type: UnsignedIntegerFieldType,
442    /// Type of event header’s timestamp field.
443    pub timestamp_field_type: UnsignedIntegerFieldType,
444}
445
446impl DataStreamTypeEventRecordFeatures {
447    /// Return the largest alignment of the CTF event header (bits)
448    pub(crate) fn alignment(&self) -> usize {
449        let aligns = [
450            self.type_id_field_type.field_type.alignment,
451            self.timestamp_field_type.field_type.alignment,
452        ];
453        *aligns.iter().max().unwrap() // SAFETY: always non-empty
454    }
455}
456
457/// The features of a data stream type object.
458#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
459#[serde(rename_all = "kebab-case")]
460pub struct DataStreamTypeFeatures {
461    /// Features related to CTF packets.
462    pub packet: DataStreamTypePacketFeatures,
463    /// Features related to CTF event records.
464    pub event_record: DataStreamTypeEventRecordFeatures,
465}
466
467/// Extra, user-defined members to be appended to a packet context structure field type.
468#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Deserialize)]
469#[serde(rename_all = "kebab-case")]
470pub struct PacketContextExtraMembers(pub Vec<BTreeMap<String, StructureFieldTypeMember>>);
471
472impl PacketContextExtraMembers {
473    /// Return the largest alignment of the event payload members (bits)
474    pub(crate) fn alignment(&self) -> usize {
475        self.0
476            .iter()
477            .flat_map(|m| m.values())
478            .map(|ftm| ftm.field_type.alignment())
479            .max()
480            .unwrap_or_else(default_alignment_bits)
481    }
482}
483
484/// A data stream type object is the type of a data stream.
485/// A data stream type describes everything a CTF consumer needs to decode its instances (data streams).
486#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
487#[serde(rename_all = "kebab-case")]
488pub struct DataStreamType {
489    /// If this property is true, then this data stream type is its trace type's default data stream type.
490    #[serde(alias = "$is-default")]
491    pub is_default: bool,
492    /// Name of the clock type which describes the default clock of this data stream type’s instances.
493    #[serde(alias = "$default-clock-type-name")]
494    pub default_clock_type_name: Option<String>,
495    /// Features of this data stream type’s instances.
496    #[serde(alias = "$features")]
497    pub features: DataStreamTypeFeatures,
498    /// Extra, user-defined members to be appended to this data stream type’s packet context structure field type.
499    #[serde(default)]
500    pub packet_context_field_type_extra_members: PacketContextExtraMembers,
501    /// Event record common context field type of this data stream type.
502    pub event_record_common_context_field_type: Option<StructureFieldType>,
503    /// Event record types of this data stream type.
504    pub event_record_types: BTreeMap<String, EventRecordType>,
505}
506
507/// The features of a trace type object.
508/// As of barectf 3.1, each feature controls whether or not some information will
509/// be part of the header of each CTF packet which the generated tracer produces.
510#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
511#[serde(rename_all = "kebab-case")]
512pub struct TraceTypeFeatures {
513    /// Type of packet header’s magic number field.
514    pub magic_field_type: FeaturesUnsignedIntegerFieldType,
515    /// Type of packet header’s trace type UUID field.
516    pub uuid_field_type: bool,
517    /// Type of packet header’s data stream type ID field.
518    pub data_stream_type_id_field_type: UnsignedIntegerFieldType,
519}
520
521impl TraceTypeFeatures {
522    /// Return the largest alignment of the CTF packet header (bits)
523    pub(crate) fn alignment(&self) -> usize {
524        let aligns = [
525            self.magic_field_type.alignment(),
526            // uuid is always byte-packed
527            self.uuid_field_type
528                .then(default_alignment_bits)
529                .unwrap_or(0),
530            self.data_stream_type_id_field_type.field_type.alignment,
531        ];
532        *aligns.iter().max().unwrap() // SAFETY: always non-empty
533    }
534}
535
536/// A trace type object is the type of a trace object.
537/// A trace type describes everything a CTF consumer needs to decode all the trace’s data streams.
538/// A trace type object is only found as the type property of a trace object.
539#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize)]
540#[serde(rename_all = "kebab-case")]
541pub struct TraceType {
542    /// Native byte order of the system which produces this trace type’s instance’s data streams.
543    pub native_byte_order: NativeByteOrder,
544    /// UUID of this trace type.
545    pub uuid: Option<Uuid>,
546    /// Features of this trace type’s instance (trace).
547    #[serde(alias = "$features")]
548    pub features: TraceTypeFeatures,
549    /// Clock type store for this trace type.
550    pub clock_types: BTreeMap<String, ClockType>,
551    /// Data stream types of this trace type.
552    pub data_stream_types: BTreeMap<String, DataStreamType>,
553}
554
555/// A trace object represents a CTF trace.
556#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Debug, Deserialize)]
557#[serde(rename_all = "kebab-case")]
558pub struct Trace {
559    /// This trace’s environment variables.
560    pub environment: BTreeMap<String, Value>,
561    /// Type of this trace (metadata part).
562    #[serde(alias = "type")]
563    pub typ: TraceType,
564}
565
566/// The code generation options of a configuration object.
567#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Debug, Deserialize)]
568#[serde(rename_all = "kebab-case")]
569pub struct CodeGenerationOptions {
570    /// Prefix of any C file which barectf generates.
571    pub file_name: String,
572    /// Prefix of any public C identifier which barectf generates.
573    pub identifier: String,
574}
575
576impl Default for CodeGenerationOptions {
577    fn default() -> Self {
578        Self {
579            file_name: "barectf".to_owned(),
580            identifier: "barectf_".to_owned(),
581        }
582    }
583}
584
585/// The C header generation options of a configuration object.
586#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Debug, Default, Deserialize)]
587#[serde(rename_all = "kebab-case")]
588pub struct HeaderGenerationOptions {
589    /// If this property is true, then barectf generates a public C
590    /// preprocessor definition named `_BARECTF_IDENTIFIER_PREFIX`
591    /// which is set to the configuration’s identifier prefix.
592    pub identifier_prefix_definition: bool,
593    /// If this property is true, then barectf generates a public C
594    /// preprocessor definition named `_BARECTF_DEFAULT_DATA_STREAM_TYPE_NAME`
595    /// which is set to the name of the trace type’s default data stream type.
596    pub default_data_stream_type_name_definition: bool,
597}
598
599/// The options of a configuration object.
600#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Debug, Default, Deserialize)]
601#[serde(rename_all = "kebab-case")]
602pub struct Options {
603    /// Code generation options.
604    pub code_generation: CodeGenerationOptions,
605    /// C header generation options.
606    pub header: HeaderGenerationOptions,
607}
608
609/// The barectf configuration object.
610///
611/// This can be constructed from the effective configuration yaml file.
612/// See <https://barectf.org/docs/barectf/3.1/cli/usage.html#show-effective-configuration-command>
613/// for more information on generating the configuration file.
614#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Debug, Deserialize)]
615#[serde(rename_all = "kebab-case")]
616pub struct Config {
617    /// Configuration options.
618    #[serde(default)]
619    pub options: Options,
620    /// Configuration’s trace.
621    pub trace: Trace,
622}
623
624pub(crate) trait FieldType {
625    /// Return the size of this field type’s instances (bits).
626    fn size(&self) -> usize;
627
628    /// Return the alignment of the field type (bits)
629    fn alignment(&self) -> usize;
630
631    /// Return the preferred base (radix) to use when displaying this field type’s instances.
632    fn preferred_display_base(&self) -> Option<PreferredDisplayBase>;
633}
634
635/// Alignment of the first bit of a field type’s instances within a CTF packet (bits).
636/// NOTE: 8 if the size property is a multiple of 8, or 1 otherwise.
637/// But we don't support bit-packed types, this is always 8
638const fn default_alignment_bits() -> usize {
639    8
640}
641
642/// Minimum alignment of the first bit of this field type’s instances within a CTF packet (bits).
643const fn default_struct_min_alignment() -> usize {
644    1
645}
646
647fn de_false<'de, D>(deserializer: D) -> Result<bool, D::Error>
648where
649    D: Deserializer<'de>,
650{
651    if bool::deserialize(deserializer)? {
652        Err(serde::de::Error::invalid_value(
653            serde::de::Unexpected::Bool(true),
654            &"the `false` boolean",
655        ))
656    } else {
657        Ok(false)
658    }
659}