use crate::{MjError, mjSpec, mjModel, mjData};
pub fn mj_loadXML(filename: impl Into<String>) -> Result<mjModel, MjError> {
let filename = std::ffi::CString::new(filename.into()).map_err(MjError::from_error)?;
let mut error = MjError::init();
let c_ptr = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_loadXML(
filename.as_ptr(),
std::ptr::null(), err_ptr,
err_len,
)
};
if c_ptr.is_null() {
Err(error)
} else {
Ok(mjModel::from_raw(c_ptr))
}
}
pub fn mj_parseXML(filename: impl Into<String>) -> Result<mjSpec, MjError> {
let filename = std::ffi::CString::new(filename.into()).map_err(MjError::from_error)?;
let mut error = MjError::init();
let c_ptr = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_parseXML(
filename.as_ptr(),
std::ptr::null(), err_ptr,
err_len,
)
};
if c_ptr.is_null() {
Err(error)
} else {
Ok(mjSpec::from_raw(c_ptr))
}
}
pub fn mj_parseXMLString(xml: impl Into<String>) -> Result<mjSpec, MjError> {
let xml = std::ffi::CString::new(xml.into()).map_err(MjError::from_error)?;
let mut error = MjError::init();
let c_ptr = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_parseXMLString(
xml.as_ptr(),
std::ptr::null(), err_ptr,
err_len,
)
};
if c_ptr.is_null() {
Err(error)
} else {
Ok(mjSpec::from_raw(c_ptr))
}
}
pub fn mj_compile(s: &mut mjSpec) -> Option<mjModel> {
let c_ptr = unsafe { crate::bindgen::mj_compile(s.as_mut_ptr(), std::ptr::null()) };
if c_ptr.is_null() {
None
} else {
Some(mjModel::from_raw(c_ptr))
}
}
pub fn mj_recompile(s: &mut mjSpec, m: &mut mjModel, d: &mut mjData) -> Result<(), ()> {
let status = unsafe {
crate::bindgen::mj_recompile(
s.as_mut_ptr(),
std::ptr::null(),
m.as_mut_ptr(),
d.as_mut_ptr(),
)
};
if status == 0 {Ok(())} else {Err(())}
}
pub fn mj_saveLastXML(
filename: impl Into<String>,
m: &mjModel,
) -> Result<(), MjError> {
let filename = std::ffi::CString::new(filename.into()).map_err(MjError::from_error)?;
let mut error = MjError::init();
let status = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_saveLastXML(
filename.as_ptr(),
m.as_ptr(),
err_ptr,
err_len,
)
};
if status == 1 {Ok(())} else {Err(error)}
}
pub fn mj_freeLastXML() {
unsafe {
crate::bindgen::mj_freeLastXML();
}
}
pub fn mj_saveXMLString(s: &mjSpec) -> Result<String, MjError> {
fn proc_inner(
s: &mjSpec,
output_buffer: &mut Vec<u8>,
) -> (i32, MjError) {
let mut error = MjError::init();
let status = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_saveXMLString(
s.as_ptr(),
output_buffer.as_mut_ptr() as *mut std::ffi::c_char,
output_buffer.len() as i32,
err_ptr,
err_len,
)
};
(status, error)
}
#[cold]
#[inline(never)]
fn retry(
s: &mjSpec,
output_buffer: &mut Vec<u8>,
) -> (i32, MjError) {
proc_inner(s, output_buffer)
}
let mut output_buffer = vec![0u8; 1 << 12];
let (mut status, mut error) = proc_inner(s, &mut output_buffer);
if status > 0 {
output_buffer.extend(vec![0u8; status as usize - output_buffer.len()]);
(status, error) = retry(s, &mut output_buffer);
}
if status == 0 {
Ok(String::from_utf8(output_buffer).map_err(MjError::from_error)?)
} else {
#[cfg(debug_assertions)] {
assert_eq!(status, -1, "unexpected status of `mj_saveXMLString`");
}
Err(error)
}
}
pub fn mj_saveXML(
s: &mjSpec,
filename: impl Into<String>,
) -> Result<(), MjError> {
let filename = std::ffi::CString::new(filename.into()).map_err(MjError::from_error)?;
let mut error = MjError::init();
let status = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_saveXML(
s.as_ptr(),
filename.as_ptr(),
err_ptr,
err_len,
)
};
if status == 0 {Ok(())} else {Err(error)}
}