1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::convert::TryInto;
use std::ffi::CStr;
use chemfiles_sys::{chfl_format_metadata, chfl_formats_list, chfl_free};
use errors::check_success;
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FormatMetadata {
pub name: &'static str,
pub extension: Option<&'static str>,
pub description: &'static str,
pub reference: &'static str,
pub read: bool,
pub write: bool,
pub memory: bool,
pub positions: bool,
pub velocities: bool,
pub unit_cell: bool,
pub atoms: bool,
pub bonds: bool,
pub residues: bool,
}
impl FormatMetadata {
pub(crate) fn from_raw(raw: &chfl_format_metadata) -> Self {
let str_from_ptr = |ptr| unsafe {
CStr::from_ptr(ptr)
.to_str()
.expect("Invalid Rust str from C")
};
let extension = if raw.extension.is_null() {
None
} else {
Some(str_from_ptr(raw.extension))
};
Self {
name: str_from_ptr(raw.name),
extension,
description: str_from_ptr(raw.description),
reference: str_from_ptr(raw.reference),
read: raw.read,
write: raw.write,
memory: raw.memory,
positions: raw.positions,
velocities: raw.velocities,
unit_cell: raw.unit_cell,
atoms: raw.atoms,
bonds: raw.bonds,
residues: raw.residues,
}
}
}
#[must_use]
pub fn formats_list() -> Vec<FormatMetadata> {
let mut formats = std::ptr::null_mut();
let mut count: u64 = 0;
let formats_slice = unsafe {
check_success(chfl_formats_list(&mut formats, &mut count));
std::slice::from_raw_parts(formats, count.try_into().unwrap())
};
let formats_vec = formats_slice
.iter()
.map(|fm| FormatMetadata::from_raw(fm))
.collect();
unsafe {
let _ = chfl_free(formats as *const _);
}
return formats_vec;
}