From 359dc10cb19621cfd60af39b9123e33a52f366ee Mon Sep 17 00:00:00 2001 From: Barugon Date: Fri, 13 May 2022 00:22:08 -0700 Subject: [PATCH 1/5] Squash --- CHANGES.md | 4 +++ fixtures/test_vsi_read_dir.zip | Bin 0 -> 930 bytes src/vsi.rs | 60 ++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 fixtures/test_vsi_read_dir.zip diff --git a/CHANGES.md b/CHANGES.md index d4bdd844d..d43bd3a38 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,10 @@ - +- Add `gdal::vsi::read_dir` function. + + - + ## 0.12 - Bump Rust edition to 2021 diff --git a/fixtures/test_vsi_read_dir.zip b/fixtures/test_vsi_read_dir.zip new file mode 100644 index 0000000000000000000000000000000000000000..e38aeb4865162d2618c57b82310fafc4056863ad GIT binary patch literal 930 zcmWIWW@Zs#0D%BY?+`EpO0Y91Fr?+@q@)(M77{U%TNDyI&TV_tGf{9*9MG4$EkWpBSD?WY3Gt}TA6GMPEJI8H?Bg;5} zCV@;t*dv|l1$Qh+h6`v9*aAbi1>qH}Ng(Wx>0XEhPaqb|`?C2qrUl}-EHHvw;0H7u zgmGH%2x39(@_8RHEl|N_fic{IRG{G?jMIW=5DR3cwZ24Hz{n)Rj5|hwVFd&B*40;uAR{P|f9I pgqllK>>`^Bibmw{M>RJeW-d{Y8sN>!2J$N_5bgo$ya2=u3;@)Bv$y~N literal 0 HcmV?d00001 diff --git a/src/vsi.rs b/src/vsi.rs index 9c2143731..858526845 100644 --- a/src/vsi.rs +++ b/src/vsi.rs @@ -5,7 +5,31 @@ use std::path::{Path, PathBuf}; use gdal_sys::{VSIFCloseL, VSIFileFromMemBuffer, VSIFree, VSIGetMemFileBuffer, VSIUnlink}; use crate::errors::{GdalError, Result}; -use crate::utils::{_last_null_pointer_err, _path_to_c_string}; +use crate::utils::{_last_null_pointer_err, _path_to_c_string, _string_array}; + +/// Read the file names from a virtual file system with optional recursion. +pub fn read_dir>(path: P, recursive: bool) -> Result> { + _read_dir(path.as_ref(), recursive) +} + +fn _read_dir(path: &Path, recursive: bool) -> Result> { + let path = _path_to_c_string(path)?; + let data = if recursive { + let data = unsafe { gdal_sys::VSIReadDirRecursive(path.as_ptr()) }; + if data.is_null() { + return Err(_last_null_pointer_err("VSIReadDirRecursive")); + } + data + } else { + let data = unsafe { gdal_sys::VSIReadDir(path.as_ptr()) }; + if data.is_null() { + return Err(_last_null_pointer_err("VSIReadDir")); + } + data + }; + + Ok(_string_array(data)) +} /// Creates a new VSIMemFile from a given buffer. pub fn create_mem_file>(file_name: P, data: Vec) -> Result<()> { @@ -277,4 +301,38 @@ mod tests { }) ); } + + #[test] + fn test_vsi_read_dir() { + use std::path::Path; + let zip_path = Path::new(file!()) + .parent() + .unwrap() + .parent() + .unwrap() + .join("fixtures") + .join("test_vsi_read_dir.zip"); + + // Concatenate "/vsizip/" prefix. + let path = ["/vsizip/", zip_path.to_str().unwrap()].concat(); + + // Read without recursion. + let expected = ["folder", "File 1.txt", "File 2.txt", "File 3.txt"]; + let files = read_dir(path.as_str(), false).unwrap(); + assert_eq!(files, expected); + + // Read with recursion. + let expected = [ + "folder/", + "folder/File 4.txt", + "File 1.txt", + "File 2.txt", + "File 3.txt", + ]; + let files = read_dir(path.as_str(), true).unwrap(); + assert_eq!(files, expected); + + // Attempting to read without VSI prefix returns error. + assert!(read_dir(zip_path, false).is_err()); + } } From 59e705f4cf20a82188e1aa9e19335e52e6fc87b1 Mon Sep 17 00:00:00 2001 From: Barugon Date: Fri, 13 May 2022 01:03:14 -0700 Subject: [PATCH 2/5] Return vector of BathBuf --- src/vsi.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/vsi.rs b/src/vsi.rs index 858526845..cfc1a2e63 100644 --- a/src/vsi.rs +++ b/src/vsi.rs @@ -8,11 +8,11 @@ use crate::errors::{GdalError, Result}; use crate::utils::{_last_null_pointer_err, _path_to_c_string, _string_array}; /// Read the file names from a virtual file system with optional recursion. -pub fn read_dir>(path: P, recursive: bool) -> Result> { +pub fn read_dir>(path: P, recursive: bool) -> Result> { _read_dir(path.as_ref(), recursive) } -fn _read_dir(path: &Path, recursive: bool) -> Result> { +fn _read_dir(path: &Path, recursive: bool) -> Result> { let path = _path_to_c_string(path)?; let data = if recursive { let data = unsafe { gdal_sys::VSIReadDirRecursive(path.as_ptr()) }; @@ -28,7 +28,14 @@ fn _read_dir(path: &Path, recursive: bool) -> Result> { data }; - Ok(_string_array(data)) + let strings = _string_array(data); + let mut paths = Vec::new(); + paths.reserve(strings.len()); + for string in strings { + paths.push(string.into()); + } + + Ok(paths) } /// Creates a new VSIMemFile from a given buffer. @@ -317,17 +324,22 @@ mod tests { let path = ["/vsizip/", zip_path.to_str().unwrap()].concat(); // Read without recursion. - let expected = ["folder", "File 1.txt", "File 2.txt", "File 3.txt"]; + let expected = [ + Path::new("folder"), + Path::new("File 1.txt"), + Path::new("File 2.txt"), + Path::new("File 3.txt"), + ]; let files = read_dir(path.as_str(), false).unwrap(); assert_eq!(files, expected); // Read with recursion. let expected = [ - "folder/", - "folder/File 4.txt", - "File 1.txt", - "File 2.txt", - "File 3.txt", + Path::new("folder/"), + Path::new("folder/File 4.txt"), + Path::new("File 1.txt"), + Path::new("File 2.txt"), + Path::new("File 3.txt"), ]; let files = read_dir(path.as_str(), true).unwrap(); assert_eq!(files, expected); From 0ae8d4f72253b6cfab5f74f98083aeadd22ae354 Mon Sep 17 00:00:00 2001 From: Barugon Date: Fri, 13 May 2022 08:57:44 -0700 Subject: [PATCH 3/5] Implement _pathbuf and _pathbuf_array functions --- src/utils.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 2d9cebb28..eff4bcd7f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use gdal_sys::{self, CPLErr}; use libc::c_char; use std::ffi::{CStr, CString}; -use std::path::Path; +use std::path::{Path, PathBuf}; use crate::errors::*; @@ -11,7 +11,23 @@ pub fn _string(raw_ptr: *const c_char) -> String { } pub fn _string_array(raw_ptr: *mut *mut c_char) -> Vec { - let mut ret_val: Vec = vec![]; + _convert_raw_ptr_array(raw_ptr, _string) +} + +pub fn _pathbuf(raw_ptr: *const c_char) -> PathBuf { + let c_str = unsafe { CStr::from_ptr(raw_ptr) }; + c_str.to_string_lossy().into_owned().into() +} + +pub fn _pathbuf_array(raw_ptr: *mut *mut c_char) -> Vec { + _convert_raw_ptr_array(raw_ptr, _pathbuf) +} + +fn _convert_raw_ptr_array(raw_ptr: *mut *mut c_char, convert: F) -> Vec +where + F: Fn(*const c_char) -> R, +{ + let mut ret_val: Vec = vec![]; let mut i = 0; unsafe { loop { @@ -23,7 +39,7 @@ pub fn _string_array(raw_ptr: *mut *mut c_char) -> Vec { if next.is_null() { break; } - let value = _string(next); + let value = convert(next); i += 1; ret_val.push(value); } From f38ca446d2a78282b305e73d0bd87a0039838e59 Mon Sep 17 00:00:00 2001 From: Barugon Date: Fri, 13 May 2022 08:58:56 -0700 Subject: [PATCH 4/5] Use _pathbuf_array --- src/vsi.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/vsi.rs b/src/vsi.rs index cfc1a2e63..b31038dcf 100644 --- a/src/vsi.rs +++ b/src/vsi.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use gdal_sys::{VSIFCloseL, VSIFileFromMemBuffer, VSIFree, VSIGetMemFileBuffer, VSIUnlink}; use crate::errors::{GdalError, Result}; -use crate::utils::{_last_null_pointer_err, _path_to_c_string, _string_array}; +use crate::utils::{_last_null_pointer_err, _path_to_c_string, _pathbuf_array}; /// Read the file names from a virtual file system with optional recursion. pub fn read_dir>(path: P, recursive: bool) -> Result> { @@ -28,14 +28,7 @@ fn _read_dir(path: &Path, recursive: bool) -> Result> { data }; - let strings = _string_array(data); - let mut paths = Vec::new(); - paths.reserve(strings.len()); - for string in strings { - paths.push(string.into()); - } - - Ok(paths) + Ok(_pathbuf_array(data)) } /// Creates a new VSIMemFile from a given buffer. From 50dfac8b3ce67c04e3242e6acee5521984da56c7 Mon Sep 17 00:00:00 2001 From: Barugon Date: Fri, 13 May 2022 10:18:25 -0700 Subject: [PATCH 5/5] Use Vec::new --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index eff4bcd7f..ff19695b4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,7 +27,7 @@ fn _convert_raw_ptr_array(raw_ptr: *mut *mut c_char, convert: F) -> Vec where F: Fn(*const c_char) -> R, { - let mut ret_val: Vec = vec![]; + let mut ret_val = Vec::new(); let mut i = 0; unsafe { loop {