flow_fcs/datatype.rs
1use anyhow::{Result, anyhow};
2use serde::{Deserialize, Serialize};
3use strum_macros::Display;
4
5/// The data type of the FCS file, which determines how event data is stored
6///
7/// FCS files can store data in different numeric formats. The most common is
8/// single-precision floating point (F), which is also the default.
9#[derive(Default, Display, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
10pub enum FcsDataType {
11 /// Unsigned binary integer
12 I,
13 /// Single-precision floating point (f32)
14 #[default]
15 F,
16 /// Double-precision floating point (f64)
17 D,
18 /// ASCII-encoded string (not supported)
19 A,
20}
21impl FcsDataType {
22 /// Matches the string pattern and returns the corresponding data type
23 /// # Errors
24 /// Will return `Err` if `data_type` is not a valid data type (ASCII-encoded strings are not supported, but binary integers, single-precision floating point, and double-precision floating point are supported)
25 pub fn from_keyword_str(data_type: &str) -> Result<Self> {
26 match data_type {
27 "I" => Ok(Self::I),
28 "F" => Ok(Self::F),
29 "D" => Ok(Self::D),
30 "A" => Err(anyhow!("ASCII-encoded string data type not supported")),
31 _ => Err(anyhow!("Invalid data type")),
32 }
33 }
34
35 /// Convert to the keyword string representation of the data type
36 /// # Returns
37 /// The single letter as expected by FCS file format (I, F, D, A)
38 pub fn to_keyword_str(&self) -> &str {
39 match self {
40 Self::I => "I",
41 Self::F => "F",
42 Self::D => "D",
43 Self::A => "A",
44 }
45 }
46
47 /// Returns the number of bytes for the data type based on the number of bits
48 ///
49 /// This is used in conjunction with `$PnB` to determine the actual bytes per parameter.
50 /// For `I` (integer) type, the actual bytes depend on `$PnB` (e.g., 16 bits = 2 bytes, 32 bits = 4 bytes).
51 /// For `F` (float32), always 4 bytes.
52 /// For `D` (float64), always 8 bytes.
53 ///
54 /// # Arguments
55 /// * `bits` - Number of bits from `$PnB` keyword
56 ///
57 /// # Returns
58 /// Number of bytes for this data type with the given bit width
59 #[must_use]
60 pub fn get_bytes_for_bits(&self, bits: usize) -> usize {
61 match self {
62 Self::I => (bits + 7) / 8, // Convert bits to bytes, rounding up
63 Self::F => 4,
64 Self::D => 8,
65 Self::A => 0,
66 }
67 }
68}