@@ -290,3 +290,90 @@ mod tests {
290290 . unwrap ( ) ;
291291 }
292292}
293+
294+ pub struct VsiDirEntry {
295+ pub name : String ,
296+ pub mode : Option < i32 > ,
297+ pub size : Option < crate :: gdal_dyn_bindgen:: vsi_l_offset > ,
298+ pub mtime : Option < crate :: gdal_dyn_bindgen:: GIntBig > ,
299+ }
300+
301+ pub struct VsiDir {
302+ api : & ' static crate :: gdal_api:: GdalApi ,
303+ handle : * mut crate :: gdal_dyn_bindgen:: VSIDIR ,
304+ }
305+
306+ impl VsiDir {
307+ pub fn next_entry ( & mut self ) -> Option < VsiDirEntry > {
308+ let entry = unsafe { ( self . api . inner . VSIGetNextDirEntry ?) ( self . handle ) } ;
309+ if entry. is_null ( ) {
310+ return None ;
311+ }
312+ let entry = unsafe { & * entry } ;
313+
314+ let name = if entry. pszName . is_null ( ) {
315+ String :: new ( )
316+ } else {
317+ unsafe { std:: ffi:: CStr :: from_ptr ( entry. pszName ) }
318+ . to_string_lossy ( )
319+ . into_owned ( )
320+ } ;
321+
322+ Some ( VsiDirEntry {
323+ name,
324+ mode : ( entry. bModeKnown != 0 ) . then_some ( entry. nMode ) ,
325+ size : ( entry. bSizeKnown != 0 ) . then_some ( entry. nSize ) ,
326+ mtime : ( entry. bMTimeKnown != 0 ) . then_some ( entry. nMTime ) ,
327+ } )
328+ }
329+ }
330+
331+ impl Iterator for VsiDir {
332+ type Item = VsiDirEntry ;
333+ fn next ( & mut self ) -> Option < Self :: Item > {
334+ self . next_entry ( )
335+ }
336+ }
337+
338+ impl Drop for VsiDir {
339+ fn drop ( & mut self ) {
340+ if !self . handle . is_null ( ) {
341+ if let Some ( close) = self . api . inner . VSICloseDir {
342+ unsafe { close ( self . handle ) } ;
343+ }
344+ self . handle = std:: ptr:: null_mut ( ) ;
345+ }
346+ }
347+ }
348+
349+ pub fn open_dir (
350+ api : & ' static crate :: gdal_api:: GdalApi ,
351+ path : & str ,
352+ recurse_depth : i32 ,
353+ options : Option < & crate :: cpl:: CslStringList > ,
354+ ) -> crate :: errors:: Result < VsiDir > {
355+ let c_path = std:: ffi:: CString :: new ( path) ?;
356+ let options_ptr: * const * const std:: os:: raw:: c_char = options
357+ . map ( |opts| opts. as_ptr ( ) as * const * const std:: os:: raw:: c_char )
358+ . unwrap_or ( std:: ptr:: null ( ) ) ;
359+ let handle =
360+ unsafe { ( api. inner . VSIOpenDir . unwrap ( ) ) ( c_path. as_ptr ( ) , recurse_depth, options_ptr) } ;
361+ if handle. is_null ( ) {
362+ return Err ( api. last_null_pointer_err ( "VSIOpenDir" ) ) ;
363+ }
364+ Ok ( VsiDir { api, handle } )
365+ }
366+
367+ pub fn get_directory_separator (
368+ api : & ' static crate :: gdal_api:: GdalApi ,
369+ path : & str ,
370+ ) -> crate :: errors:: Result < String > {
371+ let c_path = std:: ffi:: CString :: new ( path) ?;
372+ let separator_ptr = unsafe { ( api. inner . VSIGetDirectorySeparator . unwrap ( ) ) ( c_path. as_ptr ( ) ) } ;
373+ if separator_ptr. is_null ( ) {
374+ return Err ( api. last_null_pointer_err ( "VSIGetDirectorySeparator" ) ) ;
375+ }
376+ Ok ( unsafe { std:: ffi:: CStr :: from_ptr ( separator_ptr) }
377+ . to_string_lossy ( )
378+ . into_owned ( ) )
379+ }
0 commit comments