1#[macro_use]
4mod file_description;
5mod activation;
6mod data_processing;
7mod instrument;
8mod run;
9mod sample;
10mod scan_settings;
11mod software;
12#[macro_use]
13mod traits;
14
15use mzdata_param as params;
16use mzdata_param::{curie, impl_param_described};
17
18use std::borrow::Cow;
19
20pub use data_processing::{
21 DataProcessing, DataProcessingAction, DataTransformationAction, FormatConversion,
22 ProcessingMethod,
23};
24pub use software::{
25 custom_software_name, Software, SoftwareTerm, SoftwareType as SoftwareTypeFlags,
26};
27
28pub use file_description::{
29 FileDescription, MassSpectrometerFileFormatTerm, NativeIDFormatError, NativeSpectrumIDFormat,
30 NativeSpectrumIdentifierFormatTerm, SourceFile, SpectrumType,
31};
32
33pub use instrument::{
34 Component, ComponentType, DetectorTypeTerm, InletTypeTerm, InstrumentConfiguration,
35 IonizationTypeTerm, MassAnalyzerTerm,
36};
37
38pub use activation::{DissociationEnergy, DissociationEnergyTerm, DissociationMethodTerm};
39pub use run::MassSpectrometryRun;
40pub use sample::Sample;
41pub use scan_settings::ScanSettings;
42pub use traits::{FileMetadataConfig, MSDataFileMetadata};
43
44use crate::params::{ParamValueParseError, Value, ValueRef};
45
46#[macro_export]
47macro_rules! cvmap {
48 (
49 #[flag_type=$flag_type:ty]
50 $(#[$enum_attrs:meta])*
51 $vis:vis enum $enum_name:ident {
52 $(
53 #[term(cv=$cv:ident, accession=$accession:literal, name=$term_name:literal, flags=$flags:tt, parents=$parents:tt)]
54 $(#[$variant_attrs:meta])*
55 $variant:ident
56 ),*
57 $(,)?
58 }
59 ) => {
60 $(#[$enum_attrs])*
61 $vis enum $enum_name {
62 $(
63 $(#[$variant_attrs])*
64 $variant,
65 )*
66 }
67
68 impl $enum_name {
70
71 pub const fn accession(&self) -> $crate::params::AccessionIntCode {
73 match self {
74 $(Self::$variant => $accession,)*
75 }
76 }
77
78 pub const fn controlled_vocabulary(&self) -> $crate::params::ControlledVocabulary {
80 match self {
81 $(Self::$variant => $crate::params::ControlledVocabulary::$cv,)*
82 }
83 }
84
85 pub const fn name(&self) -> &'static str {
87 match self {
88 $(Self::$variant => $term_name,)*
89 }
90 }
91
92 pub fn from_name(name: &str) -> Option<Self> {
97 match name {
98 $($term_name => Some(Self::$variant),)*
99 _ => None
100 }
101 }
102
103
104 pub const fn from_accession(accession: $crate::params::AccessionIntCode) -> Option<Self> {
109 match accession {
110 $($accession => Some(Self::$variant),)*
111 _ => None
112 }
113 }
114
115 pub const fn to_param(self) -> $crate::params::ParamCow<'static> {
117 $crate::params::ParamCow::const_new(
118 self.name(),
119 $crate::params::ValueRef::Empty,
120 Some(self.accession()),
121 Some(self.controlled_vocabulary()),
122 $crate::params::Unit::Unknown
123 )
124 }
125
126 pub const fn from_curie(curie: &$crate::params::CURIE) -> Option<Self> {
130 if matches!(curie.controlled_vocabulary, $crate::params::ControlledVocabulary::MS) {
131 Self::from_accession(curie.accession)
132 } else {
133 None
134 }
135 }
136
137 pub const fn from_param(p: &$crate::params::ParamCow<'static>) -> Option<Self> {
145 if let Some(acc) = p.accession {
146 Self::from_accession(acc)
147 } else {
148 None
149 }
150 }
151
152 pub fn flags(&self) -> $flag_type {
154 match self {
155 $(Self::$variant => $flags.into(),)*
156 }
157 }
158
159 pub fn parents(&self) -> Vec<Self> {
162 match self {
163 $(Self::$variant => $parents.iter().flat_map(|s: &&str| {
164 let curie = s.parse::<$crate::params::CURIE>().unwrap();
165 Self::from_accession(curie.accession)
166 }).collect(),)*
167 }
168 }
169
170 #[cfg(feature = "cv")]
171 pub fn is_parent_of(&self, curie: $crate::params::CURIE) -> bool {
177 let self_curie = $crate::params::CURIE::new(self.controlled_vocabulary(), self.accession());
178 $crate::params::MSVocabulary::is_child_of(curie, self_curie)
179 }
180 }
181
182 impl<P> From<P> for $enum_name where P: $crate::params::ParamLike {
183 fn from(value: P) -> Self {
184 Self::from_accession(
185 value.accession().expect(
186 concat!("Cannot convert an uncontrolled parameter to ", stringify!($enum_name)))
187 ).unwrap_or_else(
188 || panic!(
189 "Could not map {:?}:{} to {}",
190 value.controlled_vocabulary().unwrap(),
191 value.accession().unwrap(),
192 stringify!($enum_name)
193 )
194 )
195 }
196 }
197
198 impl From<$enum_name> for $crate::params::ParamCow<'static> {
199 fn from(value: $enum_name) -> Self {
200 value.to_param()
201 }
202 }
203
204 impl From<$enum_name> for $crate::params::Param {
205 fn from(value: $enum_name) -> Self {
206 value.to_param().into()
207 }
208 }
209
210 impl From<&$enum_name> for $crate::params::ParamCow<'static> {
211 fn from(value: &$enum_name) -> Self {
212 value.to_param()
213 }
214 }
215
216 impl From<&$enum_name> for $crate::params::Param {
217 fn from(value: &$enum_name) -> Self {
218 value.to_param().into()
219 }
220 }
221 };
222
223 (
224 #[value_type=$value_type:ty]
225 #[flag_type=$flag_type:ty]
226 $(#[$enum_attrs:meta])*
227 $vis:vis enum $enum_name:ident {
228 $(
229 #[term(cv=$cv:ident, accession=$accession:literal, name=$term_name:literal, flags=$flags:tt, parents=$parents:tt)]
230 $(#[$variant_attrs:meta])*
231 $variant:ident($value_type2:ty)
232 ),*
233 $(,)?
234 }
235 ) => {
236 $(#[$enum_attrs])*
237 $vis enum $enum_name {
238 $(
239 $(#[$variant_attrs])*
240 $variant($value_type),
241 )*
242 }
243
244 impl $enum_name {
246
247 pub const fn accession(&self) -> $crate::params::AccessionIntCode {
249 match self {
250 $(Self::$variant(_) => $accession,)*
251 }
252 }
253
254 pub const fn controlled_vocabulary(&self) -> $crate::params::ControlledVocabulary {
256 match self {
257 $(Self::$variant(_) => $crate::params::ControlledVocabulary::$cv,)*
258 }
259 }
260
261 pub const fn name(&self) -> &'static str {
263 match self {
264 $(Self::$variant(_) => $term_name,)*
265 }
266 }
267
268 pub fn from_name(name: &str) -> Option<Self> {
273 match name {
274 $($term_name => Some(Self::$variant(Default::default())),)*
275 _ => None
276 }
277 }
278
279
280 pub const fn from_accession(accession: $crate::params::AccessionIntCode, value: $value_type) -> Option<Self> {
285 match accession {
286 $($accession => Some(Self::$variant(value)),)*
287 _ => None
288 }
289 }
290
291 pub const fn to_param(self) -> $crate::params::ParamCow<'static> {
293 $crate::params::ParamCow::const_new(
294 self.name(),
295 $crate::params::ValueRef::Empty,
296 Some(self.accession()),
297 Some(self.controlled_vocabulary()),
298 $crate::params::Unit::Unknown
299 )
300 }
301
302 pub const fn to_param_value(self, value: $crate::params::ValueRef<'static>) -> $crate::params::ParamCow<'static> {
304 $crate::params::ParamCow::const_new(
305 self.name(),
306 value,
307 Some(self.accession()),
308 Some(self.controlled_vocabulary()),
309 $crate::params::Unit::Unknown
310 )
311 }
312
313 pub fn from_curie(curie: &$crate::params::CURIE, value: f32) -> Option<Self> {
317 if matches!(curie.controlled_vocabulary, $crate::params::ControlledVocabulary::MS) {
318 Self::from_accession(curie.accession, value)
319 } else {
320 None
321 }
322 }
323
324 pub fn from_param(p: &$crate::params::ParamCow<'static>) -> Option<Self> {
332 if let Some(acc) = p.accession {
333 Self::from_accession(acc, p.value.clone().into())
334 } else {
335 None
336 }
337 }
338
339 pub fn flags(&self) -> $flag_type {
341 match self {
342 $(Self::$variant(_) => $flags.into(),)*
343 }
344 }
345
346 pub fn parents(&self) -> Vec<Self> {
349 match self {
350 $(Self::$variant(_) => $parents.iter().flat_map(|s: &&str| {
351 let curie = s.parse::<$crate::params::CURIE>().unwrap();
352 Self::from_accession(curie.accession, Default::default())
353 }).collect(),)*
354 }
355 }
356
357 }
358
359 impl<P> From<P> for $enum_name where P: $crate::params::ParamLike {
360 fn from(value: P) -> Self {
361 Self::from_accession(
362 value.accession().expect(
363 concat!("Cannot convert an uncontrolled parameter to ", stringify!($enum_name))),
364 value.value().into()
365 ).unwrap_or_else(
366 || panic!(
367 "Could not map {:?}:{} to {}",
368 value.controlled_vocabulary().unwrap(),
369 value.accession().unwrap(),
370 stringify!($enum_name)
371 )
372 )
373 }
374 }
375
376 impl From<$enum_name> for $crate::params::ParamCow<'static> {
377 fn from(value: $enum_name) -> Self {
378 value.to_param()
379 }
380 }
381
382 impl From<$enum_name> for $crate::params::Param {
383 fn from(value: $enum_name) -> Self {
384 value.to_param().into()
385 }
386 }
387
388 impl From<&$enum_name> for $crate::params::ParamCow<'static> {
389 fn from(value: &$enum_name) -> Self {
390 value.to_param()
391 }
392 }
393
394 impl From<&$enum_name> for $crate::params::Param {
395 fn from(value: &$enum_name) -> Self {
396 value.to_param().into()
397 }
398 }
399 };
400}
401
402bitflags::bitflags! {
403 #[doc="A bit mask encoding the different value types a [`Param`](crate::params::Param) can take on, associated with a term."]
404 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
405 pub struct ValueType: u16 {
406 const NoType = 0;
407 const String = 0b00000001;
408 const Integer = 0b00000010;
409 const Float = 0b00000100;
410 const Double = 0b00001000;
411 const NonNegativeInteger = 0b00010000;
412 const PositiveInteger = 0b00100000;
413 const DateTime = 0b01000000;
414 const Boolean = 0b10000000;
415
416 const ListOf = 0b1000000000000000;
417 }
418}
419
420impl From<u16> for ValueType {
421 fn from(value: u16) -> Self {
422 Self::from_bits_retain(value)
423 }
424}
425
426impl ValueType {
427 pub fn parse(&self, s: String) -> Result<Value, ParamValueParseError> {
428 let v = match *self {
429 Self::Integer | Self::NonNegativeInteger | Self::PositiveInteger => Value::Int(
430 s.parse()
431 .map_err(|_| ParamValueParseError::FailedToExtractInt(Some(s)))?,
432 ),
433 Self::Float | Self::Double => Value::Float(
434 s.parse()
435 .map_err(|_| ParamValueParseError::FailedToExtractFloat(Some(s)))?,
436 ),
437 _ => Value::String(s),
438 };
439 Ok(v)
440 }
441
442 pub fn parse_str<'a>(&self, s: &'a str) -> Result<ValueRef<'a>, ParamValueParseError> {
443 let v = match *self {
444 Self::Integer | Self::NonNegativeInteger | Self::PositiveInteger => ValueRef::Int(
445 s.parse()
446 .map_err(|_| ParamValueParseError::FailedToExtractInt(Some(s.to_string())))?,
447 ),
448 Self::Float | Self::Double => ValueRef::Float(
449 s.parse()
450 .map_err(|_| ParamValueParseError::FailedToExtractFloat(Some(s.to_string())))?,
451 ),
452 _ => ValueRef::String(Cow::Borrowed(s)),
453 };
454 Ok(v)
455 }
456}