molecule_codegen/generator/languages/c/
reader.rs

1use std::io;
2
3use super::utilities::IdentPrefix;
4use crate::ast;
5
6pub(super) trait GenReader: IdentPrefix {
7    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()>;
8
9    fn gen_reader_interfaces<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
10        self.gen_reader_interfaces_internal(writer)?;
11        Ok(())
12    }
13
14    fn gen_reader_functions<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
15        self.gen_reader_function_verify(writer)?;
16        Ok(())
17    }
18
19    fn gen_reader_function_verify<W: io::Write>(&self, _writer: &mut W) -> io::Result<()> {
20        Ok(())
21    }
22}
23
24impl GenReader for ast::Option_ {
25    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
26        {
27            self.define_reader_function(
28                writer,
29                "_verify",
30                "(const mol_seg_t*, bool)",
31                "mol_errno",
32            )?;
33        }
34        {
35            self.define_reader_macro(writer, "_is_none(s)", "mol_option_is_none(s)")?;
36        }
37        Ok(())
38    }
39
40    fn gen_reader_function_verify<W: io::Write>(&self, o: &mut W) -> io::Result<()> {
41        let func_name = format!("{}_verify", self.reader_prefix());
42        let api_decorator = self.api_decorator();
43        w!(
44            o,
45            "{} mol_errno {} (const mol_seg_t *input, bool compatible) {{",
46            api_decorator,
47            func_name
48        );
49        if self.item().typ().is_byte() {
50            w!(o, "    if (input->size > 1) {{                            ");
51            w!(o, "        return MOL_ERR;                                ");
52        } else {
53            let f = format!("{}_verify", self.item().typ().reader_prefix());
54            w!(o, "    if (input->size != 0) {{                           ");
55            w!(o, "        return {}(input, compatible);               ", f);
56        }
57        w!(o, "    }} else {{                                         ");
58        w!(o, "        return MOL_OK;                                 ");
59        w!(o, "    }}                                                 ");
60        w!(o, "}}                                                     ");
61        Ok(())
62    }
63}
64
65impl GenReader for ast::Union {
66    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
67        {
68            self.define_reader_function(
69                writer,
70                "_verify",
71                "(const mol_seg_t*, bool)",
72                "mol_errno",
73            )?;
74        }
75        {
76            self.define_reader_macro(writer, "_unpack(s)", "mol_union_unpack(s)")?;
77        }
78        Ok(())
79    }
80
81    fn gen_reader_function_verify<W: io::Write>(&self, o: &mut W) -> io::Result<()> {
82        let func_name = format!("{}_verify", self.reader_prefix());
83        let api_decorator = self.api_decorator();
84        w!(
85            o,
86            "{} mol_errno {} (const mol_seg_t *input, bool compatible) {{",
87            api_decorator,
88            func_name
89        );
90        w!(o, "    if (input->size < MOL_NUM_T_SIZE) {{               ");
91        w!(o, "        return MOL_ERR_HEADER;                         ");
92        w!(o, "    }}                                                 ");
93        w!(o, "    mol_num_t item_id = mol_unpack_number(input->ptr); ");
94        w!(o, "    mol_seg_t inner;                                   ");
95        w!(o, "    inner.ptr = input->ptr + MOL_NUM_T_SIZE;           ");
96        w!(o, "    inner.size = input->size - MOL_NUM_T_SIZE;         ");
97        w!(o, "    switch(item_id) {{                                 ");
98        for item in self.items().iter() {
99            w!(
100                o,
101                "        case {}:                              ",
102                item.id()
103            );
104            if item.typ().is_byte() {
105                w!(o, "            return inner.size == 1 ? MOL_OK : MOL_ERR; ");
106            } else {
107                let f = format!("{}_verify", item.typ().reader_prefix());
108                w!(o, "            return {}(&inner, compatible);          ", f);
109            }
110        }
111        w!(o, "        default:                                       ");
112        w!(o, "            return MOL_ERR_UNKNOWN_ITEM;               ");
113        w!(o, "    }}                                                 ");
114        w!(o, "}}                                                     ");
115        Ok(())
116    }
117}
118
119impl GenReader for ast::Array {
120    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
121        {
122            let macro_content = format!("mol_verify_fixed_size(s, {})", self.total_size());
123            self.define_reader_macro(writer, "_verify(s, c)", &macro_content)?;
124        }
125        for i in 0..self.item_count() {
126            let macro_sig_tail = format!("_get_nth{}(s)", i);
127            let item_offset = self.item_size() * i;
128            let macro_content = format!(
129                "mol_slice_by_offset(s, {}, {})",
130                item_offset,
131                self.item_size()
132            );
133            self.define_reader_macro(writer, &macro_sig_tail, &macro_content)?;
134        }
135        Ok(())
136    }
137}
138
139impl GenReader for ast::Struct {
140    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
141        {
142            let macro_content = format!("mol_verify_fixed_size(s, {})", self.total_size());
143            self.define_reader_macro(writer, "_verify(s, c)", &macro_content)?;
144        }
145        let mut field_offset = 0;
146        for (f, field_size) in self.fields().iter().zip(self.field_sizes().iter()) {
147            let macro_sig_tail = format!("_get_{}(s)", f.name());
148            let macro_content = format!("mol_slice_by_offset(s, {}, {})", field_offset, field_size);
149            self.define_reader_macro(writer, &macro_sig_tail, &macro_content)?;
150            field_offset += field_size;
151        }
152        Ok(())
153    }
154}
155
156impl GenReader for ast::FixVec {
157    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
158        {
159            let macro_content = format!("mol_fixvec_verify(s, {})", self.item_size());
160            self.define_reader_macro(writer, "_verify(s, c)", &macro_content)?;
161        }
162        {
163            self.define_reader_macro(writer, "_length(s)", "mol_fixvec_length(s)")?;
164        }
165        {
166            let macro_content = format!("mol_fixvec_slice_by_index(s, {}, i)", self.item_size());
167            self.define_reader_macro(writer, "_get(s, i)", &macro_content)?;
168        }
169        if self.item().typ().is_byte() {
170            self.define_reader_macro(writer, "_raw_bytes(s)", "mol_fixvec_slice_raw_bytes(s)")?;
171        }
172        Ok(())
173    }
174}
175
176impl GenReader for ast::DynVec {
177    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
178        {
179            self.define_reader_function(
180                writer,
181                "_verify",
182                "(const mol_seg_t*, bool)",
183                "mol_errno",
184            )?;
185        }
186        {
187            self.define_reader_macro(writer, "_length(s)", "mol_dynvec_length(s)")?;
188        }
189        {
190            self.define_reader_macro(writer, "_get(s, i)", "mol_dynvec_slice_by_index(s, i)")?;
191        }
192        Ok(())
193    }
194
195    fn gen_reader_function_verify<W: io::Write>(&self, o: &mut W) -> io::Result<()> {
196        let func_name = format!("{}_verify", self.reader_prefix());
197        let api_decorator = self.api_decorator();
198        let f = format!("{}_verify", self.item().typ().reader_prefix());
199        w!(
200            o,
201            "{} mol_errno {} (const mol_seg_t *input, bool compatible) {{",
202            api_decorator,
203            func_name
204        );
205        w!(o, "    if (input->size < MOL_NUM_T_SIZE) {{               ");
206        w!(o, "        return MOL_ERR_HEADER;                         ");
207        w!(o, "    }}                                                 ");
208        w!(o, "    uint8_t *ptr = input->ptr;                         ");
209        w!(o, "    mol_num_t total_size = mol_unpack_number(ptr);     ");
210        w!(o, "    if (input->size != total_size) {{                  ");
211        w!(o, "        return MOL_ERR_TOTAL_SIZE;                     ");
212        w!(o, "    }}                                                 ");
213        w!(o, "    if (input->size == MOL_NUM_T_SIZE) {{              ");
214        w!(o, "        return MOL_OK;                                 ");
215        w!(o, "    }}                                                 ");
216        w!(o, "    if (input->size < MOL_NUM_T_SIZE * 2) {{           ");
217        w!(o, "        return MOL_ERR_HEADER;                         ");
218        w!(o, "    }}                                                 ");
219        w!(o, "    ptr += MOL_NUM_T_SIZE;                             ");
220        w!(o, "    mol_num_t offset = mol_unpack_number(ptr);         ");
221        w!(o, "    if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) {{");
222        w!(o, "        return MOL_ERR_OFFSET;                         ");
223        w!(o, "    }}                                                 ");
224        w!(o, "    mol_num_t item_count = offset / 4 - 1;             ");
225        w!(o, "    if (input->size < MOL_NUM_T_SIZE*(item_count+1)) {{");
226        w!(o, "        return MOL_ERR_HEADER;                         ");
227        w!(o, "    }}                                                 ");
228        w!(o, "    mol_num_t end;                                     ");
229        w!(o, "    for (mol_num_t i=1; i<item_count; i++) {{          ");
230        w!(o, "        ptr += MOL_NUM_T_SIZE;                         ");
231        w!(o, "        end = mol_unpack_number(ptr);                  ");
232        w!(o, "        if (offset > end) {{                           ");
233        w!(o, "            return MOL_ERR_OFFSET;                     ");
234        w!(o, "        }}                                             ");
235        w!(o, "        mol_seg_t inner;                               ");
236        w!(o, "        inner.ptr = input->ptr + offset;               ");
237        w!(o, "        inner.size = end - offset;                     ");
238        w!(o, "        if (mol_contained_by(&inner, input)!=MOL_OK) {{");
239        w!(o, "            return MOL_ERR_OFFSET;                     ");
240        w!(o, "        }}                                             ");
241        w!(o, "        mol_errno errno = {}(&inner, compatible);   ", f);
242        w!(o, "        if (errno != MOL_OK) {{                        ");
243        w!(o, "            return MOL_ERR_DATA;                       ");
244        w!(o, "        }}                                             ");
245        w!(o, "        offset = end;                                  ");
246        w!(o, "    }}                                                 ");
247        w!(o, "    if (offset > total_size) {{                        ");
248        w!(o, "        return MOL_ERR_OFFSET;                         ");
249        w!(o, "    }}                                                 ");
250        w!(o, "    mol_seg_t inner;                                   ");
251        w!(o, "    inner.ptr = input->ptr + offset;                   ");
252        w!(o, "    inner.size = total_size - offset;                  ");
253        w!(o, "    if (mol_contained_by(&inner, input) != MOL_OK) {{  ");
254        w!(o, "        return MOL_ERR_OFFSET;                         ");
255        w!(o, "    }}                                                 ");
256        w!(o, "    return {}(&inner, compatible);                  ", f);
257        w!(o, "}}                                                     ");
258        Ok(())
259    }
260}
261
262impl GenReader for ast::Table {
263    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
264        {
265            self.define_reader_function(
266                writer,
267                "_verify",
268                "(const mol_seg_t*, bool)",
269                "mol_errno",
270            )?;
271        }
272        {
273            self.define_reader_macro(
274                writer,
275                "_actual_field_count(s)",
276                "mol_table_actual_field_count(s)",
277            )?;
278        }
279        {
280            let macro_content = format!("mol_table_has_extra_fields(s, {})", self.fields().len());
281            self.define_reader_macro(writer, "_has_extra_fields(s)", &macro_content)?;
282        }
283        for (i, f) in self.fields().iter().enumerate() {
284            let macro_sig_tail = format!("_get_{}(s)", f.name());
285            let macro_content = format!("mol_table_slice_by_index(s, {})", i);
286            self.define_reader_macro(writer, &macro_sig_tail, &macro_content)?;
287        }
288        Ok(())
289    }
290
291    fn gen_reader_function_verify<W: io::Write>(&self, o: &mut W) -> io::Result<()> {
292        let func_name = format!("{}_verify", self.reader_prefix());
293        let api_decorator = self.api_decorator();
294        let fc = self.fields().len();
295        w!(
296            o,
297            "{} mol_errno {} (const mol_seg_t *input, bool compatible) {{",
298            api_decorator,
299            func_name
300        );
301        w!(o, "    if (input->size < MOL_NUM_T_SIZE) {{               ");
302        w!(o, "        return MOL_ERR_HEADER;                         ");
303        w!(o, "    }}                                                 ");
304        w!(o, "    uint8_t *ptr = input->ptr;                         ");
305        w!(o, "    mol_num_t total_size = mol_unpack_number(ptr);     ");
306        w!(o, "    if (input->size != total_size) {{                  ");
307        w!(o, "        return MOL_ERR_TOTAL_SIZE;                     ");
308        w!(o, "    }}                                                 ");
309        if self.fields().is_empty() {
310            w!(o, "    if (input->size == MOL_NUM_T_SIZE) {{              ");
311            w!(o, "        return MOL_OK;                                 ");
312            w!(o, "    }}                                                 ");
313        }
314        w!(o, "    if (input->size < MOL_NUM_T_SIZE * 2) {{           ");
315        w!(o, "        return MOL_ERR_HEADER;                         ");
316        w!(o, "    }}                                                 ");
317        w!(o, "    ptr += MOL_NUM_T_SIZE;                             ");
318        w!(o, "    mol_num_t offset = mol_unpack_number(ptr);         ");
319        w!(o, "    if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) {{");
320        w!(o, "        return MOL_ERR_OFFSET;                         ");
321        w!(o, "    }}                                                 ");
322        w!(o, "    mol_num_t field_count = offset / 4 - 1;            ");
323        w!(o, "    if (field_count < {}) {{                       ", fc);
324        w!(o, "        return MOL_ERR_FIELD_COUNT;                    ");
325        w!(o, "    }} else if (!compatible && field_count > {}) {{", fc);
326        w!(o, "        return MOL_ERR_FIELD_COUNT;                    ");
327        w!(o, "    }}                                                 ");
328        w!(o, "    if (input->size < MOL_NUM_T_SIZE*(field_count+1)){{");
329        w!(o, "        return MOL_ERR_HEADER;                         ");
330        w!(o, "    }}                                                 ");
331        w!(o, "    mol_num_t offsets[field_count+1];                  ");
332        w!(o, "    offsets[0] = offset;                               ");
333        w!(o, "    for (mol_num_t i=1; i<field_count; i++) {{         ");
334        w!(o, "        ptr += MOL_NUM_T_SIZE;                         ");
335        w!(o, "        offsets[i] = mol_unpack_number(ptr);           ");
336        w!(o, "        if (offsets[i-1] > offsets[i]) {{              ");
337        w!(o, "            return MOL_ERR_OFFSET;                     ");
338        w!(o, "        }}                                             ");
339        w!(o, "    }}                                                 ");
340        w!(o, "    if (offsets[field_count-1] > total_size) {{        ");
341        w!(o, "        return MOL_ERR_OFFSET;                         ");
342        w!(o, "    }}                                                 ");
343        if !self.fields().is_empty() {
344            w!(o, "    offsets[field_count] = total_size;                 ");
345            if self.fields().iter().any(|field| !field.typ().is_byte()) {
346                w!(o, "        mol_seg_t inner;                               ");
347                w!(o, "        mol_errno errno;                               ");
348            }
349            for (i, field) in self.fields().iter().enumerate() {
350                let j = i + 1;
351                if field.typ().is_byte() {
352                    w!(o, "        if (offsets[{}] - offsets[{}] != 1) {{   ", j, i);
353                    w!(o, "            return MOL_ERR_DATA;                       ");
354                    w!(o, "        }}                                             ");
355                } else {
356                    let f = format!("{}_verify", field.typ().reader_prefix());
357                    w!(o, "        inner.ptr = input->ptr + offsets[{}];       ", i);
358                    w!(o, "        inner.size = offsets[{}] - offsets[{}];  ", j, i);
359                    w!(o, "        if (mol_contained_by(&inner, input)!=MOL_OK) {{");
360                    w!(o, "            return MOL_ERR_OFFSET;                     ");
361                    w!(o, "        }}                                             ");
362                    w!(o, "        errno = {}(&inner, compatible);             ", f);
363                    w!(o, "        if (errno != MOL_OK) {{                        ");
364                    w!(o, "            return MOL_ERR_DATA;                       ");
365                    w!(o, "        }}                                             ");
366                }
367            }
368        }
369        w!(o, "    return MOL_OK;                                     ");
370        w!(o, "}}                                                     ");
371        Ok(())
372    }
373}
374
375impl GenReader for ast::TopDecl {
376    fn gen_reader_interfaces_internal<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
377        match self {
378            ast::TopDecl::Option_(ref i) => i.gen_reader_interfaces_internal(writer),
379            ast::TopDecl::Union(ref i) => i.gen_reader_interfaces_internal(writer),
380            ast::TopDecl::Array(ref i) => i.gen_reader_interfaces_internal(writer),
381            ast::TopDecl::Struct(ref i) => i.gen_reader_interfaces_internal(writer),
382            ast::TopDecl::FixVec(ref i) => i.gen_reader_interfaces_internal(writer),
383            ast::TopDecl::DynVec(ref i) => i.gen_reader_interfaces_internal(writer),
384            ast::TopDecl::Table(ref i) => i.gen_reader_interfaces_internal(writer),
385            ast::TopDecl::Primitive(_) => unreachable!(),
386        }
387    }
388
389    fn gen_reader_function_verify<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
390        match self {
391            ast::TopDecl::Option_(ref i) => i.gen_reader_function_verify(writer),
392            ast::TopDecl::Union(ref i) => i.gen_reader_function_verify(writer),
393            ast::TopDecl::Array(ref i) => i.gen_reader_function_verify(writer),
394            ast::TopDecl::Struct(ref i) => i.gen_reader_function_verify(writer),
395            ast::TopDecl::FixVec(ref i) => i.gen_reader_function_verify(writer),
396            ast::TopDecl::DynVec(ref i) => i.gen_reader_function_verify(writer),
397            ast::TopDecl::Table(ref i) => i.gen_reader_function_verify(writer),
398            ast::TopDecl::Primitive(_) => unreachable!(),
399        }
400    }
401}