Skip to content

Commit

Permalink
Take the field index, not name in the feature getters and setters
Browse files Browse the repository at this point in the history
  • Loading branch information
lnicola committed Oct 29, 2024
1 parent 5d886ab commit cf3b56a
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 369 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@
- Regenerate the pre-built bindings with `std::ffi` instead of `libc` for C types ([#573](https://github.com/georust/gdal/pull/573))
- Upgrade `ndarray` dependency to 0.16 ([#569](https://github.com/georust/gdal/pull/569))

- Update `Feature::field`, `Feature::set_field`, `Feature::set_field_string`, `Feature::set_field_string_list`, `Feature::set_field_double`, `Feature::set_field_double_list`, `Feature::set_field_integer`, `Feature::set_field_integer_list`, `Feature::set_field_integer64`, `Feature::set_field_integer64_list`, `Feature::set_field_datetime`, `Feature::set_field_null`, `Feature::unset_field` to take a field index, not a name
- Drop `Feature::field_as_integer_by_name`, `Feature::field_as_integer64_by_name`, `Feature::field_as_double_by_name`, `Feature::field_as_string_by_name`, `Feature::field_as_datetime_by_name`
- Update `Feature::field_count` to return `usize` instead of `i32`
- Update `Feature::field_as_integer`, `Feature::field_as_integer64`, `Feature::field_as_double`, `Feature::field_as_string`, `Feature::field_as_datetime` to take the field index as `usize` instead of `i32`
- Drop `LayerAccess::create_feature_fields`

### Added

- Add a `bundled` feature for `gdal-sys` for building and statically linking a minimal bundled version of GDAL ([#517](https://github.com/georust/gdal/pull/517))
- Add pre-built bindings for GDAL 3.10 ([#573](https://github.com/georust/gdal/pull/573))
- Add methods `alternative_name`, `is_nullable`, `is_unique`, `default_value` to `Field` ([#561](https://github.com/georust/gdal/pull/561))
- Add `Defn::geometry_type` ([#562](https://github.com/georust/gdal/pull/562))
- Add `Defn::field_index` and `Feature::field_index`

### Fixed

Expand Down
6 changes: 3 additions & 3 deletions examples/read_write_ogr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ fn run() -> Result<()> {
}

// copy each field value of the feature:
for fd in &fields_defn {
if let Some(value) = feature_a.field(&fd.0)? {
ft.set_field(&fd.0, &value)?;
for idx in 0..fields_defn.len() {
if let Some(value) = feature_a.field(idx)? {
ft.set_field(idx, &value)?;
}
}
// Add the feature to the layer:
Expand Down
6 changes: 3 additions & 3 deletions examples/read_write_ogr_datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ fn run() -> gdal::errors::Result<()> {
ft.set_geometry(geom.clone())?;
}
// copy each field value of the feature:
for field in defn.fields() {
for (idx, field) in defn.fields().enumerate() {
ft.set_field(
&field.name(),
&match feature_a.field(field.name())?.unwrap() {
idx,
&match feature_a.field(idx)?.unwrap() {
// add one day to dates
FieldValue::DateValue(value) => {
println!("{} = {}", field.name(), value);
Expand Down
71 changes: 11 additions & 60 deletions examples/write_ogr.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use gdal::errors::Result;
use gdal::vector::{Defn, Feature, FieldDefn, FieldValue, Geometry, LayerAccess, OGRFieldType};
use gdal::vector::{Defn, Feature, FieldDefn, Geometry, OGRFieldType};
use gdal::DriverManager;
use std::fs;

/// Example 1, the detailed way:
fn example_1() -> Result<()> {
fn main() -> Result<()> {
let path = std::env::temp_dir().join("output1.geojson");
let _ = fs::remove_file(&path);
let drv = DriverManager::get_driver_by_name("GeoJSON")?;
Expand All @@ -21,81 +21,32 @@ fn example_1() -> Result<()> {

let defn = Defn::from_layer(&lyr);

let name_idx = defn.field_index("Name")?;
let value_idx = defn.field_index("Value")?;

// 1st feature:
let mut ft = Feature::new(&defn)?;
ft.set_geometry(Geometry::from_wkt("POINT (45.21 21.76)")?)?;
ft.set_field_string("Name", "Feature 1")?;
ft.set_field_double("Value", 45.78)?;
ft.set_field_string(name_idx, "Feature 1")?;
ft.set_field_double(value_idx, 45.78)?;
ft.create(&lyr)?;

// 2nd feature:
let mut ft = Feature::new(&defn)?;
ft.set_field_double("Value", 0.789)?;
ft.set_field_double(value_idx, 0.789)?;
ft.set_geometry(Geometry::from_wkt("POINT (46.50 22.50)")?)?;
ft.set_field_string("Name", "Feature 2")?;
ft.set_field_string(name_idx, "Feature 2")?;
ft.create(&lyr)?;

// Feature triggering an error due to a wrong field name:
let mut ft = Feature::new(&defn)?;
ft.set_geometry(Geometry::from_wkt("POINT (46.50 22.50)")?)?;
ft.set_field_string("Name", "Feature 2")?;
match ft.set_field_double("Values", 0.789) {
ft.set_field_string(name_idx, "Feature 2")?;
match ft.set_field_double(value_idx, 0.789) {
Ok(v) => v,
Err(err) => println!("{err}"),
};
ft.create(&lyr)?;

Ok(())
}

/// Example 2, same output, shortened way:
fn example_2() -> Result<()> {
let path = std::env::temp_dir().join("output2.geojson");
let _ = fs::remove_file(&path);
let driver = DriverManager::get_driver_by_name("GeoJSON")?;
let mut ds = driver.create_vector_only(path.to_str().unwrap())?;
let mut layer = ds.create_layer(Default::default())?;

layer.create_defn_fields(&[
("Name", OGRFieldType::OFTString),
("Value", OGRFieldType::OFTReal),
])?;

layer.create_feature_fields(
Geometry::from_wkt("POINT (45.21 21.76)")?,
&["Name", "Value"],
&[
FieldValue::StringValue("Feature 1".to_string()),
FieldValue::RealValue(45.78),
],
)?;

layer.create_feature_fields(
Geometry::from_wkt("POINT (46.50 22.50)")?,
&["Name", "Value"],
&[
FieldValue::StringValue("Feature 2".to_string()),
FieldValue::RealValue(0.789),
],
)?;

// Feature creation triggering an error due to a wrong field name:
match layer.create_feature_fields(
Geometry::from_wkt("POINT (46.50 22.50)")?,
&["Abcd", "Value"],
&[
FieldValue::StringValue("Feature 2".to_string()),
FieldValue::RealValue(0.789),
],
) {
Ok(v) => v,
Err(err) => println!("{err}"),
};

Ok(())
}

fn main() {
example_1().unwrap();
example_2().unwrap();
}
2 changes: 1 addition & 1 deletion gdal-src/source
Submodule source updated 3521 files
21 changes: 20 additions & 1 deletion src/vector/defn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ffi::c_int;
use std::ffi::{c_int, CString};

use gdal_sys::{
OGRFeatureDefnH, OGRFieldDefnH, OGRFieldType, OGRGeomFieldDefnH, OGRwkbGeometryType,
Expand Down Expand Up @@ -66,6 +66,25 @@ impl Defn {
pub fn geometry_type(&self) -> OGRwkbGeometryType::Type {
unsafe { gdal_sys::OGR_FD_GetGeomType(self.c_defn) }
}

/// Get the index of a field.
///
/// If the field is missing, returns [`GdalError::InvalidFieldName`].
///
pub fn field_index<S: AsRef<str>>(&self, field_name: S) -> Result<usize> {
let c_str_field_name = CString::new(field_name.as_ref())?;
let field_id =
unsafe { gdal_sys::OGR_FD_GetFieldIndex(self.c_defn(), c_str_field_name.as_ptr()) };
if field_id == -1 {
return Err(GdalError::InvalidFieldName {
field_name: field_name.as_ref().to_string(),
method_name: "OGR_FD_GetFieldIndex",
});
}

let idx = field_id.try_into()?;
Ok(idx)
}
}

pub struct FieldIterator<'a> {
Expand Down
Loading

0 comments on commit cf3b56a

Please sign in to comment.