1
//!!  The core section to instruct the compiler to work with C++20 modules. The most important are the base path to the interfaces and implementation files
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
/// [`ModulesAttribute`] -  The core section to instruct the compiler to work with C++20 modules.
6
/// * `base_ifcs_dir`- Base directory to shortcut the path of the implementation files
7
/// * `interfaces` - A list to define the module interface translation units for the project
8
/// * `base_impls_dir` - Base directory to shortcut the path of the implementation files
9
/// * `implementations` - A list to define the module interface translation units for the project
10
/// * `sys_modules` - An array field explicitly declare which system headers
11
///     must be precompiled in order to make the importable translation units
12
///
13
/// ### Tests
14
///
15
/// ```rust
16
/// use zork::config_file::modules::ModulesAttribute;
17
/// const CONFIG_FILE_MOCK: &str = r#"
18
///     base_ifcs_dir = "./ifc"
19
///     interfaces = [
20
///         { file = 'math.cppm' }, { file = 'some_module.cppm', module_name = 'math' }
21
///     ]
22
///     base_impls_dir = './src'
23
///     implementations = [
24
///         { file = 'math.cpp' }, { file = 'some_module_impl.cpp', dependencies = ['iostream'] }
25
///     ]
26
///     sys_modules = ['iostream', 'vector', 'string', 'type_traits', 'functional']
27
/// "#;
28
///
29
/// let config: ModulesAttribute = toml::from_str(CONFIG_FILE_MOCK)
30
///    .expect("A failure happened parsing the Zork toml file");
31
///
32
/// assert_eq!(config.base_ifcs_dir, Some("./ifc"));
33
///
34
/// let ifcs = config.interfaces.unwrap();
35
/// let ifc_0 = &ifcs[0];
36
/// assert_eq!(ifc_0.file, "math.cppm");
37
/// assert_eq!(ifc_0.module_name, None);
38
/// let ifc_1 = &ifcs[1];
39
/// assert_eq!(ifc_1.file, "some_module.cppm");
40
/// assert_eq!(ifc_1.module_name, Some("math"));
41
///
42
///
43
/// assert_eq!(config.base_impls_dir, Some("./src"));
44
///
45
/// let impls = config.implementations.unwrap();
46
/// let impl_0 = &impls[0];
47
/// assert_eq!(impl_0.file, "math.cpp");
48
/// assert_eq!(impl_0.dependencies, None);
49
/// let impl_1 = &impls[1];
50
/// assert_eq!(impl_1.file, "some_module_impl.cpp");
51
/// assert_eq!(impl_1.dependencies, Some(vec!["iostream"]));
52
///
53
///
54
/// let gcc_sys_headers = config.sys_modules.unwrap();
55
/// assert_eq!(&gcc_sys_headers[0], &"iostream");
56
/// assert_eq!(&gcc_sys_headers[1], &"vector");
57
/// assert_eq!(&gcc_sys_headers[2], &"string");
58
/// assert_eq!(&gcc_sys_headers[3], &"type_traits");
59
/// assert_eq!(&gcc_sys_headers[4], &"functional");
60
/// ```
61
145
#[derive(Serialize, Deserialize, Debug, Default, PartialEq)]
62
pub struct ModulesAttribute<'a> {
63
    #[serde(borrow)]
64
    pub base_ifcs_dir: Option<&'a str>,
65
    #[serde(borrow)]
66
    pub interfaces: Option<Vec<ModuleInterface<'a>>>,
67
    #[serde(borrow)]
68
    pub base_impls_dir: Option<&'a str>,
69
    #[serde(borrow)]
70
    pub implementations: Option<Vec<ModuleImplementation<'a>>>,
71
    #[serde(borrow)]
72
    pub sys_modules: Option<Vec<&'a str>>,
