1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::common::parser::parse_right;
use crate::common::parser::FieldParser;
use crate::types::*;
use nom::{
bytes::complete::take,
character::complete::{anychar, line_ending},
IResult,
};
pub struct Cryst1Parser;
impl FieldParser for Cryst1Parser {
type Output = Cryst1;
fn parse(i: &str) -> IResult<&str, Cryst1> {
let (i, a) = parse_right::<f32>(i, 9)?;
let (i, b) = parse_right::<f32>(i, 9)?;
let (i, c) = parse_right::<f32>(i, 9)?;
let (i, alpha) = parse_right::<f32>(i, 7)?;
let (i, beta) = parse_right::<f32>(i, 7)?;
let (i, gamma) = parse_right::<f32>(i, 7)?;
let (i, lattice_type) = parse_lattice_type(i)?;
let (i, space_group) = parse_space_group(i)?;
let (i, z) = parse_right::<u8>(i, 4)?;
let (i, _) = take(10usize)(i)?;
let (i, _) = line_ending(i)?;
Ok((
i,
Cryst1 {
a,
b,
c,
alpha,
beta,
gamma,
lattice_type,
space_group,
z,
},
))
}
}
fn parse_lattice_type(i: &str) -> IResult<&str, LatticeType> {
let (i, _) = take(1usize)(i)?;
let (i, c) = anychar(i)?;
let lattice_type = match c {
'P' => LatticeType::Primitive,
'C' => LatticeType::SideCentered,
'I' => LatticeType::BodyCentered,
'F' => LatticeType::FaceCentered,
_ => LatticeType::Unknown,
};
let (i, _) = take(1usize)(i)?;
Ok((i, lattice_type))
}
fn parse_space_group(i: &str) -> IResult<&str, SpaceGroup> {
let (i, a) = parse_group_axis(i)?;
let (i, b) = parse_group_axis(i)?;
let (i, c) = parse_group_axis(i)?;
Ok((i, SpaceGroup(a.unwrap(), b, c)))
}
fn parse_group_axis(i: &str) -> IResult<&str, Option<GroupAxis>> {
let (i, a) = anychar(i)?;
let (i, b) = anychar(i)?;
let (i, _) = anychar(i)?;
let r: Option<GroupAxis> = match (a, b) {
(' ', _) => None,
(_, ' ') => Some(GroupAxis(a.to_digit(10).unwrap(), 1u32)),
_ => Some(GroupAxis(a.to_digit(10).unwrap(), b.to_digit(10).unwrap())),
};
Ok((i, r))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_cryst1() {
let i = " 41.980 41.980 88.920 90.00 90.00 90.00 P 43 21 2 8
ORIGX1 1.000000 0.000000 0.000000 0.00000 ";
let (i, r) = Cryst1Parser::parse(i).unwrap();
assert_eq!(
i.to_owned(),
"ORIGX1 1.000000 0.000000 0.000000 0.00000 "
.to_owned()
);
}
}