use crate::metadata::Metadata;
use crate::spatial_ref::SpatialRef;
use crate::utils::{_last_null_pointer_err, _string};
use crate::vector::defn::Defn;
use crate::vector::{Feature, FieldValue, Geometry};
use crate::{dataset::Dataset, gdal_major_object::MajorObject};
use gdal_sys::{
self, GDALMajorObjectH, OGREnvelope, OGRErr, OGRFieldDefnH, OGRFieldType, OGRLayerH,
};
use libc::c_int;
use std::ptr::null_mut;
use std::{convert::TryInto, ffi::CString, marker::PhantomData};
use crate::errors::*;
#[allow(clippy::upper_case_acronyms)]
pub enum LayerCaps {
OLCRandomRead,
OLCSequentialWrite,
OLCRandomWrite,
OLCFastSpatialFilter,
OLCFastFeatureCount,
OLCFastGetExtent,
OLCCreateField,
OLCDeleteField,
OLCReorderFields,
OLCAlterFieldDefn,
OLCTransactions,
OLCDeleteFeature,
OLCFastSetNextByIndex,
OLCStringsAsUTF8,
OLCIgnoreFields,
OLCCreateGeomField,
OLCCurveGeometries,
OLCMeasuredGeometries,
}
impl LayerCaps {
fn into_cstring(self) -> CString {
CString::new(match self {
Self::OLCRandomRead => "RandomRead",
Self::OLCSequentialWrite => "SequentialWrite",
Self::OLCRandomWrite => "RandomWrite",
Self::OLCFastSpatialFilter => "FastSpatialFilter",
Self::OLCFastFeatureCount => "FastFeatureCount",
Self::OLCFastGetExtent => "FastGetExtent",
Self::OLCCreateField => "CreateField",
Self::OLCDeleteField => "DeleteField",
Self::OLCReorderFields => "ReorderFields",
Self::OLCAlterFieldDefn => "AlterFieldDefn",
Self::OLCTransactions => "Transactions",
Self::OLCDeleteFeature => "DeleteFeature",
Self::OLCFastSetNextByIndex => "FastSetNextByIndex",
Self::OLCStringsAsUTF8 => "StringsAsUTF8",
Self::OLCIgnoreFields => "IgnoreFields",
Self::OLCCreateGeomField => "CreateGeomField",
Self::OLCCurveGeometries => "CurveGeometries",
Self::OLCMeasuredGeometries => "MeasuredGeometries",
})
.unwrap()
}
}
#[derive(Debug)]
pub struct Layer<'a> {
c_layer: OGRLayerH,
defn: Defn,
phantom: PhantomData<&'a Dataset>,
}
impl<'a> MajorObject for Layer<'a> {
unsafe fn gdal_object_ptr(&self) -> GDALMajorObjectH {
self.c_layer
}
}
impl<'a> Metadata for Layer<'a> {}
impl<'a> LayerAccess for Layer<'a> {
unsafe fn c_layer(&self) -> OGRLayerH {
self.c_layer
}
fn defn(&self) -> &Defn {
&self.defn
}
}
impl<'a> Layer<'a> {
pub(crate) unsafe fn from_c_layer(_: &'a Dataset, c_layer: OGRLayerH) -> Self {
let c_defn = gdal_sys::OGR_L_GetLayerDefn(c_layer);
let defn = Defn::from_c_defn(c_defn);
Self {
c_layer,
defn,
phantom: PhantomData,
}
}
}
#[derive(Debug)]
pub struct OwnedLayer {
c_layer: OGRLayerH,
defn: Defn,
_dataset: Dataset,
}
impl MajorObject for OwnedLayer {
unsafe fn gdal_object_ptr(&self) -> GDALMajorObjectH {
self.c_layer
}
}
impl Metadata for OwnedLayer {}
impl LayerAccess for OwnedLayer {
unsafe fn c_layer(&self) -> OGRLayerH {
self.c_layer
}
fn defn(&self) -> &Defn {
&self.defn
}
}
impl OwnedLayer {
pub(crate) unsafe fn from_c_layer(dataset: Dataset, c_layer: OGRLayerH) -> Self {
let c_defn = gdal_sys::OGR_L_GetLayerDefn(c_layer);
let defn = Defn::from_c_defn(c_defn);
Self {
c_layer,
defn,
_dataset: dataset,
}
}
pub fn owned_features(mut self) -> OwnedFeatureIterator {
self.reset_feature_reading();
OwnedFeatureIterator::_with_layer(self)
}
pub fn into_dataset(self) -> Dataset {
self._dataset
}
}
unsafe impl Send for OwnedLayer {}
impl From<OwnedLayer> for Dataset {
fn from(owned_layer: OwnedLayer) -> Self {
owned_layer.into_dataset()
}
}
pub trait LayerAccess: Sized {
unsafe fn c_layer(&self) -> OGRLayerH;
fn defn(&self) -> &Defn;
fn feature(&self, fid: u64) -> Option<Feature> {
let c_feature = unsafe { gdal_sys::OGR_L_GetFeature(self.c_layer(), fid as i64) };
if c_feature.is_null() {
None
} else {
Some(unsafe { Feature::from_c_feature(self.defn(), c_feature) })
}
}
fn features(&mut self) -> FeatureIterator {
self.reset_feature_reading();
FeatureIterator::_with_layer(self)
}
fn set_feature(&self, feature: Feature) -> Result<()> {
unsafe { gdal_sys::OGR_L_SetFeature(self.c_layer(), feature.c_feature()) };
Ok(())
}
fn set_spatial_filter(&mut self, geometry: &Geometry) {
unsafe { gdal_sys::OGR_L_SetSpatialFilter(self.c_layer(), geometry.c_geometry()) };
}
fn set_spatial_filter_rect(&mut self, min_x: f64, min_y: f64, max_x: f64, max_y: f64) {
unsafe { gdal_sys::OGR_L_SetSpatialFilterRect(self.c_layer(), min_x, min_y, max_x, max_y) };
}
fn clear_spatial_filter(&mut self) {
unsafe { gdal_sys::OGR_L_SetSpatialFilter(self.c_layer(), null_mut()) };
}
fn name(&self) -> String {
let rv = unsafe { gdal_sys::OGR_L_GetName(self.c_layer()) };
_string(rv)
}
fn has_capability(&self, capability: LayerCaps) -> bool {
unsafe {
gdal_sys::OGR_L_TestCapability(self.c_layer(), capability.into_cstring().as_ptr()) == 1
}
}
fn create_defn_fields(&self, fields_def: &[(&str, OGRFieldType::Type)]) -> Result<()> {
for fd in fields_def {
let fdefn = FieldDefn::new(fd.0, fd.1)?;
fdefn.add_to_layer(self)?;
}
Ok(())
}
fn create_feature(&mut self, geometry: Geometry) -> Result<()> {
let feature = Feature::new(self.defn())?;
let c_geometry = unsafe { geometry.into_c_geometry() };
let rv = unsafe { gdal_sys::OGR_F_SetGeometryDirectly(feature.c_feature(), c_geometry) };
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_F_SetGeometryDirectly",
});
}
let rv = unsafe { gdal_sys::OGR_L_CreateFeature(self.c_layer(), feature.c_feature()) };
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_L_CreateFeature",
});
}
Ok(())
}
fn create_feature_fields(
&mut self,
geometry: Geometry,
field_names: &[&str],
values: &[FieldValue],
) -> Result<()> {
let mut ft = Feature::new(self.defn())?;
ft.set_geometry(geometry)?;
for (fd, val) in field_names.iter().zip(values.iter()) {
ft.set_field(fd, val)?;
}
ft.create(self)?;
Ok(())
}
fn feature_count(&self) -> u64 {
(unsafe { gdal_sys::OGR_L_GetFeatureCount(self.c_layer(), 1) }) as u64
}
fn try_feature_count(&self) -> Option<u64> {
let rv = unsafe { gdal_sys::OGR_L_GetFeatureCount(self.c_layer(), 0) };
if rv < 0 {
None
} else {
Some(rv as u64)
}
}
fn get_extent(&self) -> Result<gdal_sys::OGREnvelope> {
let mut envelope = OGREnvelope {
MinX: 0.0,
MaxX: 0.0,
MinY: 0.0,
MaxY: 0.0,
};
let force = 1;
let rv = unsafe { gdal_sys::OGR_L_GetExtent(self.c_layer(), &mut envelope, force) };
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_L_GetExtent",
});
}
Ok(envelope)
}
fn try_get_extent(&self) -> Result<Option<gdal_sys::OGREnvelope>> {
let mut envelope = OGREnvelope {
MinX: 0.0,
MaxX: 0.0,
MinY: 0.0,
MaxY: 0.0,
};
let force = 0;
let rv = unsafe { gdal_sys::OGR_L_GetExtent(self.c_layer(), &mut envelope, force) };
if rv == OGRErr::OGRERR_FAILURE {
Ok(None)
} else {
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_L_GetExtent",
});
}
Ok(Some(envelope))
}
}
fn spatial_ref(&self) -> Result<SpatialRef> {
let c_obj = unsafe { gdal_sys::OGR_L_GetSpatialRef(self.c_layer()) };
if c_obj.is_null() {
return Err(_last_null_pointer_err("OGR_L_GetSpatialRef"));
}
unsafe { SpatialRef::from_c_obj(c_obj) }
}
fn reset_feature_reading(&mut self) {
unsafe {
gdal_sys::OGR_L_ResetReading(self.c_layer());
}
}
fn set_attribute_filter(&mut self, query: &str) -> Result<()> {
let c_str = CString::new(query)?;
let rv = unsafe { gdal_sys::OGR_L_SetAttributeFilter(self.c_layer(), c_str.as_ptr()) };
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_L_SetAttributeFilter",
});
}
Ok(())
}
fn clear_attribute_filter(&mut self) {
unsafe {
gdal_sys::OGR_L_SetAttributeFilter(self.c_layer(), null_mut());
}
}
}
pub struct FeatureIterator<'a> {
defn: &'a Defn,
c_layer: OGRLayerH,
size_hint: Option<usize>,
}
impl<'a> Iterator for FeatureIterator<'a> {
type Item = Feature<'a>;
#[inline]
fn next(&mut self) -> Option<Feature<'a>> {
let c_feature = unsafe { gdal_sys::OGR_L_GetNextFeature(self.c_layer) };
if c_feature.is_null() {
None
} else {
Some(unsafe { Feature::from_c_feature(self.defn, c_feature) })
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.size_hint {
Some(size) => (size, Some(size)),
None => (0, None),
}
}
}
impl<'a> FeatureIterator<'a> {
pub(crate) fn _with_layer<L: LayerAccess>(layer: &'a L) -> Self {
let defn = layer.defn();
let size_hint = layer.try_feature_count().and_then(|s| s.try_into().ok());
Self {
c_layer: unsafe { layer.c_layer() },
size_hint,
defn,
}
}
}
pub struct OwnedFeatureIterator {
pub(crate) layer: OwnedLayer,
size_hint: Option<usize>,
}
impl<'a> Iterator for &'a mut OwnedFeatureIterator
where
Self: 'a,
{
type Item = Feature<'a>;
#[inline]
fn next(&mut self) -> Option<Feature<'a>> {
let c_feature = unsafe { gdal_sys::OGR_L_GetNextFeature(self.layer.c_layer()) };
if c_feature.is_null() {
return None;
}
Some(unsafe {
let defn: &'a Defn = std::mem::transmute::<&'_ _, &'a _>(self.layer.defn());
Feature::from_c_feature(defn, c_feature)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.size_hint {
Some(size) => (size, Some(size)),
None => (0, None),
}
}
}
impl OwnedFeatureIterator {
pub(crate) fn _with_layer(layer: OwnedLayer) -> Self {
let size_hint = layer.try_feature_count().and_then(|s| s.try_into().ok());
Self { layer, size_hint }
}
pub fn into_layer(self) -> OwnedLayer {
self.layer
}
}
impl AsMut<OwnedFeatureIterator> for OwnedFeatureIterator {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl From<OwnedFeatureIterator> for OwnedLayer {
fn from(feature_iterator: OwnedFeatureIterator) -> Self {
feature_iterator.into_layer()
}
}
pub struct FieldDefn {
c_obj: OGRFieldDefnH,
}
impl Drop for FieldDefn {
fn drop(&mut self) {
unsafe { gdal_sys::OGR_Fld_Destroy(self.c_obj) };
}
}
impl MajorObject for FieldDefn {
unsafe fn gdal_object_ptr(&self) -> GDALMajorObjectH {
self.c_obj
}
}
impl FieldDefn {
pub fn new(name: &str, field_type: OGRFieldType::Type) -> Result<FieldDefn> {
let c_str = CString::new(name)?;
let c_obj = unsafe { gdal_sys::OGR_Fld_Create(c_str.as_ptr(), field_type) };
if c_obj.is_null() {
return Err(_last_null_pointer_err("OGR_Fld_Create"));
};
Ok(FieldDefn { c_obj })
}
pub fn set_width(&self, width: i32) {
unsafe { gdal_sys::OGR_Fld_SetWidth(self.c_obj, width as c_int) };
}
pub fn set_precision(&self, precision: i32) {
unsafe { gdal_sys::OGR_Fld_SetPrecision(self.c_obj, precision as c_int) };
}
pub fn add_to_layer<L: LayerAccess>(&self, layer: &L) -> Result<()> {
let rv = unsafe { gdal_sys::OGR_L_CreateField(layer.c_layer(), self.c_obj, 1) };
if rv != OGRErr::OGRERR_NONE {
return Err(GdalError::OgrError {
err: rv,
method_name: "OGR_L_CreateFeature",
});
}
Ok(())
}
}