73
}
74

            
75
/// [`ModuleInterface`] -  A module interface structure for dealing
76
/// with the parse work of prebuild module interface units
77
///
78
/// * `file`- The path of a primary module interface (relative to base_ifcs_path if applies)
79
///
80
/// * `module_name` - An optional field for make an explicit declaration of the
81
///     C++ module declared on this module interface with the `export module 'module_name'
82
///     statement. If this attribute isn't present, Zork++ will assume that the
83
///     C++ module declared within this file is equals to the filename
84
///
85
/// * `partition` - Whenever this attribute is present, we are telling Zork++ that the
86
///     actual translation unit is a partition, either an interface partition or an implementation
87
///     partition unit
88
///
89
/// * `dependencies` - An optional array field for declare the module interfaces
90
///     in which this file is dependent on
91
/// ### Tests
92
/// ```rust
93
/// use zork::config_file::modules::ModulesAttribute;
94
/// use zork::config_file::modules::ModuleInterface;
95
/// const CONFIG_FILE_MOCK: &str = r#"
96
///     interfaces = [
97
///         { file = 'math.cppm' },
98
///         { file = 'some_module.cppm', module_name = 'math' },
99
///         { file = 'a.cppm', module_name = 'module', dependencies = ['math', 'type_traits', 'iostream'] },
100
///         { file = 'some_module_part.cppm', module_name = 'math_part', dependencies = ['math'] }
101
///     ]
102
/// "#;
103
///
104
/// let config: ModulesAttribute = toml::from_str(CONFIG_FILE_MOCK)
105
///    .expect("A failure happened parsing the Zork toml file");
106
///
107
/// let ifcs = config.interfaces.unwrap();
108
///
109
/// let ifc_0 = &ifcs[0];
110
/// assert_eq!(ifc_0.file, "math.cppm");
111
/// assert_eq!(ifc_0.module_name, None);
112
/// assert_eq!(ifc_0.partition, None);
113
///
114
/// let ifc_1 = &ifcs[1];
115
/// assert_eq!(ifc_1.file, "some_module.cppm");
116
/// assert_eq!(ifc_1.module_name, Some("math"));
117
///
118
/// let ifc_2 = &ifcs[2];
119
/// assert_eq!(ifc_2.file, "a.cppm");
120
/// assert_eq!(ifc_2.module_name, Some("module"));
121
/// let deps = ifc_2.dependencies.as_ref().unwrap();
122
///
123
/// let deps_ifc2 = ifc_2.dependencies.as_ref().unwrap();
124
/// assert_eq!(deps_ifc2[0], "math");
125
/// assert_eq!(deps_ifc2[1], "type_traits");
126
/// assert_eq!(deps_ifc2[2], "iostream");
127
///
128
/// let ifc_3 = &ifcs[3];
129
/// assert_eq!(ifc_3.file, "some_module_part.cppm");
130
/// assert_eq!(ifc_3.module_name, Some("math_part"));
131
/// ```
132
201
#[derive(Serialize, Deserialize, Debug, Default, PartialEq)]
133
#[serde(deny_unknown_fields)]
134
pub struct ModuleInterface<'a> {
135
    #[serde(borrow)]
136
    pub file: &'a str,
137
    #[serde(borrow)]
138
    pub module_name: Option<&'a str>,
139
    #[serde(borrow)]
140
    pub partition: Option<ModulePartition<'a>>,
141
    #[serde(borrow)]
142
    pub dependencies: Option<Vec<&'a str>>,
143
}
144

            
145
/// [`ModulePartition`] - Type for dealing with the parse work
146
/// of module partitions, either interfaces or implementations
147
///
148
/// * `module`- The interface module unit that this partitions belongs to
149
///
150
/// * `partition_name` - An optional field for explicitly declare the name of a module interface
151
///     partition, or a module implementation partition.
152
///     Currently this requirement is only needed if your partitions file names aren't
153
///     declared as the modules convention, that is `module_name-partition_name.extension`
154
///
155
/// * `is_internal_partition` - Optional field for declare that the module is actually
156
///     a module for hold implementation details, known as module implementation partitions.
157
///     This option only takes effect with MSVC
158
80
#[derive(Serialize, Deserialize, Debug, Default, PartialEq)]
159
pub struct ModulePartition<'a> {
160
    #[serde(borrow)]
161
    pub module: &'a str,
162
    #[serde(borrow)]
163
    pub partition_name: Option<&'a str>,
164
    pub is_internal_partition: Option<bool>,
165
}
166

            
167
/// [`ModuleImplementation`] -  Type for dealing with the parse work
168
/// of module implementation translation units
169
///
170
/// * `file`- The path of a primary module interface (relative to base_ifcs_path)
171
/// * `dependencies` - An optional array field for declare the module interfaces
172
///     in which this file is dependent on
173
///
174
/// ### Tests
175
/// ```rust
176
/// use zork::config_file::modules::ModulesAttribute;
177
/// use zork::config_file::modules::ModuleImplementation;
178
/// const CONFIG_FILE_MOCK: &str = r#"
179
///     implementations = [
180
///         { file = 'math.cppm', is_partition = false },
181
///         { file = 'a.cppm', dependencies = ['math', 'type_traits', 'iostream'] }
182
///     ]
183
/// "#;
184
///
185
/// let config: ModulesAttribute = toml::from_str(CONFIG_FILE_MOCK)
186
///    .expect("A failure happened parsing the Zork toml file");
187
///
188
/// let impls = config.implementations.unwrap();
189
///
190
/// let impl_0 = &impls[0];
191
/// assert_eq!(impl_0.file, "math.cppm");
192
///
193
/// let impl_1 = &impls[1];
194
/// assert_eq!(impl_1.file, "a.cppm");
195
/// let deps = impl_1.dependencies.as_ref().unwrap();
196
/// assert_eq!(deps[0], "math");
197
/// assert_eq!(deps[1], "type_traits");
198
/// assert_eq!(deps[2], "iostream");
199
/// ```
200
154
#[derive(Serialize, Deserialize, Debug, Default, PartialEq)]
201
pub struct ModuleImplementation<'a> {
202
    #[serde(borrow)]
203
    pub file: &'a str,
204
    #[serde(borrow)]
205
    pub dependencies: Option<Vec<&'a str>>,
206
}