Skip to content

Commit

Permalink
Merge #257
Browse files Browse the repository at this point in the history
257: Implement read_dir function and test r=lnicola a=Barugon

Implement a `gdal::vsi::read_dir` function and test.

- [x] I agree to follow the project's [code of conduct](https://github.com/georust/gdal/blob/master/CODE_OF_CONDUCT.md).
- [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---



Co-authored-by: Barugon <barugon@dungeonbox.net>
  • Loading branch information
bors[bot] and Barugon authored May 13, 2022
2 parents d8aa19a + 50dfac8 commit b0ebd1d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

- <https://github.com/georust/gdal/pull/271>

- Add `gdal::vsi::read_dir` function.

- <https://github.com/georust/gdal/pull/257>

## 0.12

- Bump Rust edition to 2021
Expand Down
Binary file added fixtures/test_vsi_read_dir.zip
Binary file not shown.
22 changes: 19 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand All @@ -11,7 +11,23 @@ pub fn _string(raw_ptr: *const c_char) -> String {
}

pub fn _string_array(raw_ptr: *mut *mut c_char) -> Vec<String> {
let mut ret_val: Vec<String> = 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<PathBuf> {
_convert_raw_ptr_array(raw_ptr, _pathbuf)
}

fn _convert_raw_ptr_array<F, R>(raw_ptr: *mut *mut c_char, convert: F) -> Vec<R>
where
F: Fn(*const c_char) -> R,
{
let mut ret_val = Vec::new();
let mut i = 0;
unsafe {
loop {
Expand All @@ -23,7 +39,7 @@ pub fn _string_array(raw_ptr: *mut *mut c_char) -> Vec<String> {
if next.is_null() {
break;
}
let value = _string(next);
let value = convert(next);
i += 1;
ret_val.push(value);
}
Expand Down
65 changes: 64 additions & 1 deletion src/vsi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, _pathbuf_array};

/// Read the file names from a virtual file system with optional recursion.
pub fn read_dir<P: AsRef<Path>>(path: P, recursive: bool) -> Result<Vec<PathBuf>> {
_read_dir(path.as_ref(), recursive)
}

fn _read_dir(path: &Path, recursive: bool) -> Result<Vec<PathBuf>> {
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(_pathbuf_array(data))
}

/// Creates a new VSIMemFile from a given buffer.
pub fn create_mem_file<P: AsRef<Path>>(file_name: P, data: Vec<u8>) -> Result<()> {
Expand Down Expand Up @@ -277,4 +301,43 @@ 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 = [
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 = [
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);

// Attempting to read without VSI prefix returns error.
assert!(read_dir(zip_path, false).is_err());
}
}

0 comments on commit b0ebd1d

Please sign in to comment.