fortran_descriptor_parser_macro/
lib.rs1use quote::quote;
2
3#[derive(Debug, Clone)]
4struct Nested {
5 repetitions: usize,
6 elements: Vec<DataElement>,
7}
8
9#[derive(Debug, Clone)]
10struct ElementInfo {
11 repetitions: usize,
12 bytes_to_take: usize,
13}
14
15impl ElementInfo {
16 fn new(repetitions: usize, bytes_to_take: usize) -> Self {
17 Self {
18 repetitions,
19 bytes_to_take,
20 }
21 }
22}
23
24#[derive(Debug, Clone)]
25enum DataElement {
26 Integer(ElementInfo),
27 Float(ElementInfo),
28 Double(ElementInfo),
29 String(ElementInfo),
30 Nested(Nested),
31}
32
33impl DataElement {
34 fn bytes_to_take(&self) -> usize {
35 match self {
36 DataElement::Integer(element_info) => element_info.bytes_to_take,
37 DataElement::Float(element_info) => element_info.bytes_to_take,
38 DataElement::Double(element_info) => element_info.bytes_to_take,
39 DataElement::String(element_info) => element_info.bytes_to_take,
40 DataElement::Nested(_nested) => unreachable!(),
41 }
42 }
43
44 fn repetitions(&self) -> usize {
45 match self {
46 DataElement::Integer(element_info) => element_info.repetitions,
47 DataElement::Float(element_info) => element_info.repetitions,
48 DataElement::Double(element_info) => element_info.repetitions,
49 DataElement::String(element_info) => element_info.repetitions,
50 DataElement::Nested(_nested) => unreachable!(),
51 }
52 }
53}
54
55fn split_elements(s: &str) -> Vec<String> {
56 let mut complete_list: Vec<String> = vec![];
57 let mut current_element: Vec<char> = vec![];
58 let mut bracket_count = 0;
59 let chars = s.chars();
60 for c in chars {
61 match c {
62 ' ' => (),
63 ',' => {
64 if bracket_count == 0 {
65 complete_list.push(current_element.iter().collect());
66 current_element.clear();
67 } else {
68 current_element.push(c);
69 }
70 }
71 '(' => {
72 bracket_count += 1;
73 current_element.push(c);
74 }
75 ')' => {
76 bracket_count -= 1;
77 current_element.push(c);
78 }
79 _ => {
80 current_element.push(c);
81 }
82 }
83 }
84 if current_element.is_empty() {
85 complete_list
86 } else {
87 complete_list.push(current_element.iter().collect());
88 complete_list
89 }
90}
91
92impl DataElement {
93 fn parse_element(s: &str) -> DataElement {
94 if s.contains("(") {
95 let (repetitions_str, rest) = s.split_at(s.find('(').unwrap());
96 let repetitions = if repetitions_str.is_empty() {
97 1
98 } else {
99 repetitions_str.parse::<usize>().unwrap_or_else(|_| {
100 panic!("Can't convert {} to repetitions (usize)", repetitions_str)
101 })
102 };
103 let mut bracket_count = 0;
104 let mut inner: Vec<char> = Vec::new();
105
106 for c in rest.chars() {
107 match c {
108 '(' => {
109 if bracket_count > 0 {
110 inner.push(c);
111 }
112 bracket_count += 1;
113 }
114 ')' => {
115 bracket_count -= 1;
116 if bracket_count < 1 {
117 let inner: String = inner.iter().collect();
118 let split = split_elements(&inner);
119 let mut nested = Nested {
120 repetitions,
121 elements: Vec::new(),
122 };
123 parse_elements(&split, &mut nested.elements);
124 return DataElement::Nested(nested);
125 } else {
126 inner.push(c);
127 }
128 }
129 _ => {
130 inner.push(c);
131 }
132 }
133 }
134 panic!("Opening bracket was not closed: {}", repetitions_str);
135 } else {
136 let (i, c) =
137 if let Some((i, c)) = s.char_indices().find(|(_i, c)| c.is_ascii_alphabetic()) {
138 (i, c)
139 } else {
140 panic!("Element does not have a type identifier");
141 };
142 let (repetitions_str, bytes_to_take_str) = s.split_at(i);
143 let bytes_to_take_str: String = bytes_to_take_str.chars().skip(1).collect();
144 let repetitions = if repetitions_str.is_empty() {
145 1
146 } else {
147 repetitions_str.parse::<usize>().unwrap_or_else(|_| {
148 panic!("Can't convert {} to repetitions (usize)", repetitions_str)
149 })
150 };
151 let bytes_to_take = bytes_to_take_str.parse::<usize>().unwrap_or_else(|_| {
152 panic!(
153 "Can't convert {} to bytes_to_take (usize)",
154 bytes_to_take_str
155 )
156 });
157 match c.to_ascii_uppercase() {
158 'I' => DataElement::Integer(ElementInfo::new(repetitions, bytes_to_take)),
159 'F' => DataElement::Float(ElementInfo::new(repetitions, bytes_to_take)),
160 'D' => DataElement::Double(ElementInfo::new(repetitions, bytes_to_take)),
161 'S' => DataElement::String(ElementInfo::new(repetitions, bytes_to_take)),
162 _ => panic!("Unsupported type {}", c),
163 }
164 }
165 }
166}
167
168fn parse_elements(split: &Vec<String>, list: &mut Vec<DataElement>) {
169 for s in split {
170 list.push(DataElement::parse_element(s));
171 }
172}
173
174fn expand_elements(elements: &[DataElement]) -> Vec<DataElement> {
175 let mut expanded_elements: Vec<DataElement> = Vec::new();
176 for element in elements.iter() {
177 match element {
178 DataElement::Nested(nested) => {
179 for _ in 0..nested.repetitions {
180 let mut nested_elements = expand_elements(&nested.elements);
181 expanded_elements.append(&mut nested_elements);
182 }
183 }
184 _ => {
185 for _ in 0..element.repetitions() {
186 expanded_elements.push(element.clone());
187 }
188 }
189 }
190 }
191 expanded_elements
192}
193
194#[proc_macro]
196pub fn descriptor_parser(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
197 let mut input_iter = input.into_iter();
198 let input_string = if let Some(tree) = input_iter.next() {
199 match tree {
200 proc_macro::TokenTree::Literal(literal) => literal.to_string(),
201 _ => panic!("Please provide a string, found {:?}", tree),
202 }
203 } else {
204 panic!("Please provide a string literal, found empty input");
205 };
206 let input_string: String = input_string.chars().filter(|c| *c != '"').collect();
207 let split = split_elements(&input_string);
208 let mut elements = Vec::new();
209 parse_elements(&split, &mut elements);
210
211 let expanded_elements = expand_elements(&elements);
212 let bytes_to_take = expanded_elements
213 .iter()
214 .fold(0, |acc, e| acc + e.bytes_to_take());
215
216 let mut parse_tokens = Vec::new();
217 for e in expanded_elements.iter() {
218 match e {
219 DataElement::Integer(element_info) => {
220 let bytes_to_take = element_info.bytes_to_take;
221 parse_tokens.push(quote! {
222 <[u8] as ::fortran_descriptor_parser::FromSlice<i32>>::to_type(::fortran_descriptor_parser::get_sub_slice(&mut start_byte, #bytes_to_take, i))?
223 });
224 }
225 DataElement::Float(element_info) => {
226 let bytes_to_take = element_info.bytes_to_take;
227 parse_tokens.push(quote! {
228 <[u8] as ::fortran_descriptor_parser::FromSlice<f32>>::to_type(::fortran_descriptor_parser::get_sub_slice(&mut start_byte, #bytes_to_take, i))?
229 });
230 }
231 DataElement::Double(element_info) => {
232 let bytes_to_take = element_info.bytes_to_take;
233 parse_tokens.push(quote! {
234 <[u8] as ::fortran_descriptor_parser::FromSlice<f64>>::to_type(::fortran_descriptor_parser::get_sub_slice(&mut start_byte, #bytes_to_take, i))?
235 });
236 }
237 DataElement::String(element_info) => {
238 let bytes_to_take = element_info.bytes_to_take;
239 parse_tokens.push(quote! {
240 <[u8] as ::fortran_descriptor_parser::FromSlice<String>>::to_type(::fortran_descriptor_parser::get_sub_slice(&mut start_byte, #bytes_to_take, i))?
241 });
242 }
243 DataElement::Nested(_nested) => unreachable!(),
244 }
245 }
246 quote! {
247 |i: &[u8]| {
248 if i.len() < #bytes_to_take {
249 return Err(::fortran_descriptor_parser::DescriptorParserError::NotEnoughBytes(i.len(), #bytes_to_take));
250 }
251 let mut start_byte: usize = 0;
252 let parsers = (#(#parse_tokens),*);
253 Ok(parsers)
254 }
255 }
256 .into()
257}