crystal_cif_io/grammar/structures/loop_struct/
body.rs1use winnow::{
2 combinator::{preceded, repeat},
3 Parser,
4};
5
6use crate::{
7 data_dict::{CifTerm, LoopValueTerm},
8 grammar::{tags_values::Value, whitespace_comments::WhiteSpace, SyntacticUnit, Tag},
9};
10
11#[derive(Debug, Clone)]
12pub struct LoopBody {
13 values: Vec<Value>,
14}
15
16impl LoopBody {
17 pub fn new(values: Vec<Value>) -> Self {
18 Self { values }
19 }
20
21 pub fn values(&self) -> &[Value] {
22 &self.values
23 }
24
25 pub fn nth_column_values(&self, nth: usize, column_width: usize) -> Vec<Value> {
27 self.values
28 .chunks(column_width)
29 .map(|chunk| chunk[nth].clone())
30 .collect()
31 }
32
33 pub fn from_columns<T: LoopValueTerm>(columns: &[T], column_length: usize) -> Self {
35 Self::new(
36 (0..column_length)
37 .flat_map(|i| {
38 columns
39 .iter()
40 .map(|c| c.values()[i].clone())
41 .collect::<Vec<Value>>()
42 })
43 .collect::<Vec<Value>>(),
44 )
45 }
46}
47
48impl SyntacticUnit for LoopBody {
49 type ParseResult = Self;
50
51 type FormatOutput = String;
52
53 fn parser(input: &mut &str) -> winnow::prelude::PResult<Self::ParseResult> {
54 (
55 Value::parser,
56 repeat(0.., preceded(WhiteSpace::parser, Value::parser)),
57 )
58 .map(|(first, following): (Value, Vec<Value>)| {
59 let mut values = vec![first];
60 values.extend(following);
61 LoopBody::new(values)
62 })
63 .parse_next(input)
64 }
65
66 fn formatted_output(&self) -> Self::FormatOutput {
67 self.values()
68 .iter()
69 .map(|v| format!("{v}"))
70 .collect::<Vec<String>>()
71 .join(" ")
72 }
73}
74
75#[derive(Debug, Clone)]
76pub struct LoopColumn {
77 tag: Tag,
78 values: Vec<Value>,
79}
80
81impl AsRef<[Value]> for LoopColumn {
82 fn as_ref(&self) -> &[Value] {
83 <Vec<Value> as AsRef<[Value]>>::as_ref(&self.values)
84 }
85}
86
87impl LoopColumn {
88 pub fn new(tag: Tag, values: Vec<Value>) -> Self {
89 Self { tag, values }
90 }
91
92 pub fn values(&self) -> &[Value] {
93 &self.values
94 }
95
96 pub fn tag(&self) -> &Tag {
97 &self.tag
98 }
99
100 pub fn tag_mut(&mut self) -> &mut Tag {
101 &mut self.tag
102 }
103
104 pub fn values_mut(&mut self) -> &mut Vec<Value> {
105 &mut self.values
106 }
107}
108
109impl CifTerm for LoopColumn {
110 fn tag(&self) -> Tag {
111 self.tag.clone()
112 }
113}
114
115impl LoopValueTerm for LoopColumn {
116 fn values(&self) -> Vec<Value> {
117 self.values().to_vec()
118 }
119}