use crate::{Codec, Model, ModelError};
#[cfg(feature = "step")]
pub fn from_step_bytes(bytes: &[u8]) -> Result<Model, ModelError> {
ifc_step::StepCodec.read_bytes(bytes)
}
#[allow(clippy::vec_init_then_push)]
pub fn codecs() -> Vec<Box<dyn Codec>> {
#[allow(unused_mut)]
let mut out: Vec<Box<dyn Codec>> = Vec::new();
#[cfg(feature = "step")]
out.push(Box::new(ifc_step::StepCodec));
#[cfg(feature = "ifcxml")]
out.push(Box::new(ifc_xml::XmlCodec::default()));
out
}
pub fn read_path(path: &std::path::Path) -> Result<Model, ModelError> {
let bytes = std::fs::read(path).map_err(|e| ModelError::Io(e.to_string()))?;
let extension = path
.extension()
.and_then(|e| e.to_str())
.unwrap_or_default()
.to_ascii_lowercase();
let available = codecs();
let chosen = available
.iter()
.position(|codec| codec.detect(&bytes))
.or_else(|| {
available
.iter()
.position(|codec| codec.extensions().contains(&extension.as_str()))
});
if let Some(index) = chosen {
return available[index].read_owned(bytes);
}
Err(ModelError::WrongFormat {
expected: "IFC",
detail: format!(
"no compiled-in codec recognized this input (available: {})",
available
.iter()
.map(|c| c.name())
.collect::<Vec<_>>()
.join(", ")
),
})
}