diff --git a/CHANGES.md b/CHANGES.md index 20f56fad3..5e55113da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -34,10 +34,14 @@ - -- Exposed various functions on `Geometry`: `make_valid`, `geometry_name`, and `point_count`. - +- Exposed various functions on `Geometry`: `make_valid`, `geometry_name`, and `point_count`. + - +- Exposed `read_arrow_stream` on `Layer` to access OGR's columnar reading API. + + - + ## 0.14 - Added new content to `README.md` and the root docs. diff --git a/Cargo.toml b/Cargo.toml index 6fd1dd6e9..05636c6c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,8 @@ semver = "1.0" [dev-dependencies] tempfile = "3.3" +# Only used in the example +arrow2 = "0.15" [workspace] members = ["gdal-sys"] diff --git a/examples/read_ogr_arrow.rs b/examples/read_ogr_arrow.rs new file mode 100644 index 000000000..42596a7d0 --- /dev/null +++ b/examples/read_ogr_arrow.rs @@ -0,0 +1,102 @@ +//! Example of reading from OGR to a stream of Arrow arrays +//! +//! As of this writing (Feb 2023), there are two competing low-level Arrow libraries in Rust. +//! [`arrow-rs`](https://github.com/apache/arrow-rs) is the "official" one but uses unsafe +//! transmutes. [`arrow2`](https://github.com/jorgecarleitao/arrow2) was written to be a fully safe +//! implementation of Arrow. +//! +//! Each library implements the same Arrow memory standard, and each implements the +//! ArrowArrayStream interface, so each can integrate with the GDAL `read_arrow_stream` API. +//! +//! This example will use `arrow2` but the process should be similar using `arrow-rs`. + +#[cfg(any(major_ge_4, all(major_is_3, minor_ge_6)))] +fn run() -> gdal::errors::Result<()> { + use arrow2::array::{BinaryArray, StructArray}; + use arrow2::datatypes::DataType; + use gdal::cpl::CslStringList; + use gdal::vector::*; + use gdal::Dataset; + use std::path::Path; + + // Open a dataset and access a layer + let dataset_a = Dataset::open(Path::new("fixtures/roads.geojson"))?; + let mut layer_a = dataset_a.layer(0)?; + + // Instantiate an `ArrowArrayStream` for OGR to write into + let mut output_stream = Box::new(arrow2::ffi::ArrowArrayStream::empty()); + + // Access the unboxed pointer + let output_stream_ptr = &mut *output_stream as *mut arrow2::ffi::ArrowArrayStream; + + // gdal includes its own copy of the ArrowArrayStream struct definition. These are guaranteed + // to be the same across implementations, but we need to manually cast between the two for Rust + // to allow it. + let gdal_pointer: *mut gdal::ArrowArrayStream = output_stream_ptr.cast(); + + let mut options = CslStringList::new(); + options.set_name_value("INCLUDE_FID", "NO")?; + + // Read the layer's data into our provisioned pointer + unsafe { layer_a.read_arrow_stream(gdal_pointer, &options).unwrap() } + + // The rest of this example is arrow2-specific. + + // `arrow2` has a helper class `ArrowArrayStreamReader` to assist with iterating over the raw + // batches + let mut arrow_stream_reader = + unsafe { arrow2::ffi::ArrowArrayStreamReader::try_new(output_stream).unwrap() }; + + // Iterate over the stream until it's finished + // arrow_stream_reader.next() will return None when the stream has no more data + while let Some(maybe_array) = unsafe { arrow_stream_reader.next() } { + // Access the contained array + let top_level_array = maybe_array.unwrap(); + + // The top-level array is a single logical "struct" array which includes all columns of the + // dataset inside it. + assert!( + matches!(top_level_array.data_type(), DataType::Struct(..)), + "Top-level arrays from OGR are expected to be of struct type" + ); + + // Downcast from the Box to a concrete StructArray + let struct_array = top_level_array + .as_any() + .downcast_ref::() + .unwrap(); + + // Access the underlying column metadata and data + // Clones are cheap because they do not copy the underlying data + let (fields, columns, _validity) = struct_array.clone().into_data(); + + // Find the index of the geometry column + let geom_column_index = fields + .iter() + .position(|field| field.name == "wkb_geometry") + .unwrap(); + + // Pick that column and downcast to a BinaryArray + let geom_column = &columns[geom_column_index]; + let binary_array = geom_column + .as_any() + .downcast_ref::>() + .unwrap(); + + // Access the first row as WKB + let _wkb_buffer = binary_array.value(0); + + println!("Number of geometries: {}", binary_array.len()); + } + + Ok(()) +} + +#[cfg(not(any(major_ge_4, all(major_is_3, minor_ge_6))))] +fn run() -> gdal::errors::Result<()> { + Ok(()) +} + +fn main() { + run().unwrap(); +} diff --git a/gdal-sys/prebuilt-bindings/gdal_3.6.rs b/gdal-sys/prebuilt-bindings/gdal_3.6.rs index a65843802..87a340d81 100644 --- a/gdal-sys/prebuilt-bindings/gdal_3.6.rs +++ b/gdal-sys/prebuilt-bindings/gdal_3.6.rs @@ -1,290 +1,309 @@ /* automatically generated by rust-bindgen 0.63.0 */ -pub type va_list = __builtin_va_list; -pub type __dev_t = libc::c_ulong; -pub type __uid_t = libc::c_uint; -pub type __gid_t = libc::c_uint; -pub type __ino_t = libc::c_ulong; -pub type __mode_t = libc::c_uint; -pub type __nlink_t = libc::c_ulong; -pub type __off_t = libc::c_long; -pub type __off64_t = libc::c_long; -pub type __time_t = libc::c_long; -pub type __blksize_t = libc::c_long; -pub type __blkcnt_t = libc::c_long; -pub type __syscall_slong_t = libc::c_long; -pub type FILE = _IO_FILE; +pub type __uint16_t = libc::c_ushort; +pub type __int32_t = libc::c_int; +pub type __uint32_t = libc::c_uint; +pub type __int64_t = libc::c_longlong; +pub type __uint64_t = libc::c_ulonglong; +pub type __darwin_va_list = __builtin_va_list; +pub type __darwin_wchar_t = libc::c_int; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_blkcnt_t = __int64_t; +pub type __darwin_blksize_t = __int32_t; +pub type __darwin_dev_t = __int32_t; +pub type __darwin_gid_t = __uint32_t; +pub type __darwin_ino64_t = __uint64_t; +pub type __darwin_mode_t = __uint16_t; +pub type __darwin_off_t = __int64_t; +pub type __darwin_uid_t = __uint32_t; +pub type va_list = __darwin_va_list; +pub type fpos_t = __darwin_off_t; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct _IO_marker { - _unused: [u8; 0], +pub struct __sbuf { + pub _base: *mut libc::c_uchar, + pub _size: libc::c_int, } -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _IO_codecvt { - _unused: [u8; 0], +#[test] +fn bindgen_test_layout___sbuf() { + const UNINIT: ::std::mem::MaybeUninit<__sbuf> = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::<__sbuf>(), + 16usize, + concat!("Size of: ", stringify!(__sbuf)) + ); + assert_eq!( + ::std::mem::align_of::<__sbuf>(), + 8usize, + concat!("Alignment of ", stringify!(__sbuf)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._base) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__sbuf), + "::", + stringify!(_base) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._size) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(__sbuf), + "::", + stringify!(_size) + ) + ); } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct _IO_wide_data { +pub struct __sFILEX { _unused: [u8; 0], } -pub type _IO_lock_t = libc::c_void; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct _IO_FILE { - pub _flags: libc::c_int, - pub _IO_read_ptr: *mut libc::c_char, - pub _IO_read_end: *mut libc::c_char, - pub _IO_read_base: *mut libc::c_char, - pub _IO_write_base: *mut libc::c_char, - pub _IO_write_ptr: *mut libc::c_char, - pub _IO_write_end: *mut libc::c_char, - pub _IO_buf_base: *mut libc::c_char, - pub _IO_buf_end: *mut libc::c_char, - pub _IO_save_base: *mut libc::c_char, - pub _IO_backup_base: *mut libc::c_char, - pub _IO_save_end: *mut libc::c_char, - pub _markers: *mut _IO_marker, - pub _chain: *mut _IO_FILE, - pub _fileno: libc::c_int, - pub _flags2: libc::c_int, - pub _old_offset: __off_t, - pub _cur_column: libc::c_ushort, - pub _vtable_offset: libc::c_schar, - pub _shortbuf: [libc::c_char; 1usize], - pub _lock: *mut _IO_lock_t, - pub _offset: __off64_t, - pub _codecvt: *mut _IO_codecvt, - pub _wide_data: *mut _IO_wide_data, - pub _freeres_list: *mut _IO_FILE, - pub _freeres_buf: *mut libc::c_void, - pub __pad5: usize, - pub _mode: libc::c_int, - pub _unused2: [libc::c_char; 20usize], +pub struct __sFILE { + pub _p: *mut libc::c_uchar, + pub _r: libc::c_int, + pub _w: libc::c_int, + pub _flags: libc::c_short, + pub _file: libc::c_short, + pub _bf: __sbuf, + pub _lbfsize: libc::c_int, + pub _cookie: *mut libc::c_void, + pub _close: ::std::option::Option libc::c_int>, + pub _read: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut libc::c_void, + arg2: *mut libc::c_char, + arg3: libc::c_int, + ) -> libc::c_int, + >, + pub _seek: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut libc::c_void, arg2: fpos_t, arg3: libc::c_int) -> fpos_t, + >, + pub _write: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut libc::c_void, + arg2: *const libc::c_char, + arg3: libc::c_int, + ) -> libc::c_int, + >, + pub _ub: __sbuf, + pub _extra: *mut __sFILEX, + pub _ur: libc::c_int, + pub _ubuf: [libc::c_uchar; 3usize], + pub _nbuf: [libc::c_uchar; 1usize], + pub _lb: __sbuf, + pub _blksize: libc::c_int, + pub _offset: fpos_t, } #[test] -fn bindgen_test_layout__IO_FILE() { - const UNINIT: ::std::mem::MaybeUninit<_IO_FILE> = ::std::mem::MaybeUninit::uninit(); +fn bindgen_test_layout___sFILE() { + const UNINIT: ::std::mem::MaybeUninit<__sFILE> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::<_IO_FILE>(), - 216usize, - concat!("Size of: ", stringify!(_IO_FILE)) + ::std::mem::size_of::<__sFILE>(), + 152usize, + concat!("Size of: ", stringify!(__sFILE)) ); assert_eq!( - ::std::mem::align_of::<_IO_FILE>(), + ::std::mem::align_of::<__sFILE>(), 8usize, - concat!("Alignment of ", stringify!(_IO_FILE)) + concat!("Alignment of ", stringify!(__sFILE)) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._flags) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._p) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_flags) + stringify!(_p) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_read_ptr) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._r) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), + "::", + stringify!(_r) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._w) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(__sFILE), "::", - stringify!(_IO_read_ptr) + stringify!(_w) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_read_end) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._flags) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_read_end) + stringify!(_flags) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_read_base) as usize - ptr as usize }, - 24usize, + unsafe { ::std::ptr::addr_of!((*ptr)._file) as usize - ptr as usize }, + 18usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_read_base) + stringify!(_file) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_write_base) as usize - ptr as usize }, - 32usize, + unsafe { ::std::ptr::addr_of!((*ptr)._bf) as usize - ptr as usize }, + 24usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_write_base) + stringify!(_bf) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_write_ptr) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._lbfsize) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_write_ptr) + stringify!(_lbfsize) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_write_end) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._cookie) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_write_end) + stringify!(_cookie) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_buf_base) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._close) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_buf_base) + stringify!(_close) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_buf_end) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._read) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_buf_end) + stringify!(_read) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_save_base) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._seek) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_save_base) + stringify!(_seek) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_backup_base) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._write) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_IO_backup_base) + stringify!(_write) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._IO_save_end) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._ub) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_save_end) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._markers) as usize - ptr as usize }, - 96usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_markers) + stringify!(_ub) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._chain) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._extra) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_chain) + stringify!(_extra) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._fileno) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._ur) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_fileno) + stringify!(_ur) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._flags2) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._ubuf) as usize - ptr as usize }, 116usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_flags2) + stringify!(_ubuf) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._old_offset) as usize - ptr as usize }, - 120usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_old_offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._cur_column) as usize - ptr as usize }, - 128usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_cur_column) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._vtable_offset) as usize - ptr as usize }, - 130usize, + unsafe { ::std::ptr::addr_of!((*ptr)._nbuf) as usize - ptr as usize }, + 119usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_vtable_offset) + stringify!(_nbuf) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._shortbuf) as usize - ptr as usize }, - 131usize, + unsafe { ::std::ptr::addr_of!((*ptr)._lb) as usize - ptr as usize }, + 120usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_shortbuf) + stringify!(_lb) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._lock) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr)._blksize) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", - stringify!(_lock) + stringify!(_blksize) ) ); assert_eq!( @@ -292,89 +311,24 @@ fn bindgen_test_layout__IO_FILE() { 144usize, concat!( "Offset of field: ", - stringify!(_IO_FILE), + stringify!(__sFILE), "::", stringify!(_offset) ) ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._codecvt) as usize - ptr as usize }, - 152usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_codecvt) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._wide_data) as usize - ptr as usize }, - 160usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_wide_data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._freeres_list) as usize - ptr as usize }, - 168usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_freeres_list) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._freeres_buf) as usize - ptr as usize }, - 176usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_freeres_buf) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).__pad5) as usize - ptr as usize }, - 184usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad5) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._mode) as usize - ptr as usize }, - 192usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_mode) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._unused2) as usize - ptr as usize }, - 196usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_unused2) - ) - ); } -pub type wchar_t = libc::c_int; -pub type time_t = __time_t; +pub type FILE = __sFILE; +pub type off_t = __darwin_off_t; +pub type uid_t = __darwin_uid_t; +pub type wchar_t = __darwin_wchar_t; +pub type dev_t = __darwin_dev_t; +pub type mode_t = __darwin_mode_t; +pub type time_t = __darwin_time_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timespec { - pub tv_sec: __time_t, - pub tv_nsec: __syscall_slong_t, + pub tv_sec: __darwin_time_t, + pub tv_nsec: libc::c_long, } #[test] fn bindgen_test_layout_timespec() { @@ -424,7 +378,7 @@ pub struct tm { pub tm_yday: libc::c_int, pub tm_isdst: libc::c_int, pub tm_gmtoff: libc::c_long, - pub tm_zone: *const libc::c_char, + pub tm_zone: *mut libc::c_char, } #[test] fn bindgen_test_layout_tm() { @@ -576,7 +530,7 @@ extern "C" { pub fn CPLAtomicAdd(ptr: *mut libc::c_int, increment: libc::c_int) -> libc::c_int; } extern "C" { - #[doc = " Compares *ptr with oldval. If *ptr == oldval, then *ptr is assigned\n newval and TRUE is returned. Otherwise nothing is done, and FALSE is returned.\n\n Current platforms/architectures where an efficient implementation\n exists are MacOSX, MS Windows, i386/x86_64 with GCC and platforms\n supported by GCC 4.1 or higher. For other platforms supporting\n the pthread library, and when GDAL is configured with thread-support,\n the atomicity will be done with a mutex, but with\n reduced efficiency. For the remaining platforms, a simple compare and\n exchange with no locking will be done...\n\n @param ptr a pointer to an integer (aligned on 32bit boundary).\n @param oldval old value\n @param newval new value\n @return TRUE if the exchange has been done"] + #[doc = " Compares *ptr with oldval. If *ptr == oldval, then *ptr is assigned\n newval and TRUE is returned. Otherwise nothing is done, and FALSE is\n returned.\n\n Current platforms/architectures where an efficient implementation\n exists are MacOSX, MS Windows, i386/x86_64 with GCC and platforms\n supported by GCC 4.1 or higher. For other platforms supporting\n the pthread library, and when GDAL is configured with thread-support,\n the atomicity will be done with a mutex, but with\n reduced efficiency. For the remaining platforms, a simple compare and\n exchange with no locking will be done...\n\n @param ptr a pointer to an integer (aligned on 32bit boundary).\n @param oldval old value\n @param newval new value\n @return TRUE if the exchange has been done"] pub fn CPLAtomicCompareAndExchange( ptr: *mut libc::c_int, oldval: libc::c_int, @@ -622,24 +576,31 @@ extern "C" { extern "C" { pub fn GDALDestroyScaledProgress(arg1: *mut libc::c_void); } +pub type gid_t = __darwin_gid_t; +pub type blkcnt_t = __darwin_blkcnt_t; +pub type blksize_t = __darwin_blksize_t; +pub type nlink_t = __uint16_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct stat { - pub st_dev: __dev_t, - pub st_ino: __ino_t, - pub st_nlink: __nlink_t, - pub st_mode: __mode_t, - pub st_uid: __uid_t, - pub st_gid: __gid_t, - pub __pad0: libc::c_int, - pub st_rdev: __dev_t, - pub st_size: __off_t, - pub st_blksize: __blksize_t, - pub st_blocks: __blkcnt_t, - pub st_atim: timespec, - pub st_mtim: timespec, - pub st_ctim: timespec, - pub __glibc_reserved: [__syscall_slong_t; 3usize], + pub st_dev: dev_t, + pub st_mode: mode_t, + pub st_nlink: nlink_t, + pub st_ino: __darwin_ino64_t, + pub st_uid: uid_t, + pub st_gid: gid_t, + pub st_rdev: dev_t, + pub st_atimespec: timespec, + pub st_mtimespec: timespec, + pub st_ctimespec: timespec, + pub st_birthtimespec: timespec, + pub st_size: off_t, + pub st_blocks: blkcnt_t, + pub st_blksize: blksize_t, + pub st_flags: __uint32_t, + pub st_gen: __uint32_t, + pub st_lspare: __int32_t, + pub st_qspare: [__int64_t; 2usize], } #[test] fn bindgen_test_layout_stat() { @@ -666,18 +627,18 @@ fn bindgen_test_layout_stat() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_ino) as usize - ptr as usize }, - 8usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_mode) as usize - ptr as usize }, + 4usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_ino) + stringify!(st_mode) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_nlink) as usize - ptr as usize }, - 16usize, + 6usize, concat!( "Offset of field: ", stringify!(stat), @@ -686,18 +647,18 @@ fn bindgen_test_layout_stat() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_mode) as usize - ptr as usize }, - 24usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_ino) as usize - ptr as usize }, + 8usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_mode) + stringify!(st_ino) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_uid) as usize - ptr as usize }, - 28usize, + 16usize, concat!( "Offset of field: ", stringify!(stat), @@ -707,7 +668,7 @@ fn bindgen_test_layout_stat() { ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_gid) as usize - ptr as usize }, - 32usize, + 20usize, concat!( "Offset of field: ", stringify!(stat), @@ -716,48 +677,68 @@ fn bindgen_test_layout_stat() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).__pad0) as usize - ptr as usize }, - 36usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_rdev) as usize - ptr as usize }, + 24usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(__pad0) + stringify!(st_rdev) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_rdev) as usize - ptr as usize }, - 40usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_atimespec) as usize - ptr as usize }, + 32usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_rdev) + stringify!(st_atimespec) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_size) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).st_mtimespec) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_size) + stringify!(st_mtimespec) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_blksize) as usize - ptr as usize }, - 56usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_ctimespec) as usize - ptr as usize }, + 64usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_blksize) + stringify!(st_ctimespec) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).st_birthtimespec) as usize - ptr as usize }, + 80usize, + concat!( + "Offset of field: ", + stringify!(stat), + "::", + stringify!(st_birthtimespec) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).st_size) as usize - ptr as usize }, + 96usize, + concat!( + "Offset of field: ", + stringify!(stat), + "::", + stringify!(st_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_blocks) as usize - ptr as usize }, - 64usize, + 104usize, concat!( "Offset of field: ", stringify!(stat), @@ -766,43 +747,53 @@ fn bindgen_test_layout_stat() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_atim) as usize - ptr as usize }, - 72usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_blksize) as usize - ptr as usize }, + 112usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_atim) + stringify!(st_blksize) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_mtim) as usize - ptr as usize }, - 88usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_flags) as usize - ptr as usize }, + 116usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_mtim) + stringify!(st_flags) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).st_ctim) as usize - ptr as usize }, - 104usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_gen) as usize - ptr as usize }, + 120usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(st_ctim) + stringify!(st_gen) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).__glibc_reserved) as usize - ptr as usize }, - 120usize, + unsafe { ::std::ptr::addr_of!((*ptr).st_lspare) as usize - ptr as usize }, + 124usize, concat!( "Offset of field: ", stringify!(stat), "::", - stringify!(__glibc_reserved) + stringify!(st_lspare) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).st_qspare) as usize - ptr as usize }, + 128usize, + concat!( + "Offset of field: ", + stringify!(stat), + "::", + stringify!(st_qspare) ) ); } @@ -968,13 +959,8 @@ extern "C" { pszSourceFilename: *const libc::c_char, ) -> libc::c_int; } -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct stat64 { - _unused: [u8; 0], -} #[doc = " Type for VSIStatL()"] -pub type VSIStatBufL = stat64; +pub type VSIStatBufL = stat; extern "C" { pub fn VSIStatL(arg1: *const libc::c_char, arg2: *mut VSIStatBufL) -> libc::c_int; } @@ -1109,7 +1095,7 @@ extern "C" { pub fn VSIMalloc2(nSize1: usize, nSize2: usize) -> *mut libc::c_void; } extern "C" { - #[doc = "VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.\nIn case of overflow of the multiplication, or if memory allocation fails, a\nNULL pointer is returned and a CE_Failure error is raised with CPLError().\nIf nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.\nCPLFree() or VSIFree() can be used to free memory allocated by this function."] + #[doc = "VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.\nIn case of overflow of the multiplication, or if memory allocation fails, a\nNULL pointer is returned and a CE_Failure error is raised with CPLError().\nIf nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be\nreturned. CPLFree() or VSIFree() can be used to free memory allocated by this\nfunction."] pub fn VSIMalloc3(nSize1: usize, nSize2: usize, nSize3: usize) -> *mut libc::c_void; } extern "C" { @@ -1533,14 +1519,14 @@ pub type VSIFilesystemPluginReadDirCallback = ::std::option::Option< nMaxFiles: libc::c_int, ) -> *mut *mut libc::c_char, >; -#[doc = " List related files. Must return NULL if unknown, or a list of relative filenames\n that can be opened along the main file. If no other file than pszFilename needs to\n be opened, return static_cast (CPLCalloc(1,sizeof(char*)));\n\n Optional\n @since GDAL 3.2"] +#[doc = " List related files. Must return NULL if unknown, or a list of relative\n filenames that can be opened along the main file. If no other file than\n pszFilename needs to be opened, return static_cast\n (CPLCalloc(1,sizeof(char*)));\n\n Optional\n @since GDAL 3.2"] pub type VSIFilesystemPluginSiblingFilesCallback = ::std::option::Option< unsafe extern "C" fn( pUserData: *mut libc::c_void, pszDirname: *const libc::c_char, ) -> *mut *mut libc::c_char, >; -#[doc = " Open a handle. Mandatory. Returns an opaque pointer that will be used in subsequent file I/O calls.\n Should return null and/or set errno if the handle does not exist or the access mode is incorrect.\n @since GDAL 3.0"] +#[doc = " Open a handle. Mandatory. Returns an opaque pointer that will be used in\n subsequent file I/O calls. Should return null and/or set errno if the handle\n does not exist or the access mode is incorrect.\n @since GDAL 3.0"] pub type VSIFilesystemPluginOpenCallback = ::std::option::Option< unsafe extern "C" fn( pUserData: *mut libc::c_void, @@ -1568,7 +1554,7 @@ pub type VSIFilesystemPluginReadCallback = ::std::option::Option< nCount: usize, ) -> usize, >; -#[doc = " Read from multiple offsets. Optional, will be replaced by multiple calls to Read() if not provided\n @since GDAL 3.0"] +#[doc = " Read from multiple offsets. Optional, will be replaced by multiple calls to\n Read() if not provided\n @since GDAL 3.0"] pub type VSIFilesystemPluginReadMultiRangeCallback = ::std::option::Option< unsafe extern "C" fn( pFile: *mut libc::c_void, @@ -1608,11 +1594,11 @@ pub type VSIFilesystemPluginTruncateCallback = ::std::option::Option< #[doc = " Close file handle. Optional\n @since GDAL 3.0"] pub type VSIFilesystemPluginCloseCallback = ::std::option::Option libc::c_int>; -#[doc = " struct containing callbacks to used by the handler.\n (rw), (r), (w) or () at the end indicate whether the given callback is mandatory\n for reading and or writing handlers. A (?) indicates that the callback might\n be mandatory for certain drivers only.\n @since GDAL 3.0"] +#[doc = " struct containing callbacks to used by the handler.\n (rw), (r), (w) or () at the end indicate whether the given callback is\n mandatory for reading and or writing handlers. A (?) indicates that the\n callback might be mandatory for certain drivers only.\n @since GDAL 3.0"] #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct VSIFilesystemPluginCallbacksStruct { - #[doc = " Optional opaque pointer passed back to filemanager callbacks (e.g. open, stat, rmdir)"] + #[doc = " Optional opaque pointer passed back to filemanager callbacks (e.g. open,\n stat, rmdir)"] pub pUserData: *mut libc::c_void, #[doc = "< stat handle by name (rw)"] pub stat: VSIFilesystemPluginStatCallback, @@ -1885,7 +1871,7 @@ fn bindgen_test_layout_VSIFilesystemPluginCallbacksStruct() { ); } extern "C" { - #[doc = " return a VSIFilesystemPluginCallbacksStruct to be populated at runtime with handler callbacks\n @since GDAL 3.0"] + #[doc = " return a VSIFilesystemPluginCallbacksStruct to be populated at runtime with\n handler callbacks\n @since GDAL 3.0"] pub fn VSIAllocFilesystemPluginCallbacksStruct() -> *mut VSIFilesystemPluginCallbacksStruct; } extern "C" { @@ -1893,7 +1879,7 @@ extern "C" { pub fn VSIFreeFilesystemPluginCallbacksStruct(poCb: *mut VSIFilesystemPluginCallbacksStruct); } extern "C" { - #[doc = " register a handler on the given prefix. All IO on datasets opened with the filename /prefix/xxxxxx\n will go through these callbacks.\n pszPrefix must begin and end with a '/'\n @since GDAL 3.0"] + #[doc = " register a handler on the given prefix. All IO on datasets opened with the\n filename /prefix/xxxxxx will go through these callbacks. pszPrefix must begin\n and end with a '/'\n @since GDAL 3.0"] pub fn VSIInstallPluginHandler( pszPrefix: *const libc::c_char, poCb: *const VSIFilesystemPluginCallbacksStruct, @@ -1931,7 +1917,7 @@ extern "C" { arg1: CPLErr::Type, arg2: CPLErrorNum, arg3: *const libc::c_char, - arg4: *mut __va_list_tag, + arg4: va_list, ); } extern "C" { @@ -2786,7 +2772,7 @@ extern "C" { str_: *mut libc::c_char, size: usize, fmt: *const libc::c_char, - args: *mut __va_list_tag, + args: va_list, ) -> libc::c_int; } extern "C" { @@ -2823,7 +2809,7 @@ extern "C" { pub fn CPLVASPrintf( buf: *mut *mut libc::c_char, fmt: *const libc::c_char, - args: *mut __va_list_tag, + args: va_list, ) -> libc::c_int; } extern "C" { @@ -3377,7 +3363,7 @@ extern "C" { pub struct CPLVirtualMem { _unused: [u8; 0], } -#[doc = " Callback triggered when a still unmapped page of virtual memory is accessed.\n The callback has the responsibility of filling the page with relevant values\n\n @param ctxt virtual memory handle.\n @param nOffset offset of the page in the memory mapping.\n @param pPageToFill address of the page to fill. Note that the address might\n be a temporary location, and not at CPLVirtualMemGetAddr() + nOffset.\n @param nToFill number of bytes of the page.\n @param pUserData user data that was passed to CPLVirtualMemNew()."] +#[doc = " Callback triggered when a still unmapped page of virtual memory is accessed.\n The callback has the responsibility of filling the page with relevant values\n\n @param ctxt virtual memory handle.\n @param nOffset offset of the page in the memory mapping.\n @param pPageToFill address of the page to fill. Note that the address might\n be a temporary location, and not at CPLVirtualMemGetAddr()\n + nOffset.\n @param nToFill number of bytes of the page.\n @param pUserData user data that was passed to CPLVirtualMemNew()."] pub type CPLVirtualMemCachePageCbk = ::std::option::Option< unsafe extern "C" fn( ctxt: *mut CPLVirtualMem, @@ -3387,7 +3373,7 @@ pub type CPLVirtualMemCachePageCbk = ::std::option::Option< pUserData: *mut libc::c_void, ), >; -#[doc = " Callback triggered when a dirty mapped page is going to be freed.\n (saturation of cache, or termination of the virtual memory mapping).\n\n @param ctxt virtual memory handle.\n @param nOffset offset of the page in the memory mapping.\n @param pPageToBeEvicted address of the page that will be flushed. Note that the address might\n be a temporary location, and not at CPLVirtualMemGetAddr() + nOffset.\n @param nToBeEvicted number of bytes of the page.\n @param pUserData user data that was passed to CPLVirtualMemNew()."] +#[doc = " Callback triggered when a dirty mapped page is going to be freed.\n (saturation of cache, or termination of the virtual memory mapping).\n\n @param ctxt virtual memory handle.\n @param nOffset offset of the page in the memory mapping.\n @param pPageToBeEvicted address of the page that will be flushed. Note that\n the address might be a temporary location, and not at CPLVirtualMemGetAddr()\n + nOffset.\n @param nToBeEvicted number of bytes of the page.\n @param pUserData user data that was passed to CPLVirtualMemNew()."] pub type CPLVirtualMemUnCachePageCbk = ::std::option::Option< unsafe extern "C" fn( ctxt: *mut CPLVirtualMem, @@ -3403,11 +3389,11 @@ pub type CPLVirtualMemFreeUserData = pub mod CPLVirtualMemAccessMode { #[doc = " Access mode of a virtual memory mapping."] pub type Type = libc::c_uint; - #[doc = " The mapping is meant at being read-only, but writes will not be prevented.\nNote that any content written will be lost."] + #[doc = " The mapping is meant at being read-only, but writes will not be\nprevented. Note that any content written will be lost."] pub const VIRTUALMEM_READONLY: Type = 0; #[doc = " The mapping is meant at being read-only, and this will be enforced\nthrough the operating system page protection mechanism."] pub const VIRTUALMEM_READONLY_ENFORCED: Type = 1; - #[doc = " The mapping is meant at being read-write, and modified pages can be saved\nthanks to the pfnUnCachePage callback"] + #[doc = " The mapping is meant at being read-write, and modified pages can be\nsaved thanks to the pfnUnCachePage callback"] pub const VIRTUALMEM_READWRITE: Type = 2; } extern "C" { @@ -3415,7 +3401,7 @@ extern "C" { pub fn CPLGetPageSize() -> usize; } extern "C" { - #[doc = " Create a new virtual memory mapping.\n\n This will reserve an area of virtual memory of size nSize, whose size\n might be potentially much larger than the physical memory available. Initially,\n no physical memory will be allocated. As soon as memory pages will be accessed,\n they will be allocated transparently and filled with the pfnCachePage callback.\n When the allowed cache size is reached, the least recently used pages will\n be unallocated.\n\n On Linux AMD64 platforms, the maximum value for nSize is 128 TB.\n On Linux x86 platforms, the maximum value for nSize is 2 GB.\n\n Only supported on Linux for now.\n\n Note that on Linux, this function will install a SIGSEGV handler. The\n original handler will be restored by CPLVirtualMemManagerTerminate().\n\n @param nSize size in bytes of the virtual memory mapping.\n @param nCacheSize size in bytes of the maximum memory that will be really\n allocated (must ideally fit into RAM).\n @param nPageSizeHint hint for the page size. Must be a multiple of the\n system page size, returned by CPLGetPageSize().\n Minimum value is generally 4096. Might be set to 0 to\n let the function determine a default page size.\n @param bSingleThreadUsage set to TRUE if there will be no concurrent threads\n that will access the virtual memory mapping. This can\n optimize performance a bit.\n @param eAccessMode permission to use for the virtual memory mapping.\n @param pfnCachePage callback triggered when a still unmapped page of virtual\n memory is accessed. The callback has the responsibility\n of filling the page with relevant values.\n @param pfnUnCachePage callback triggered when a dirty mapped page is going to\n be freed (saturation of cache, or termination of the\n virtual memory mapping). Might be NULL.\n @param pfnFreeUserData callback that can be used to free pCbkUserData. Might be\n NULL\n @param pCbkUserData user data passed to pfnCachePage and pfnUnCachePage.\n\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] + #[doc = " Create a new virtual memory mapping.\n\n This will reserve an area of virtual memory of size nSize, whose size\n might be potentially much larger than the physical memory available.\n Initially, no physical memory will be allocated. As soon as memory pages will\n be accessed, they will be allocated transparently and filled with the\n pfnCachePage callback. When the allowed cache size is reached, the least\n recently used pages will be unallocated.\n\n On Linux AMD64 platforms, the maximum value for nSize is 128 TB.\n On Linux x86 platforms, the maximum value for nSize is 2 GB.\n\n Only supported on Linux for now.\n\n Note that on Linux, this function will install a SIGSEGV handler. The\n original handler will be restored by CPLVirtualMemManagerTerminate().\n\n @param nSize size in bytes of the virtual memory mapping.\n @param nCacheSize size in bytes of the maximum memory that will be really\n allocated (must ideally fit into RAM).\n @param nPageSizeHint hint for the page size. Must be a multiple of the\n system page size, returned by CPLGetPageSize().\n Minimum value is generally 4096. Might be set to 0 to\n let the function determine a default page size.\n @param bSingleThreadUsage set to TRUE if there will be no concurrent threads\n that will access the virtual memory mapping. This\n can optimize performance a bit.\n @param eAccessMode permission to use for the virtual memory mapping.\n @param pfnCachePage callback triggered when a still unmapped page of virtual\n memory is accessed. The callback has the responsibility\n of filling the page with relevant values.\n @param pfnUnCachePage callback triggered when a dirty mapped page is going to\n be freed (saturation of cache, or termination of the\n virtual memory mapping). Might be NULL.\n @param pfnFreeUserData callback that can be used to free pCbkUserData. Might\n be NULL\n @param pCbkUserData user data passed to pfnCachePage and pfnUnCachePage.\n\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] pub fn CPLVirtualMemNew( nSize: usize, nCacheSize: usize, @@ -3433,7 +3419,7 @@ extern "C" { pub fn CPLIsVirtualMemFileMapAvailable() -> libc::c_int; } extern "C" { - #[doc = " Create a new virtual memory mapping from a file.\n\n The file must be a \"real\" file recognized by the operating system, and not\n a VSI extended virtual file.\n\n In VIRTUALMEM_READWRITE mode, updates to the memory mapping will be written\n in the file.\n\n On Linux AMD64 platforms, the maximum value for nLength is 128 TB.\n On Linux x86 platforms, the maximum value for nLength is 2 GB.\n\n Supported on Linux only in GDAL <= 2.0, and all POSIX systems supporting\n mmap() in GDAL >= 2.1\n\n @param fp Virtual file handle.\n @param nOffset Offset in the file to start the mapping from.\n @param nLength Length of the portion of the file to map into memory.\n @param eAccessMode Permission to use for the virtual memory mapping. This must\n be consistent with how the file has been opened.\n @param pfnFreeUserData callback that is called when the object is destroyed.\n @param pCbkUserData user data passed to pfnFreeUserData.\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] + #[doc = " Create a new virtual memory mapping from a file.\n\n The file must be a \"real\" file recognized by the operating system, and not\n a VSI extended virtual file.\n\n In VIRTUALMEM_READWRITE mode, updates to the memory mapping will be written\n in the file.\n\n On Linux AMD64 platforms, the maximum value for nLength is 128 TB.\n On Linux x86 platforms, the maximum value for nLength is 2 GB.\n\n Supported on Linux only in GDAL <= 2.0, and all POSIX systems supporting\n mmap() in GDAL >= 2.1\n\n @param fp Virtual file handle.\n @param nOffset Offset in the file to start the mapping from.\n @param nLength Length of the portion of the file to map into memory.\n @param eAccessMode Permission to use for the virtual memory mapping. This\n must be consistent with how the file has been opened.\n @param pfnFreeUserData callback that is called when the object is destroyed.\n @param pCbkUserData user data passed to pfnFreeUserData.\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] pub fn CPLVirtualMemFileMapNew( fp: *mut VSILFILE, nOffset: vsi_l_offset, @@ -3444,7 +3430,7 @@ extern "C" { ) -> *mut CPLVirtualMem; } extern "C" { - #[doc = " Create a new virtual memory mapping derived from an other virtual memory\n mapping.\n\n This may be useful in case of creating mapping for pixel interleaved data.\n\n The new mapping takes a reference on the base mapping.\n\n @param pVMemBase Base virtual memory mapping\n @param nOffset Offset in the base virtual memory mapping from which to start\n the new mapping.\n @param nSize Size of the base virtual memory mapping to expose in the\n the new mapping.\n @param pfnFreeUserData callback that is called when the object is destroyed.\n @param pCbkUserData user data passed to pfnFreeUserData.\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] + #[doc = " Create a new virtual memory mapping derived from an other virtual memory\n mapping.\n\n This may be useful in case of creating mapping for pixel interleaved data.\n\n The new mapping takes a reference on the base mapping.\n\n @param pVMemBase Base virtual memory mapping\n @param nOffset Offset in the base virtual memory mapping from which to\n start the new mapping.\n @param nSize Size of the base virtual memory mapping to expose in the\n the new mapping.\n @param pfnFreeUserData callback that is called when the object is destroyed.\n @param pCbkUserData user data passed to pfnFreeUserData.\n @return a virtual memory object that must be freed by CPLVirtualMemFree(),\n or NULL in case of failure.\n\n @since GDAL 1.11"] pub fn CPLVirtualMemDerivedNew( pVMemBase: *mut CPLVirtualMem, nOffset: vsi_l_offset, @@ -3454,7 +3440,7 @@ extern "C" { ) -> *mut CPLVirtualMem; } extern "C" { - #[doc = " Free a virtual memory mapping.\n\n The pointer returned by CPLVirtualMemGetAddr() will no longer be valid.\n If the virtual memory mapping was created with read/write permissions and that\n they are dirty (i.e. modified) pages, they will be flushed through the\n pfnUnCachePage callback before being freed.\n\n @param ctxt context returned by CPLVirtualMemNew().\n\n @since GDAL 1.11"] + #[doc = " Free a virtual memory mapping.\n\n The pointer returned by CPLVirtualMemGetAddr() will no longer be valid.\n If the virtual memory mapping was created with read/write permissions and\n that they are dirty (i.e. modified) pages, they will be flushed through the\n pfnUnCachePage callback before being freed.\n\n @param ctxt context returned by CPLVirtualMemNew().\n\n @since GDAL 1.11"] pub fn CPLVirtualMemFree(ctxt: *mut CPLVirtualMem); } extern "C" { @@ -3679,27 +3665,23 @@ pub mod OGRwkbGeometryType { pub const wkbPolygon: Type = 3; #[doc = "< GeometryCollection of Points, standard WKB"] pub const wkbMultiPoint: Type = 4; - #[doc = "< GeometryCollection of LineStrings, standard WKB"] pub const wkbMultiLineString: Type = 5; #[doc = "< GeometryCollection of Polygons, standard WKB"] pub const wkbMultiPolygon: Type = 6; #[doc = "< geometric object that is a collection of 1\nor more geometric objects, standard WKB"] pub const wkbGeometryCollection: Type = 7; - #[doc = "< one or more circular arc segments connected end to end,\n ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< one or more circular arc segments connected end\n to end, ISO SQL/MM Part 3. GDAL >= 2.0"] pub const wkbCircularString: Type = 8; - #[doc = "< sequence of contiguous curves, ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< sequence of contiguous curves, ISO SQL/MM Part 3.\nGDAL >= 2.0"] pub const wkbCompoundCurve: Type = 9; - #[doc = "< planar surface, defined by 1 exterior boundary\n and zero or more interior boundaries, that are curves.\n ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< planar surface, defined by 1 exterior boundary\n and zero or more interior boundaries, that are\n curves. ISO SQL/MM Part 3. GDAL >= 2.0"] pub const wkbCurvePolygon: Type = 10; - #[doc = "< GeometryCollection of Curves, ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< GeometryCollection of Curves, ISO SQL/MM Part 3.\nGDAL >= 2.0"] pub const wkbMultiCurve: Type = 11; - #[doc = "< GeometryCollection of Surfaces, ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< GeometryCollection of Surfaces, ISO SQL/MM\nPart 3. GDAL >= 2.0"] pub const wkbMultiSurface: Type = 12; - #[doc = "< Curve (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1"] pub const wkbCurve: Type = 13; - #[doc = "< Surface (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1"] pub const wkbSurface: Type = 14; - #[doc = "< a contiguous collection of polygons, which share common boundary segments,\n ISO SQL/MM Part 3. GDAL >= 2.3"] pub const wkbPolyhedralSurface: Type = 15; #[doc = "< a PolyhedralSurface consisting only of Triangle patches\n ISO SQL/MM Part 3. GDAL >= 2.3"] pub const wkbTIN: Type = 16; @@ -3709,19 +3691,19 @@ pub mod OGRwkbGeometryType { pub const wkbNone: Type = 100; #[doc = "< non-standard, just for createGeometry()"] pub const wkbLinearRing: Type = 101; - #[doc = "< wkbCircularString with Z component. ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< wkbCircularString with Z component. ISO\nSQL/MM Part 3. GDAL >= 2.0"] pub const wkbCircularStringZ: Type = 1008; - #[doc = "< wkbCompoundCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< wkbCompoundCurve with Z component. ISO SQL/MM\nPart 3. GDAL >= 2.0"] pub const wkbCompoundCurveZ: Type = 1009; - #[doc = "< wkbCurvePolygon with Z component. ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< wkbCurvePolygon with Z component. ISO SQL/MM\nPart 3. GDAL >= 2.0"] pub const wkbCurvePolygonZ: Type = 1010; - #[doc = "< wkbMultiCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< wkbMultiCurve with Z component. ISO SQL/MM\nPart 3. GDAL >= 2.0"] pub const wkbMultiCurveZ: Type = 1011; - #[doc = "< wkbMultiSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0"] + #[doc = "< wkbMultiSurface with Z component. ISO SQL/MM\nPart 3. GDAL >= 2.0"] pub const wkbMultiSurfaceZ: Type = 1012; - #[doc = "< wkbCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.1"] + #[doc = "< wkbCurve with Z component. ISO SQL/MM Part 3. GDAL\n>= 2.1"] pub const wkbCurveZ: Type = 1013; - #[doc = "< wkbSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.1"] + #[doc = "< wkbSurface with Z component. ISO SQL/MM Part 3.\nGDAL >= 2.1"] pub const wkbSurfaceZ: Type = 1014; #[doc = "< ISO SQL/MM Part 3. GDAL >= 2.3"] pub const wkbPolyhedralSurfaceZ: Type = 1015; @@ -3925,7 +3907,7 @@ pub mod OGRFieldSubType { pub const OFSTBoolean: Type = 1; #[doc = " Signed 16-bit integer. Only valid for OFTInteger and OFTIntegerList."] pub const OFSTInt16: Type = 2; - #[doc = " Single precision (32 bit) floating point. Only valid for OFTReal and OFTRealList."] + #[doc = " Single precision (32 bit) floating point. Only valid for OFTReal and\nOFTRealList."] pub const OFSTFloat32: Type = 3; #[doc = " JSON content. Only valid for OFTString.\n @since GDAL 2.4"] pub const OFSTJSON: Type = 4; @@ -4558,7 +4540,7 @@ pub mod OGRFieldDomainSplitPolicy { pub const OFDSP_DEFAULT_VALUE: Type = 0; #[doc = " Duplicate"] pub const OFDSP_DUPLICATE: Type = 1; - #[doc = " New values are computed by the ratio of their area/length compared to the area/length of the original feature"] + #[doc = " New values are computed by the ratio of their area/length compared to\nthe area/length of the original feature"] pub const OFDSP_GEOMETRY_RATIO: Type = 2; } pub mod OGRFieldDomainMergePolicy { @@ -4575,7 +4557,7 @@ extern "C" { pub fn GDALVersionInfo(arg1: *const libc::c_char) -> *const libc::c_char; } extern "C" { - #[doc = " Return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor.\n\nThe purpose of this method is to ensure that calling code will run with the GDAL\nversion it is compiled for. It is primarily indented for external plugins.\n\n@param nVersionMajor Major version to be tested against\n@param nVersionMinor Minor version to be tested against\n@param pszCallingComponentName If not NULL, in case of version mismatch, the method\nwill issue a failure mentioning the name of\nthe calling component."] + #[doc = " Return TRUE if GDAL library version at runtime matches\nnVersionMajor.nVersionMinor.\n\nThe purpose of this method is to ensure that calling code will run with the\nGDAL version it is compiled for. It is primarily indented for external\nplugins.\n\n@param nVersionMajor Major version to be tested against\n@param nVersionMinor Minor version to be tested against\n@param pszCallingComponentName If not NULL, in case of version mismatch, the\nmethod will issue a failure mentioning the name of the calling component."] pub fn GDALCheckVersion( nVersionMajor: libc::c_int, nVersionMinor: libc::c_int, @@ -5924,12 +5906,6 @@ extern "C" { extern "C" { pub fn OGR_L_GetNextFeature(arg1: OGRLayerH) -> OGRFeatureH; } -#[doc = " Data type for a Arrow C stream Include ogr_recordbatch.h to get the definition."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ArrowArrayStream { - _unused: [u8; 0], -} extern "C" { pub fn OGR_L_GetArrowStream( hLayer: OGRLayerH, @@ -6607,7 +6583,7 @@ pub mod GDALRIOResampleAlg { pub const GRIORA_Lanczos: Type = 4; #[doc = " Average"] pub const GRIORA_Average: Type = 5; - #[doc = " Mode (selects the value which appears most often of all the sampled points)"] + #[doc = " Mode (selects the value which appears most often of all the sampled\npoints)"] pub const GRIORA_Mode: Type = 6; #[doc = " Gauss blurring"] pub const GRIORA_Gauss: Type = 7; @@ -6615,7 +6591,7 @@ pub mod GDALRIOResampleAlg { pub const GRIORA_RESERVED_START: Type = 8; #[doc = " @cond Doxygen_Suppress"] pub const GRIORA_RESERVED_END: Type = 13; - #[doc = " @endcond */\n/** RMS: Root Mean Square / Quadratic Mean.\n For complex numbers, applies on the real and imaginary part independently."] + #[doc = " @endcond */\n/** RMS: Root Mean Square / Quadratic Mean.\n For complex numbers, applies on the real and imaginary part\n independently."] pub const GRIORA_RMS: Type = 14; #[doc = " @cond Doxygen_Suppress"] pub const GRIORA_LAST: Type = 14; @@ -6632,15 +6608,15 @@ pub struct GDALRasterIOExtraArg { pub pfnProgress: GDALProgressFunc, #[doc = " Progress callback user data"] pub pProgressData: *mut libc::c_void, - #[doc = " Indicate if dfXOff, dfYOff, dfXSize and dfYSize are set.\nMostly reserved from the VRT driver to communicate a more precise\nsource window. Must be such that dfXOff - nXOff < 1.0 and\ndfYOff - nYOff < 1.0 and nXSize - dfXSize < 1.0 and nYSize - dfYSize < 1.0"] + #[doc = " Indicate if dfXOff, dfYOff, dfXSize and dfYSize are set.\nMostly reserved from the VRT driver to communicate a more precise\nsource window. Must be such that dfXOff - nXOff < 1.0 and\ndfYOff - nYOff < 1.0 and nXSize - dfXSize < 1.0 and nYSize - dfYSize\n< 1.0"] pub bFloatingPointWindowValidity: libc::c_int, - #[doc = " Pixel offset to the top left corner. Only valid if bFloatingPointWindowValidity = TRUE"] + #[doc = " Pixel offset to the top left corner. Only valid if\n bFloatingPointWindowValidity = TRUE"] pub dfXOff: f64, - #[doc = " Line offset to the top left corner. Only valid if bFloatingPointWindowValidity = TRUE"] + #[doc = " Line offset to the top left corner. Only valid if\n bFloatingPointWindowValidity = TRUE"] pub dfYOff: f64, - #[doc = " Width in pixels of the area of interest. Only valid if bFloatingPointWindowValidity = TRUE"] + #[doc = " Width in pixels of the area of interest. Only valid if\n bFloatingPointWindowValidity = TRUE"] pub dfXSize: f64, - #[doc = " Height in pixels of the area of interest. Only valid if bFloatingPointWindowValidity = TRUE"] + #[doc = " Height in pixels of the area of interest. Only valid if\n bFloatingPointWindowValidity = TRUE"] pub dfYSize: f64, } #[test] @@ -6821,7 +6797,7 @@ pub type GDALRasterBandH = *mut libc::c_void; pub type GDALDriverH = *mut libc::c_void; #[doc = " Opaque type used for the C bindings of the C++ GDALColorTable class"] pub type GDALColorTableH = *mut libc::c_void; -#[doc = " Opaque type used for the C bindings of the C++ GDALRasterAttributeTable class"] +#[doc = " Opaque type used for the C bindings of the C++ GDALRasterAttributeTable\n class"] pub type GDALRasterAttributeTableH = *mut libc::c_void; #[doc = " Opaque type used for the C bindings of the C++ GDALAsyncReader class"] pub type GDALAsyncReaderH = *mut libc::c_void; @@ -9149,11 +9125,11 @@ extern "C" { pub mod GDALTileOrganization { #[doc = " Enumeration to describe the tile organization"] pub type Type = libc::c_uint; - #[doc = " Tile Interleaved by Pixel: tile (0,0) with internal band interleaved by pixel organization, tile (1, 0), ..."] + #[doc = " Tile Interleaved by Pixel: tile (0,0) with internal band interleaved by\npixel organization, tile (1, 0), ..."] pub const GTO_TIP: Type = 0; - #[doc = " Band Interleaved by Tile : tile (0,0) of first band, tile (0,0) of second band, ... tile (1,0) of first band, tile (1,0) of second band, ..."] + #[doc = " Band Interleaved by Tile : tile (0,0) of first band, tile (0,0) of\nsecond band, ... tile (1,0) of first band, tile (1,0) of second band, ..."] pub const GTO_BIT: Type = 1; - #[doc = " Band SeQuential : all the tiles of first band, all the tiles of following band..."] + #[doc = " Band SeQuential : all the tiles of first band, all the tiles of\nfollowing band..."] pub const GTO_BSQ: Type = 2; } extern "C" { @@ -10487,7 +10463,7 @@ extern "C" { pub struct GDALTriFacet { #[doc = "< index to the padfX/padfY arrays"] pub anVertexIdx: [libc::c_int; 3usize], - #[doc = "< index to GDALDelaunayTriangulation.pasFacets, or -1"] + #[doc = "< index to GDALDelaunayTriangulation.pasFacets, or\n-1"] pub anNeighborIdx: [libc::c_int; 3usize], } #[test] @@ -11702,7 +11678,7 @@ pub mod OSRAxisMappingStrategy { pub type Type = libc::c_uint; #[doc = "< Traditional GIS order"] pub const OAMS_TRADITIONAL_GIS_ORDER: Type = 0; - #[doc = "< Compliant with the order mandated by the CRS authority"] + #[doc = "< Compliant with the order mandated by the CRS\nauthority"] pub const OAMS_AUTHORITY_COMPLIANT: Type = 1; #[doc = "< Custom"] pub const OAMS_CUSTOM: Type = 2; @@ -12136,7 +12112,7 @@ extern "C" { ) -> OGRErr::Type; } extern "C" { - #[doc = " Transverse Mercator\n\n Special processing available for Transverse Mercator with GDAL >= 1.10 and PROJ >= 4.8 :\n see OGRSpatialReference::exportToProj4()."] + #[doc = " Transverse Mercator\n\n Special processing available for Transverse Mercator with GDAL >= 1.10 and\n PROJ >= 4.8 : see OGRSpatialReference::exportToProj4()."] pub fn OSRSetTM( hSRS: OGRSpatialReferenceH, dfCenterLat: f64, @@ -12637,7 +12613,7 @@ extern "C" { pub fn CPLDestroyCond(hCond: *mut libc::c_void); } extern "C" { - #[doc = " Contrary to what its name suggests, CPLGetPID() actually returns the thread id"] + #[doc = " Contrary to what its name suggests, CPLGetPID() actually returns the thread\n id"] pub fn CPLGetPID() -> GIntBig; } extern "C" { @@ -12739,9 +12715,9 @@ pub mod GDALResampleAlg { pub const GRA_CubicSpline: Type = 3; #[doc = " Lanczos windowed sinc interpolation (6x6 kernel)"] pub const GRA_Lanczos: Type = 4; - #[doc = " Average (computes the weighted average of all non-NODATA contributing pixels)"] + #[doc = " Average (computes the weighted average of all non-NODATA contributing\npixels)"] pub const GRA_Average: Type = 5; - #[doc = " Mode (selects the value which appears most often of all the sampled points)"] + #[doc = " Mode (selects the value which appears most often of all the sampled\npoints)"] pub const GRA_Mode: Type = 6; #[doc = " Max (selects maximum of all non-NODATA contributing pixels)"] pub const GRA_Max: Type = 8; @@ -12753,9 +12729,9 @@ pub mod GDALResampleAlg { pub const GRA_Q1: Type = 11; #[doc = " Q3 (selects third quartile of all non-NODATA contributing pixels)"] pub const GRA_Q3: Type = 12; - #[doc = " Sum (weighed sum of all non-NODATA contributing pixels). Added in GDAL 3.1"] + #[doc = " Sum (weighed sum of all non-NODATA contributing pixels). Added in\nGDAL 3.1"] pub const GRA_Sum: Type = 13; - #[doc = " RMS (weighted root mean square (quadratic mean) of all non-NODATA contributing pixels)"] + #[doc = " RMS (weighted root mean square (quadratic mean) of all non-NODATA\ncontributing pixels)"] pub const GRA_RMS: Type = 14; #[doc = " @cond Doxygen_Suppress"] pub const GRA_LAST_VALUE: Type = 14; @@ -12860,7 +12836,7 @@ pub struct GDALWarpOptions { pub eWorkingDataType: GDALDataType::Type, #[doc = " Source image dataset."] pub hSrcDS: GDALDatasetH, - #[doc = " Destination image dataset - may be NULL if only using GDALWarpOperation::WarpRegionToBuffer()."] + #[doc = " Destination image dataset - may be NULL if only using\n GDALWarpOperation::WarpRegionToBuffer()."] pub hDstDS: GDALDatasetH, #[doc = " Number of bands to process, may be 0 to select all bands."] pub nBandCount: libc::c_int, @@ -12872,11 +12848,11 @@ pub struct GDALWarpOptions { pub nSrcAlphaBand: libc::c_int, #[doc = " The dest. band so use as an alpha (transparency) value, 0=disabled"] pub nDstAlphaBand: libc::c_int, - #[doc = " The \"nodata\" value real component for each input band, if NULL there isn't one"] + #[doc = " The \"nodata\" value real component for each input band, if NULL there\n isn't one"] pub padfSrcNoDataReal: *mut f64, #[doc = " The \"nodata\" value imaginary component - may be NULL even if real\ncomponent is provided. This value is not used to flag invalid values.\nOnly the real component is used."] pub padfSrcNoDataImag: *mut f64, - #[doc = " The \"nodata\" value real component for each output band, if NULL there isn't one"] + #[doc = " The \"nodata\" value real component for each output band, if NULL there\n isn't one"] pub padfDstNoDataReal: *mut f64, #[doc = " The \"nodata\" value imaginary component - may be NULL even if real\ncomponent is provided. Note that warp operations only use real component\nfor flagging invalid data."] pub padfDstNoDataImag: *mut f64, @@ -12922,7 +12898,7 @@ pub struct GDALWarpOptions { pub pPostWarpProcessorArg: *mut libc::c_void, #[doc = " Optional OGRPolygonH for a masking cutline."] pub hCutline: *mut libc::c_void, - #[doc = " Optional blending distance to apply across cutline in pixels, default is zero."] + #[doc = " Optional blending distance to apply across cutline in pixels, default is\n zero."] pub dfCutlineBlendDist: f64, } #[test] @@ -13448,91 +13424,356 @@ extern "C" { arg11: libc::c_int, ) -> CPLErr::Type; } -pub mod OGRErr { - #[doc = " Type for a OGR error\n\n
"] - pub type Type = libc::c_uint; - #[doc = " Success\n\n
"] - pub const OGRERR_NONE: Type = 0; - #[doc = " Not enough data to deserialize\n\n
"] - pub const OGRERR_NOT_ENOUGH_DATA: Type = 1; - #[doc = " Not enough memory\n\n
"] - pub const OGRERR_NOT_ENOUGH_MEMORY: Type = 2; - #[doc = " Unsupported geometry type\n\n
"] - pub const OGRERR_UNSUPPORTED_GEOMETRY_TYPE: Type = 3; - #[doc = " Unsupported operation\n\n
"] - pub const OGRERR_UNSUPPORTED_OPERATION: Type = 4; - #[doc = " Corrupt data\n\n
"] - pub const OGRERR_CORRUPT_DATA: Type = 5; - #[doc = " Failure\n\n
"] - pub const OGRERR_FAILURE: Type = 6; - #[doc = " Unsupported SRS\n\n
"] - pub const OGRERR_UNSUPPORTED_SRS: Type = 7; - #[doc = " Invalid handle\n\n
"] - pub const INVALID_HANDLE: Type = 8; - #[doc = " Non existing feature. Added in GDAL 2.0\n\n
"] - pub const NON_EXISTING_FEATURE: Type = 9; -} -pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct __va_list_tag { - pub gp_offset: libc::c_uint, - pub fp_offset: libc::c_uint, - pub overflow_arg_area: *mut libc::c_void, - pub reg_save_area: *mut libc::c_void, +pub struct ArrowSchema { + pub format: *const libc::c_char, + pub name: *const libc::c_char, + pub metadata: *const libc::c_char, + pub flags: i64, + pub n_children: i64, + pub children: *mut *mut ArrowSchema, + pub dictionary: *mut ArrowSchema, + pub release: ::std::option::Option, + pub private_data: *mut libc::c_void, } #[test] -fn bindgen_test_layout___va_list_tag() { - const UNINIT: ::std::mem::MaybeUninit<__va_list_tag> = ::std::mem::MaybeUninit::uninit(); +fn bindgen_test_layout_ArrowSchema() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::<__va_list_tag>(), + ::std::mem::size_of::(), + 72usize, + concat!("Size of: ", stringify!(ArrowSchema)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(ArrowSchema)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(format) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(name) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).metadata) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(metadata) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 24usize, - concat!("Size of: ", stringify!(__va_list_tag)) + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(flags) + ) ); assert_eq!( - ::std::mem::align_of::<__va_list_tag>(), + unsafe { ::std::ptr::addr_of!((*ptr).n_children) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(n_children) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(children) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).dictionary) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(dictionary) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).release) as usize - ptr as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(release) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).private_data) as usize - ptr as usize }, + 64usize, + concat!( + "Offset of field: ", + stringify!(ArrowSchema), + "::", + stringify!(private_data) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ArrowArray { + pub length: i64, + pub null_count: i64, + pub offset: i64, + pub n_buffers: i64, + pub n_children: i64, + pub buffers: *mut *const libc::c_void, + pub children: *mut *mut ArrowArray, + pub dictionary: *mut ArrowArray, + pub release: ::std::option::Option, + pub private_data: *mut libc::c_void, +} +#[test] +fn bindgen_test_layout_ArrowArray() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 80usize, + concat!("Size of: ", stringify!(ArrowArray)) + ); + assert_eq!( + ::std::mem::align_of::(), 8usize, - concat!("Alignment of ", stringify!(__va_list_tag)) + concat!("Alignment of ", stringify!(ArrowArray)) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).gp_offset) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", - stringify!(__va_list_tag), + stringify!(ArrowArray), "::", - stringify!(gp_offset) + stringify!(length) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fp_offset) as usize - ptr as usize }, - 4usize, + unsafe { ::std::ptr::addr_of!((*ptr).null_count) as usize - ptr as usize }, + 8usize, concat!( "Offset of field: ", - stringify!(__va_list_tag), + stringify!(ArrowArray), "::", - stringify!(fp_offset) + stringify!(null_count) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).overflow_arg_area) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(offset) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).n_buffers) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(n_buffers) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).n_children) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(n_children) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).buffers) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(buffers) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(children) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).dictionary) as usize - ptr as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(dictionary) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).release) as usize - ptr as usize }, + 64usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(release) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).private_data) as usize - ptr as usize }, + 72usize, + concat!( + "Offset of field: ", + stringify!(ArrowArray), + "::", + stringify!(private_data) + ) + ); +} +#[doc = " Data type for a Arrow C stream Include ogr_recordbatch.h to get the\n definition."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ArrowArrayStream { + pub get_schema: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ArrowArrayStream, out: *mut ArrowSchema) -> libc::c_int, + >, + pub get_next: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ArrowArrayStream, out: *mut ArrowArray) -> libc::c_int, + >, + pub get_last_error: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ArrowArrayStream) -> *const libc::c_char, + >, + pub release: ::std::option::Option, + pub private_data: *mut libc::c_void, +} +#[test] +fn bindgen_test_layout_ArrowArrayStream() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 40usize, + concat!("Size of: ", stringify!(ArrowArrayStream)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(ArrowArrayStream)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).get_schema) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ArrowArrayStream), + "::", + stringify!(get_schema) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).get_next) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", - stringify!(__va_list_tag), + stringify!(ArrowArrayStream), "::", - stringify!(overflow_arg_area) + stringify!(get_next) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).reg_save_area) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).get_last_error) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", - stringify!(__va_list_tag), + stringify!(ArrowArrayStream), "::", - stringify!(reg_save_area) + stringify!(get_last_error) ) ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).release) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(ArrowArrayStream), + "::", + stringify!(release) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).private_data) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(ArrowArrayStream), + "::", + stringify!(private_data) + ) + ); +} +pub mod OGRErr { + #[doc = " Type for a OGR error\n\n
"] + pub type Type = libc::c_uint; + #[doc = " Success\n\n
"] + pub const OGRERR_NONE: Type = 0; + #[doc = " Not enough data to deserialize\n\n
"] + pub const OGRERR_NOT_ENOUGH_DATA: Type = 1; + #[doc = " Not enough memory\n\n
"] + pub const OGRERR_NOT_ENOUGH_MEMORY: Type = 2; + #[doc = " Unsupported geometry type\n\n
"] + pub const OGRERR_UNSUPPORTED_GEOMETRY_TYPE: Type = 3; + #[doc = " Unsupported operation\n\n
"] + pub const OGRERR_UNSUPPORTED_OPERATION: Type = 4; + #[doc = " Corrupt data\n\n
"] + pub const OGRERR_CORRUPT_DATA: Type = 5; + #[doc = " Failure\n\n
"] + pub const OGRERR_FAILURE: Type = 6; + #[doc = " Unsupported SRS\n\n
"] + pub const OGRERR_UNSUPPORTED_SRS: Type = 7; + #[doc = " Invalid handle\n\n
"] + pub const INVALID_HANDLE: Type = 8; + #[doc = " Non existing feature. Added in GDAL 2.0\n\n
"] + pub const NON_EXISTING_FEATURE: Type = 9; } +pub type __builtin_va_list = *mut libc::c_char; diff --git a/gdal-sys/wrapper.h b/gdal-sys/wrapper.h index 755556fa1..e3bd499fa 100644 --- a/gdal-sys/wrapper.h +++ b/gdal-sys/wrapper.h @@ -26,6 +26,13 @@ */ #include "gdalwarper.h" +/** + * Include ArrowArrayStream header for recent GDAL versions + */ +#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) + #include "ogr_recordbatch.h" +#endif + /** * Type for a OGR error * diff --git a/src/lib.rs b/src/lib.rs index f85950ae2..62985e918 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,8 @@ pub use dataset::{ LayerOptions, Transaction, }; pub use driver::{Driver, DriverManager}; +#[cfg(any(major_ge_4, all(major_is_3, minor_ge_6)))] +pub use gdal_sys::ArrowArrayStream; pub use metadata::{Metadata, MetadataEntry}; #[cfg(test)] diff --git a/src/vector/layer.rs b/src/vector/layer.rs index 22260b307..40ab48206 100644 --- a/src/vector/layer.rs +++ b/src/vector/layer.rs @@ -52,6 +52,8 @@ pub enum LayerCaps { OLCCurveGeometries, /// Layer capability for measured geometries support OLCMeasuredGeometries, + /// Layer capability for a specialized implementation to ArrowArrayStream + OLCFastGetArrowStream, } // Manage conversion to Gdal values @@ -76,6 +78,7 @@ impl LayerCaps { Self::OLCCreateGeomField => "CreateGeomField", Self::OLCCurveGeometries => "CurveGeometries", Self::OLCMeasuredGeometries => "MeasuredGeometries", + Self::OLCFastGetArrowStream => "FastGetArrowStream", }) .unwrap() } @@ -467,6 +470,46 @@ pub trait LayerAccess: Sized { gdal_sys::OGR_L_SetAttributeFilter(self.c_layer(), null_mut()); } } + + /// Read batches of columnar [Arrow](https://arrow.apache.org/) data from OGR. + /// + /// Extended options are available via [`CslStringList`]. As defined in the OGR documentation for [`GetArrowStream`](https://gdal.org/api/ogrlayer_cpp.html#_CPPv4N8OGRLayer14GetArrowStreamEP16ArrowArrayStream12CSLConstList), the current options are: + /// + /// * `INCLUDE_FID=YES/NO`. Whether to include the FID column. Defaults to YES. + /// * `MAX_FEATURES_IN_BATCH=integer`. Maximum number of features to retrieve in a ArrowArray batch. Defaults to 65 536. + /// + /// Additional driver-specific options may exist. + /// + /// This API is new as of GDAL 3.6. + /// + /// # Example + /// + /// Refer to the example provided in `read_ogr_arrow.rs`. + /// + /// # Safety + /// This uses the Arrow C Data Interface to operate on raw pointers provisioned from Rust. + /// These pointers must be valid and provisioned according to the ArrowArrayStream spec. + #[cfg(any(major_ge_4, all(major_is_3, minor_ge_6)))] + unsafe fn read_arrow_stream( + &mut self, + out_stream: *mut gdal_sys::ArrowArrayStream, + options: &crate::cpl::CslStringList, + ) -> Result<()> { + self.reset_feature_reading(); + + unsafe { + let success = + gdal_sys::OGR_L_GetArrowStream(self.c_layer(), out_stream, options.as_ptr()); + if !success { + return Err(GdalError::OgrError { + err: 1, + method_name: "OGR_L_GetArrowStream", + }); + } + } + + Ok(()) + } } pub struct FeatureIterator<'a> {