Make features iterator take mut ref
Refer:
MODIFY
examples/read_write_ogr.rs
examples/read_write_ogr.rs
@@ -7,7 +7,7 @@ use std::path::Path;
fn run() -> Result<()> {
let dataset_a = Dataset::open(Path::new("fixtures/roads.geojson"))?;
- let layer_a = dataset_a.layer(0)?;
+ let mut layer_a = dataset_a.layer(0)?;
let fields_defn = layer_a
.defn()
.fields()

MODIFY
src/lib.rs
src/lib.rs
//! use std::path::Path;
//! use gdal::Dataset;
//!
-//! let mut dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
-//! let layer = dataset.layer(0).unwrap();
+//! let dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
+//! let mut layer = dataset.layer(0).unwrap();
//! for feature in layer.features() {
//! let highway_field = feature.field("highway").unwrap().unwrap();
//! let geometry = feature.geometry();

MODIFY
src/vector/layer.rs
src/vector/layer.rs
@@ -19,8 +19,8 @@ use crate::errors::*;
/// use std::path::Path;
/// use gdal::Dataset;
///
-/// let mut dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
-/// let layer = dataset.layer(0).unwrap();
+/// let dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
+/// let mut layer = dataset.layer(0).unwrap();
/// for feature in layer.features() {
/// // do something with each feature
/// }
@@ -83,7 +83,7 @@ impl<'a> Layer<'a> {
}
/// Iterate over all features in this layer.
- pub fn features(&self) -> FeatureIterator {
+ pub fn features(&mut self) -> FeatureIterator {
FeatureIterator::_with_layer(self)
}
@@ -244,7 +244,9 @@ impl<'a> Layer<'a> {
}
pub struct FeatureIterator<'a> {
- layer: &'a Layer<'a>,
+ defn: &'a Defn,
+ c_layer: OGRLayerH,
+ size_hint: Option<usize>,
}
impl<'a> Iterator for FeatureIterator<'a> {
@@ -252,21 +254,16 @@ impl<'a> Iterator for FeatureIterator<'a> {
#[inline]
fn next(&mut self) -> Option<Feature<'a>> {
- let c_feature = unsafe { gdal_sys::OGR_L_GetNextFeature(self.layer.c_layer) };
+ 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.layer.defn(), c_feature) })
+ Some(unsafe { Feature::from_c_feature(self.defn, c_feature) })
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
- match self
- .layer
- .try_feature_count()
- .map(|s| s.try_into().ok())
- .flatten()
- {
+ match self.size_hint {
Some(size) => (size, Some(size)),
None => (0, None),
}
@@ -275,7 +272,12 @@ impl<'a> Iterator for FeatureIterator<'a> {
impl<'a> FeatureIterator<'a> {
pub fn _with_layer(layer: &'a Layer) -> FeatureIterator<'a> {
- FeatureIterator { layer }
+ let defn = layer.defn();
+ let size_hint = layer
+ .try_feature_count()
+ .map(|s| s.try_into().ok())
+ .flatten();
+ FeatureIterator { c_layer: layer.c_layer, size_hint, defn }
}
}

MODIFY
src/vector/mod.rs
src/vector/mod.rs
//! use std::path::Path;
//! use gdal::Dataset;
//!
-//! let mut dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
-//! let layer = dataset.layer(0).unwrap();
+//! let dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
+//! let mut layer = dataset.layer(0).unwrap();
//! for feature in layer.features() {
//! let highway_field = feature.field("highway").unwrap().unwrap();
//! let geometry = feature.geometry();

MODIFY
src/vector/vector_tests/mod.rs
src/vector/vector_tests/mod.rs
@@ -85,7 +85,7 @@ fn with_features<F>(name: &str, f: F)
where
F: Fn(FeatureIterator),
{
- with_layer(name, |layer| f(layer.features()));
+ with_layer(name, |mut layer| f(layer.features()));
}
fn with_feature<F>(name: &str, fid: u64, f: F)
@@ -205,7 +205,7 @@ mod tests {
#[test]
fn test_field_in_layer() {
- ds_with_layer("three_layer_ds.s3db", "layer_0", |layer| {
+ ds_with_layer("three_layer_ds.s3db", "layer_0", |mut layer| {
let feature = layer.features().next().unwrap();
assert_eq!(feature.field("id").unwrap(), None);
});
@@ -481,7 +481,7 @@ mod tests {
let ds = Dataset::open(fixture!("output.geojson")).unwrap();
fs::remove_file(fixture!("output.geojson")).unwrap();
- let layer = ds.layer(0).unwrap();
+ let mut layer = ds.layer(0).unwrap();
let ft = layer.features().next().unwrap();
assert_eq!(ft.geometry().wkt().unwrap(), "POINT (1 2)");
assert_eq!(
@@ -491,4 +491,20 @@ mod tests {
assert_eq!(ft.field("Value").unwrap().unwrap().into_real(), Some(45.78));
assert_eq!(ft.field("Int_value").unwrap().unwrap().into_int(), Some(1));
}
+
+ // A compilation test that should fail.
+ //
+ // It tries to iterate over a layer's features, while
+ // also trying to read the layer's definition. The
+ // features iterator borrows layer as a mutable ref as
+ // it increments the internal state of the layer.
+ //
+ // fn test_features_mut_lifetime_enforce() {
+ // with_layer("roads.geojson", |mut layer| {
+ // for _ in layer.features() {
+ // let _ = layer.defn();
+ // }
+ // });
+ // }
+
}

Make features iterator take mut ref

Refer: https://github.com/georust/gdal/issues/159