Skip to main content

ohos_resource_manager_binding/
raw_dir.rs

1use ohos_resource_manager_sys::{
2    OH_ResourceManager_CloseRawDir, OH_ResourceManager_CloseRawFile,
3    OH_ResourceManager_CloseRawFile64, OH_ResourceManager_GetRawFileCount,
4    OH_ResourceManager_GetRawFileDescriptor64, OH_ResourceManager_GetRawFileDescriptorData,
5    OH_ResourceManager_GetRawFileName, OH_ResourceManager_GetRawFileOffset,
6    OH_ResourceManager_GetRawFileOffset64, OH_ResourceManager_GetRawFileRemainingLength,
7    OH_ResourceManager_GetRawFileRemainingLength64, OH_ResourceManager_GetRawFileSize,
8    OH_ResourceManager_GetRawFileSize64, OH_ResourceManager_IsRawDir,
9    OH_ResourceManager_OpenRawDir, OH_ResourceManager_OpenRawFile,
10    OH_ResourceManager_OpenRawFile64, OH_ResourceManager_ReadRawFile,
11    OH_ResourceManager_ReadRawFile64, OH_ResourceManager_SeekRawFile,
12    OH_ResourceManager_SeekRawFile64, RawFileDescriptor, RawFileDescriptor64,
13};
14use std::collections::HashMap;
15use std::ffi::CString;
16use std::ptr::NonNull;
17use std::{ffi::CStr, fmt::Display, os::raw::c_void};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct FileMetaInfo {
21    index: i32,
22    is_dir: bool,
23}
24
25/// RawDir
26pub struct RawDir {
27    #[allow(dead_code)]
28    mgr: NonNull<ohos_resource_manager_sys::NativeResourceManager>,
29    path: String,
30
31    /// Current file folder file name and index
32    pub files: HashMap<String, FileMetaInfo>,
33}
34
35impl RawDir {
36    pub fn from_raw(
37        mgr: NonNull<ohos_resource_manager_sys::NativeResourceManager>,
38        path: String,
39        recursive: bool,
40    ) -> Self {
41        let mut files = HashMap::new();
42        let mut dirs = Vec::new();
43
44        let dir = CString::new(path.clone()).expect("Can't crate CString.");
45        let raw = unsafe { OH_ResourceManager_OpenRawDir(mgr.as_ptr(), dir.as_ptr().cast()) };
46        // if rawfiles is empty, return null ptr.
47        if raw.is_null() {
48            return RawDir { mgr, path, files };
49        }
50
51        let count = unsafe { OH_ResourceManager_GetRawFileCount(raw) };
52        for i in 0..count {
53            let name = unsafe { OH_ResourceManager_GetRawFileName(raw, i) };
54            let name_ret = unsafe { CStr::from_ptr(name).to_str().unwrap_or("") }.to_string();
55
56            // avoid double //
57            let mut format_name = format!("{}/{}", path, name_ret).replace("//", "/");
58
59            if format_name.starts_with("/") {
60                format_name = format_name.split_at(1).1.to_string();
61            }
62
63            let full_path = CString::new(format_name.clone()).unwrap();
64
65            let is_dir =
66                unsafe { OH_ResourceManager_IsRawDir(mgr.as_ptr(), full_path.as_ptr().cast()) };
67
68            files.insert(format_name.clone(), FileMetaInfo { index: i, is_dir });
69
70            // if recursive, and is dir, then add to dirs
71            if recursive && is_dir {
72                dirs.push(format_name.clone());
73            }
74        }
75
76        // close raw dir
77        unsafe { OH_ResourceManager_CloseRawDir(raw) };
78
79        while let Some(dir) = dirs.pop() {
80            let dir_c = CString::new(dir.clone()).unwrap();
81
82            let dir_raw =
83                unsafe { OH_ResourceManager_OpenRawDir(mgr.as_ptr(), dir_c.as_ptr().cast()) };
84            #[cfg(debug_assertions)]
85            assert!(!dir_raw.is_null(), "RawDir is null");
86
87            let count = unsafe { OH_ResourceManager_GetRawFileCount(dir_raw) };
88            for i in 0..count {
89                let name = unsafe { OH_ResourceManager_GetRawFileName(dir_raw, i) };
90                let name_ret = unsafe { CStr::from_ptr(name).to_str().unwrap_or("") }.to_string();
91
92                let mut format_name = format!("{}/{}", dir.clone(), name_ret).replace("//", "/");
93
94                if format_name.starts_with("/") {
95                    format_name = format_name.split_at(1).1.to_string();
96                }
97
98                let full_path = CString::new(format_name.clone()).unwrap();
99
100                let is_dir =
101                    unsafe { OH_ResourceManager_IsRawDir(mgr.as_ptr(), full_path.as_ptr().cast()) };
102
103                files.insert(format_name.clone(), FileMetaInfo { index: i, is_dir });
104
105                // if recursive, and is dir, then add to dirs
106                if recursive && is_dir {
107                    dirs.push(format_name.clone());
108                }
109            }
110
111            unsafe { OH_ResourceManager_CloseRawDir(dir_raw) };
112        }
113
114        RawDir { mgr, files, path }
115    }
116
117    pub fn open_file<S: AsRef<str>>(&self, file_name: S) -> RawFile {
118        let file_name = file_name.as_ref();
119        let file_name_c = CString::new(file_name).unwrap();
120
121        let raw = unsafe {
122            OH_ResourceManager_OpenRawFile(self.mgr.as_ptr(), file_name_c.as_ptr().cast())
123        };
124        RawFile::from_raw(raw)
125    }
126
127    pub fn open_file64<S: AsRef<str>>(&self, file_name: S) -> RawFile64 {
128        let file_name = file_name.as_ref();
129        let file_name_c = CString::new(file_name).unwrap();
130
131        let raw = unsafe {
132            OH_ResourceManager_OpenRawFile64(self.mgr.as_ptr(), file_name_c.as_ptr().cast())
133        };
134        RawFile64::from_raw(raw)
135    }
136}
137
138impl Display for RawDir {
139    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140        write!(f, "RawDir: {}", self.path)
141    }
142}
143
144/// Use for file size less than 2G
145/// If the file size is greater than 2G, there is a risk of precision loss, it is recommended to use RawFile64
146pub struct RawFile {
147    raw: NonNull<ohos_resource_manager_sys::RawFile>,
148}
149
150impl RawFile {
151    pub fn from_raw(raw: *mut ohos_resource_manager_sys::RawFile) -> Self {
152        #[cfg(debug_assertions)]
153        assert!(!raw.is_null(), "RawFile is null");
154
155        Self {
156            raw: unsafe { NonNull::new_unchecked(raw) },
157        }
158    }
159
160    pub fn file_size(&self) -> i32 {
161        unsafe { OH_ResourceManager_GetRawFileSize(self.raw.as_ptr()) as _ }
162    }
163
164    pub fn seek(&self, offset: i32, whence: i32) -> i32 {
165        unsafe { OH_ResourceManager_SeekRawFile(self.raw.as_ptr(), offset as _, whence) }
166    }
167
168    pub fn offset(&self) -> i32 {
169        unsafe { OH_ResourceManager_GetRawFileOffset(self.raw.as_ptr()) as _ }
170    }
171
172    pub fn read(&self, len: usize) -> Vec<u8> {
173        let mut ret = vec![0; len];
174        let _ = unsafe {
175            OH_ResourceManager_ReadRawFile(
176                self.raw.as_ptr(),
177                ret.as_mut_ptr() as *mut c_void,
178                len as _,
179            )
180        };
181        ret
182    }
183
184    pub fn remain(&self) -> i32 {
185        unsafe { OH_ResourceManager_GetRawFileRemainingLength(self.raw.as_ptr()) as _ }
186    }
187
188    /// try to get fd with start and length
189    /// get failed it will return -1 and then return fd
190    pub fn fd(&self, start: i32, len: i32) -> i32 {
191        let mut file_descriptor = RawFileDescriptor {
192            fd: 0,
193            start: start as _,
194            length: len as _,
195        };
196        let ret = unsafe {
197            OH_ResourceManager_GetRawFileDescriptorData(self.raw.as_ptr(), &mut file_descriptor)
198        };
199        if ret {
200            file_descriptor.fd
201        } else {
202            -1
203        }
204    }
205}
206
207impl Drop for RawFile {
208    fn drop(&mut self) {
209        unsafe {
210            OH_ResourceManager_CloseRawFile(self.raw.as_ptr());
211        }
212    }
213}
214
215pub struct RawFile64 {
216    raw: NonNull<ohos_resource_manager_sys::RawFile64>,
217}
218
219/// Using for file size.
220/// Recommended to use this type if the file size is greater than 2G
221impl RawFile64 {
222    pub fn from_raw(raw: *mut ohos_resource_manager_sys::RawFile64) -> Self {
223        #[cfg(debug_assertions)]
224        assert!(!raw.is_null(), "RawFile64 is null");
225        Self {
226            raw: unsafe { NonNull::new_unchecked(raw) },
227        }
228    }
229
230    pub fn file_size(&self) -> i64 {
231        unsafe { OH_ResourceManager_GetRawFileSize64(self.raw.as_ptr()) }
232    }
233
234    pub fn seek(&self, offset: i64, whence: i32) -> i32 {
235        unsafe { OH_ResourceManager_SeekRawFile64(self.raw.as_ptr(), offset, whence) }
236    }
237
238    pub fn offset(&self) -> i64 {
239        unsafe { OH_ResourceManager_GetRawFileOffset64(self.raw.as_ptr()) }
240    }
241
242    pub fn read(&self, len: i64) -> Vec<u8> {
243        let mut ret = vec![0; len as usize];
244        let _ = unsafe {
245            OH_ResourceManager_ReadRawFile64(
246                self.raw.as_ptr(),
247                ret.as_mut_ptr() as *mut c_void,
248                len,
249            )
250        };
251        ret
252    }
253
254    pub fn remain(&self) -> i64 {
255        unsafe { OH_ResourceManager_GetRawFileRemainingLength64(self.raw.as_ptr()) }
256    }
257
258    /// try to get fd with start and length
259    /// get failed it will return -1 and then return fd
260    pub fn fd(&self, start: i64, len: i64) -> i32 {
261        let mut file_descriptor = RawFileDescriptor64 {
262            fd: 0,
263            start,
264            length: len,
265        };
266        let ret = unsafe {
267            OH_ResourceManager_GetRawFileDescriptor64(self.raw.as_ptr(), &mut file_descriptor)
268        };
269        if ret {
270            file_descriptor.fd
271        } else {
272            -1
273        }
274    }
275}
276
277impl Drop for RawFile64 {
278    fn drop(&mut self) {
279        unsafe {
280            OH_ResourceManager_CloseRawFile64(self.raw.as_ptr());
281        }
282    }
283}