csv_deserializer/
struct_gen.rs1#![allow(clippy::uninlined_format_args)]
2
3use crate::{
4 COLUMN_TYPE_ENUM_NAME, ColName, CsvDataset, MAIN_STRUCT_NAME, SanitizedStr, csv_type::CsvAny, dataset_info::{ColumnInfo, Variant}
5};
6
7pub fn gen_struct(dataset: &CsvDataset) -> String {
11 let mut final_str = format!("pub struct {MAIN_STRUCT_NAME}{{\n");
12
13 dataset.names.iter().for_each(|name| {
15 final_str.push_str(&format!(
16 "\tpub {}: {},\n",
17 name.sanitized.0.to_lowercase(),
18 COLUMN_TYPE_ENUM_NAME
19 ));
20 });
21 final_str.push('}');
22
23 let impl_str_open = format!(
24 "impl {MAIN_STRUCT_NAME}{{
25"
26 );
27 let new_method = gen_new_method(&dataset.names, &dataset.info);
28 let column_list_method = gen_column_list_method(&dataset.names);
29 let impl_str_close = '}';
30
31 final_str.push_str(&impl_str_open);
32 final_str.push_str(&new_method);
33 final_str.push_str(&column_list_method);
34 final_str.push(impl_str_close);
35
36 final_str
37}
38
39fn gen_column_list_method(col_names: &[ColName]) -> String {
40 let mut number_of_cols = 0;
41 let columns = col_names
42 .iter()
43 .map(|x| {
44 number_of_cols += 1;
45 format!("&self.{},", x.sanitized.0)
46 })
47 .collect::<String>();
48 format!(
49 "\
50 pub fn get_columns(&self)-> [&{COLUMN_TYPE_ENUM_NAME};{number_of_cols}] {{
51 [{columns}]
52 }}"
53 )
54}
55
56fn gen_new_method(col_names: &[ColName], cols_info: &[ColumnInfo]) -> String {
57 let vecs_of_enums = cols_info
58 .iter()
59 .map(|col_info| gen_vec_of_enums(&col_info.column_name, &col_info.unique_values) + "\n\n")
60 .collect::<String>();
61
62 let fields_list = col_names
63 .iter()
64 .map(|colname| format!("{},\n\t\t\t", colname.sanitized.0.to_lowercase()))
65 .collect::<String>();
66 format!(
67 "\
68 pub fn new(dataset: &csv_deserializer::CsvDataset) -> Self{{
69 {vecs_of_enums}
70
71 {MAIN_STRUCT_NAME}{{
72 {fields_list}
73 }}
74 }}
75"
76 )
77}
78
79fn gen_vec_of_enums(col_name: &ColName, unique_values: &[Variant]) -> String {
80 let ColName {
81 raw: _raw,
82 sanitized,
83 } = col_name;
84 let SanitizedStr(sanitized) = sanitized;
85 let sanitized_lower = sanitized.to_lowercase();
86 let mut float_case_already_written = false;
87 let mut int_case_already_written = false;
88 let mut str_case_already_written = false;
89 let match_arms = unique_values
90 .iter()
91 .filter_map(|v| match &v.csvany {
92 CsvAny::Str(_) if !str_case_already_written => {
93 str_case_already_written = true;
94 Some(format!(
95 "csv_deserializer::csv_type::CsvAny::Str(s) => {sanitized}::from_str(s).unwrap(),\n"
96 ))
97 }
98 CsvAny::Int(_) if !int_case_already_written => {
99 int_case_already_written = true;
100 Some(format!(
101 "csv_deserializer::csv_type::CsvAny::Int(i) => {sanitized}::Int(*i),\n"
102 ))
103 }
104 CsvAny::Float(_) if !float_case_already_written => {
105 float_case_already_written = true;
106 Some(format!(
107 "csv_deserializer::csv_type::CsvAny::Float(f) => {sanitized}::Float(*f),\n"
108 ))
109 }
110 CsvAny::Null => Some(format!(
111 "csv_deserializer::csv_type::CsvAny::Null => {sanitized}::Null,\n"
112 )),
113 CsvAny::Empty => Some(format!(
114 "csv_deserializer::csv_type::CsvAny::Empty => {sanitized}::Null,\n"
115 )),
116 _ => None,
117 })
118 .collect::<String>();
119 format!(
120 "\
121let (index, _) = dataset
122 .names
123 .iter()
124 .enumerate()
125 .find(|(index, cl)| &cl.sanitized.0 == \"{sanitized}\")
126 .unwrap();
127let {sanitized_lower} = {COLUMN_TYPE_ENUM_NAME}::{sanitized}(dataset.values[index].iter().map(|val| match val{{
128 {match_arms}
129 _ => panic!(),
130}}).collect::<Vec<{sanitized}>>());
131 "
132 )
133}