geopackage-core 0.10.0

No-IO core for the OGC GeoPackage format: GeoPackage Binary (GPB) codec, table DDL, RTree trigger definitions, and validation rules
Documentation

geopackage

CI crates.io docs.rs

Read and write OGC GeoPackage 1.4 files from Rust: feature and attribute tables, RTree spatial indexes, tile pyramids, and columnar I/O through Apache Arrow. A command-line tool and a C ABI are built over the same library.

Pre-1.0: the API changes between minor versions.

[!NOTE] These crates are a testbed for LLM-assisted Rust development and have been produced with the substantial assistance of Claude's Fable and Opus 5 models. Issues will be answered by the author.

Install

[dependencies]
geopackage = "0.10"

The default build links the system SQLite, which must include the RTree module (libsqlite3-dev on Debian/Ubuntu, sqlite-devel on Fedora; macOS needs nothing beyond the SDK). The bundled feature compiles and links a vendored SQLite instead, needs a C compiler, and is the only option on Windows. The arrow feature adds the columnar read and write paths. The minimum supported Rust version is 1.95.

The command-line tool vendors SQLite by default:

cargo install geopackage-cli

Example

Create a file, declare a point layer, write two features, and query by bounding box. Writing accepts any geo_traits::GeometryTrait implementor, which includes every geo-types geometry.

use geo_types::Point;
use geopackage::core::types::{ColumnType, GeometryType};
use geopackage::{
    BoundingBox, ColumnSpec, GeoPackage, GeometrySpec, NewFeature, TableSchemaBuilder, Value,
};

let gpkg = GeoPackage::create("cities.gpkg")?;

gpkg.create_layer(
    &TableSchemaBuilder::new("cities")
        .column(ColumnSpec::new("name", ColumnType::Text(None)))
        .geometry(GeometrySpec::new(GeometryType::Point, 4326)),
)?;

let layer = gpkg.layer("cities")?;
layer.write_all(
    vec![
        NewFeature::new(Point::new(-6.26, 53.35), vec![Value::Text("Dublin".into())]),
        NewFeature::new(Point::new(-0.13, 51.51), vec![Value::Text("London".into())]),
    ],
    0,
)?;

// Served by the RTree index that `create_layer` builds.
for feature in layer.features_in(BoundingBox::new(-7.0, 53.0, -6.0, 54.0))? {
    let feature = feature?;
    let geom = feature.geometry()?.and_then(|g| g.to_geo());
    println!("{:?} at {:?}", feature.value("name"), geom);
}

Tiles, Arrow, extensions, validation and configuration are covered in the crate documentation. Runnable programs are in geopackage/examples.

Workspace

Crate Contents Reference
geopackage The container: files, layers, spatial indexes, tile pyramids, Arrow I/O. docs.rs
geopackage-core Format primitives with no SQLite dependency: the GPB codec, table DDL, RTree trigger SQL. docs.rs
geopackage-cli gpkg: info, validate, index, repair, copy and tiles. gpkg --help
geopackage-ffi The C ABI: opaque handles, the Arrow C Data Interface as data plane, packaged with cargo-c. Five C programs in examples are compiled against the committed header by CI. docs.rs, include/geopackage.h

geopackage-ffi is the only crate that contains unsafe.

Scope

  • CRS definitions are stored, not applied: there is no PROJ dependency and no coordinate transformation.
  • Tiles are stored and validated as bytes. The crate does not decode images, reproject a pyramid, or build one from a raster.
  • Tiled gridded coverages (elevation and other measured grids, OGC 17-066r2) are read, written and validated, payloads included: the extension's TIFF and PNG encoding rules are checked from the header, and a coverage's scale, offset and null are applied to a sample you decoded elsewhere. Samples themselves stay opaque, so the per-tile statistics are whatever the caller supplies and Requirement 21 (no NaN, no Inf) cannot be enforced here.
  • Non-linear curve types (CIRCULARSTRING and the rest) can be written, indexed and queried by extent, but do not read back as geometry objects; Feature::geometry_bytes returns their WKB.

Conformance and performance

Files written by this crate pass the OGC ets-gpkg12 suite except one test whose regex hard-codes the 1.2 trigger set, and the Tiles conformance class in full. Round trips through GDAL byte-compare geometry and attributes. Details are in the changelog and roadmap/08-testing-conformance.md.

Benchmarks on three multi-gigabyte datasets, with method and caveats, are in the current baseline write-up. scripts/bench_datasets.sh runs the measurements and scripts/bench_fly.sh provides the machine to run them on. Earlier write-ups in that directory predate the current method.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.