use std::convert::TryInto;
use std::ffi::CStr;
use std::path::Path;
use chemfiles_sys as ffi;
use crate::errors::check_success;
use crate::{errors::check, Error};
#[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: &ffi::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(ffi::chfl_formats_list(&mut formats, &mut count));
std::slice::from_raw_parts(formats, count.try_into().expect("failed to convert u64 to usize"))
};
let formats_vec = formats_slice.iter().map(FormatMetadata::from_raw).collect();
unsafe {
let _ = ffi::chfl_free(formats as *const _);
}
return formats_vec;
}
#[allow(clippy::doc_markdown)]
pub fn guess_format<P>(path: P) -> Result<String, Error>
where
P: AsRef<Path>,
{
let path = path.as_ref().to_str().expect("couldn't convert path to Unicode");
let path = crate::strings::to_c(path);
let mut buffer = vec![0; 128];
unsafe {
check(ffi::chfl_guess_format(
path.as_ptr(),
buffer.as_mut_ptr(),
buffer.len() as u64,
))?;
}
Ok(crate::strings::from_c(buffer.as_ptr()))
}