knuckles_parse/records/
mtrixn.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4#[cfg(feature = "python")]
5use pyo3::prelude::*;
6
7#[cfg(feature = "python")]
8use knuckles_macro::pydefault;
9
10#[derive(Debug, Clone)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(feature = "python", pyclass)]
13#[cfg_attr(feature = "python", pydefault)]
14pub enum MtrixN {
15    Mtrix1(MtrixnRecord),
16    Mtrix2(MtrixnRecord),
17    Mtrix3(MtrixnRecord),
18}
19
20impl MtrixN {
21    pub fn new(str: &str) -> Self {
22        let record = MtrixnRecord::from(str);
23        match record.n {
24            1 => MtrixN::Mtrix1(record),
25            2 => MtrixN::Mtrix2(record),
26            3 => MtrixN::Mtrix3(record),
27            _ => panic!("Invalid MTRIXn record"),
28        }
29    }
30}
31
32impl From<&str> for MtrixN {
33    fn from(str: &str) -> Self {
34        MtrixN::new(str)
35    }
36}
37
38#[derive(Debug, Clone)]
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
41#[cfg_attr(feature = "python", pydefault)]
42pub struct MtrixnRecord {
43    pub n: u32,
44    pub serial_number: u32,
45    pub matrix: [f32; 3],
46    pub vn: f32,
47    pub i_given: bool,
48}
49
50impl MtrixnRecord {
51    pub fn new(str: &str) -> Self {
52        Self::from(str)
53    }
54
55    pub fn from(str: &str) -> Self {
56        Self {
57            n: str.chars().nth(5).unwrap() as u32 - 48,
58            serial_number: str[7..10].trim().parse().unwrap(),
59            matrix: [
60                str[10..20].trim().parse().unwrap(),
61                str[20..30].trim().parse().unwrap(),
62                str[30..40].trim().parse().unwrap(),
63            ],
64            vn: str[45..55].trim().parse().unwrap(),
65            i_given: str.chars().nth(59).unwrap() == '1',
66        }
67    }
68}
69
70impl From<&str> for MtrixnRecord {
71    fn from(line: &str) -> Self {
72        Self::from(line)
73    }
74}
75
76impl std::fmt::Display for MtrixnRecord {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        let n = format!("{:1}", self.n);
79        let serial_number = format!("{:3}", self.serial_number);
80        let origxn = format!(
81            "{:10.6}{:10.6}{:10.6}",
82            self.matrix[0], self.matrix[1], self.matrix[2]
83        );
84        let vn = format!("     {:10.5}", self.vn);
85        let i_given = format!("{:1}", self.i_given as u32);
86        write!(
87            f,
88            "{:<1$}",
89            format!("MTRIX{} {}{}{}{:>5}", n, serial_number, origxn, vn, i_given),
90            80
91        )
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn test_mtrixn_record() {
101        let line =
102            "MTRIX1   1 -1.000000  0.000000  0.000000        0.00000    1                   ";
103        let record = MtrixnRecord::from(line);
104        assert_eq!(record.n, 1);
105        assert_eq!(record.serial_number, 1);
106        assert_eq!(record.matrix, [-1., 0., 0.]);
107        assert_eq!(record.vn, 0.);
108        assert!(record.i_given);
109        let line2 = "MTRIX2   1  0.000000  1.000000  0.000000        0.00000    1";
110        let record = MtrixnRecord::from(line2);
111
112        assert_eq!(record.n, 2);
113        assert_eq!(record.serial_number, 1);
114        assert_eq!(record.matrix, [0., 1., 0.]);
115        assert_eq!(record.vn, 0.);
116        assert!(record.i_given);
117    }
118
119    #[test]
120    fn test_mtrixn() {
121        let line = "MTRIX1   1 -1.000000  0.000000  0.000000        0.00000    1";
122        let record = MtrixN::from(line);
123        match record {
124            MtrixN::Mtrix1(record) => {
125                assert_eq!(record.n, 1);
126                assert_eq!(record.serial_number, 1);
127                assert_eq!(record.matrix, [-1., 0., 0.]);
128                assert_eq!(record.vn, 0.);
129                assert!(record.i_given);
130            }
131            _ => unreachable!(),
132        }
133    }
134
135    #[test]
136    fn test_mtrixn_display() {
137        let line =
138            "MTRIX1   1 -1.000000  0.000000  0.000000        0.00000    1                    ";
139        let record = MtrixnRecord::from(line);
140        assert_eq!(format!("{}", record), line);
141    }
142}