use core::ffi::CStr;
use std::ffi::CString;
use ndk::android::asset::*;
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct Assets {
inner: *const AAssetManager,
}
impl Assets {
pub fn as_sys(&self) -> *mut AAssetManager {
self.inner as _
}
pub fn from_java(env: *mut jni::JNIEnv, asset_manager: jni::jobject) -> Self {
let inner = unsafe { AAssetManager_fromJava(env, asset_manager) };
Self { inner }
}
pub fn read_dir(&self, dir_name: &CStr, file_list: &mut Vec<CString>) -> Option<()> {
let dir = unsafe { AAssetManager_openDir(self.inner as _, dir_name.as_ptr()) };
let dir = Dir::from_sys(dir)?;
dir.read(file_list);
Some(())
}
pub fn read(&self, file_name: &CStr, bytes: &mut Vec<u8>) -> Result<(), &'static str> {
debug_assert!(!self.inner.is_null());
let file = unsafe { AAssetManager_open(self.inner as _, file_name.as_ptr(), AASSET_MODE_BUFFER as _) };
let file = File::from_sys(file)?;
file.read(bytes)?;
core::mem::forget(file);
Ok(())
}
}
struct Dir(*mut AAssetDir);
impl Drop for Dir {
fn drop(&mut self) {
unsafe { AAssetDir_close(self.0) };
}
}
impl Dir {
pub fn from_sys(dir: *mut AAssetDir) -> Option<Self> {
if !dir.is_null() {
Some(Self(dir))
} else {
None
}
}
pub fn read(&self, file_list: &mut Vec<CString>) {
loop {
let file = unsafe { AAssetDir_getNextFileName(self.0) };
if !file.is_null() {
let file = unsafe { CStr::from_ptr(file) };
file_list.push(file.to_owned());
continue;
}
break;
}
}
}
struct File(*mut AAsset);
impl Drop for File {
fn drop(&mut self) {
unsafe { AAsset_close(self.0) };
}
}
impl File {
pub fn from_sys(file: *mut AAsset) -> Result<Self, &'static str> {
if !file.is_null() {
Ok(Self(file))
} else {
Err("AAsset File handle Null")
}
}
pub fn read(&self, bytes: &mut Vec<u8>) -> Result<(), &'static str> {
let len = unsafe { AAsset_getLength64(self.0) } as usize;
let data = unsafe { AAsset_getBuffer(self.0) } as *const u8;
if data.is_null() {
return Err("AAsset_getBuffer failed");
}
let src = unsafe { core::slice::from_raw_parts(data, len) };
bytes.reserve(len);
unsafe { bytes.set_len(len) };
bytes.copy_from_slice(src);
Ok(())
}
}