knuckles_parse/records/
mtrixn.rs1#[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}