1use std::ffi::{CStr, CString};
2use std::os::raw::c_char;
3use std::path::Path;
4
5use libheif_sys as lh;
6
7use crate::{FileTypeResult, HeifError, HeifErrorCode, HeifErrorSubCode, Result};
8
9#[inline]
10pub(crate) fn cstr_to_str<'a>(c_str: *const c_char) -> Option<&'a str> {
11 if c_str.is_null() {
12 None
13 } else {
14 let res = unsafe { CStr::from_ptr(c_str).to_str() };
15 res.ok()
16 }
17}
18
19pub(crate) fn str_to_cstring(s: &str, name: &str) -> Result<CString> {
20 CString::new(s).map_err(|e| HeifError {
21 code: HeifErrorCode::UsageError,
22 sub_code: HeifErrorSubCode::InvalidParameterValue,
23 message: format!("Invalid value of '{}': {}", name, e),
24 })
25}
26
27pub(crate) fn path_to_cstring(path: &Path) -> CString {
28 #[cfg(unix)]
29 {
30 use std::os::unix::ffi::OsStrExt;
31 CString::new(path.as_os_str().as_bytes()).unwrap_or_default()
32 }
33
34 #[cfg(windows)]
35 {
36 use std::os::windows::ffi::OsStrExt;
37 let mut buf = Vec::new();
38 buf.extend(
39 path.as_os_str()
40 .encode_wide()
41 .chain(Some(0))
42 .flat_map(|b| b.to_ne_bytes()),
43 );
44 CString::new(buf).unwrap_or_default()
45 }
46}
47
48#[cfg(feature = "v1_18")]
49pub(crate) fn get_non_null_ptr<T>(ptr: *mut T) -> Result<std::ptr::NonNull<T>> {
50 std::ptr::NonNull::new(ptr).ok_or_else(|| HeifError {
51 code: HeifErrorCode::MemoryAllocationError,
52 sub_code: HeifErrorSubCode::Unspecified,
53 message: "".to_string(),
54 })
55}
56
57pub fn check_file_type(data: &[u8]) -> FileTypeResult {
60 let res = unsafe { lh::heif_check_filetype(data.as_ptr(), data.len() as _) };
61 FileTypeResult::n(res).unwrap_or(FileTypeResult::No)
62}