Skip to content

Commit

Permalink
feat: Bring back GDAL and cli create-item
Browse files Browse the repository at this point in the history
  • Loading branch information
alekzvik committed Dec 14, 2024
1 parent 2bb2f93 commit aa2c652
Show file tree
Hide file tree
Showing 15 changed files with 438 additions and 3 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"crates/derive",
"crates/duckdb",
"crates/extensions",
"crates/gdal",
"crates/pgstac",
"crates/server",
]
Expand Down Expand Up @@ -46,6 +47,7 @@ cql2 = "0.3.0"
duckdb = "=1.0.0"
fluent-uri = "0.3.1"
futures = "0.3.31"
gdal = { version = "0.17.1", features = ["bindgen"] }
geo = "0.29.3"
geo-types = "0.7.13"
geoarrow = "0.3.0"
Expand Down Expand Up @@ -75,6 +77,8 @@ stac-api = { version = "0.6.2", path = "crates/api" }
stac-derive = { version = "0.1.0", path = "crates/derive" }
stac-duckdb = { version = "0.0.3", path = "crates/duckdb" }
stac-server = { version = "0.3.2", path = "crates/server" }
stac-extensions = { version = "0.1.0", path = "crates/extensions" }
stac-gdal = { version = "0.1.0", path = "crates/gdal" }
syn = "2.0"
tempfile = "3.13"
thiserror = "2.0"
Expand Down
1 change: 1 addition & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ stac = { workspace = true, features = [
stac-api = { workspace = true, features = ["client"] }
stac-duckdb = { workspace = true, optional = true }
stac-server = { workspace = true, features = ["axum"] }
stac-gdal.workspace = true
thiserror.workspace = true
tokio = { workspace = true, features = [
"macros",
Expand Down
6 changes: 5 additions & 1 deletion crates/cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// The verbosity stuff is cribbed from https://github.com/clap-rs/clap-verbosity-flag/blob/c621a6a8a7c0b6df8f1464a985a5d076b4915693/src/lib.rs and updated for tracing

use crate::{
subcommand::{search, serve, translate, validate},
subcommand::{create_item, search, serve, translate, validate},
Error, Result, Value,
};
use clap::Parser;
Expand Down Expand Up @@ -85,6 +85,9 @@ pub enum Subcommand {

/// Validate a STAC object using json-schema
Validate(validate::Args),

/// Create a STAC Item from a href.
CreateItem(create_item::Args),
}

#[derive(Copy, Clone, Debug, Default)]
Expand All @@ -109,6 +112,7 @@ impl Args {
Subcommand::Serve(args) => self.serve(args).await,
Subcommand::Translate(args) => self.translate(args).await,
Subcommand::Validate(args) => self.validate(args).await,
Subcommand::CreateItem(args) => self.create_item(args).await,
}
}

Expand Down
4 changes: 4 additions & 0 deletions crates/cli/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ pub enum Error {
#[error(transparent)]
Stac(#[from] stac::Error),

/// [stac_gdal::Error]
#[error(transparent)]
StacGdal(#[from] stac_gdal::Error),

/// [stac_duckdb::Error]
#[cfg(feature = "duckdb")]
#[error(transparent)]
Expand Down
48 changes: 48 additions & 0 deletions crates/cli/src/subcommand/create_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use stac::{item::Builder as ItemBuilder, Asset, ToJson};
use stac_gdal::update_item;
use std::path::Path;

use crate::Result;

/// Arguments for the `create_item` subcommand.
#[derive(clap::Args, Debug, Clone)]
pub struct Args {
/// The input file.
// ///
// /// If not provided or `-`, the input will be read from standard input.
href: String,

/// Asset key
#[arg(default_value = "data")]
asset_key: String,

/// Semantic roles of the asset
#[arg(short, long)]
roles: Option<String>,
}

impl crate::Args {
pub async fn create_item(&self, args: &Args) -> Result<()> {
// TODO: Filename must be present or we need to react
let filename = Path::new(&args.href)
.file_name()
.and_then(|s| s.to_str())
.unwrap();
let mut asset = Asset::new(&args.href);
if let Some(roles) = &args.roles {
asset = asset.role(roles);
}

let mut item = ItemBuilder::new(filename)
.asset(&args.asset_key, asset)
.build()?;

update_item(&mut item, false, true)?;

{
let mut stdout = std::io::stdout().lock();
item.to_json_writer(&mut stdout, false)?;
}
Ok(())
}
}
1 change: 1 addition & 0 deletions crates/cli/src/subcommand/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod create_item;
#[cfg(feature = "pgstac")]
pub mod pgstac;
pub mod search;
Expand Down
5 changes: 5 additions & 0 deletions crates/core/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ pub struct Asset {
/// Additional fields on the asset.
#[serde(flatten)]
pub additional_fields: Map<String, Value>,

/// Phantom field to make extensions work
#[serde(skip)]
pub extensions: Vec<String>,
}

/// Trait implemented by anything that has assets.
Expand Down Expand Up @@ -139,6 +143,7 @@ impl Asset {
statistics: None,
unit: None,
additional_fields: Map::new(),
extensions: Vec::new(),
}
}

Expand Down
12 changes: 12 additions & 0 deletions crates/core/src/bbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@ impl Default for Bbox {
}
}

impl From<[f64; 4]> for Bbox {
fn from(value: [f64; 4]) -> Self {
Bbox::TwoDimensional(value)
}
}

impl From<[f64; 6]> for Bbox {
fn from(value: [f64; 6]) -> Self {
Bbox::ThreeDimensional(value)
}
}

#[cfg(feature = "geo")]
impl From<geo::Rect> for Bbox {
fn from(rect: geo::Rect) -> Bbox {
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/statistics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};

/// Statistics of all pixels in the band.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Statistics {
/// Mean value of all the pixels in the band
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
3 changes: 2 additions & 1 deletion crates/extensions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub mod projection;
pub mod raster;

use serde::{de::DeserializeOwned, Serialize};
use stac::{Catalog, Collection, Error, Fields, Item, Result};
use stac::{Asset, Catalog, Collection, Error, Fields, Item, Result};
pub use {projection::Projection, raster::Raster};

/// A trait implemented by extensions.
Expand Down Expand Up @@ -215,6 +215,7 @@ macro_rules! impl_extensions {
};
}

impl_extensions!(Asset);
impl_extensions!(Item);
impl_extensions!(Catalog);
impl_extensions!(Collection);
Expand Down
20 changes: 20 additions & 0 deletions crates/gdal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "stac-gdal"
description = "STAC utilities that use GDAL"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true
license.workspace = true
categories.workspace = true
rust-version.workspace = true

[dependencies]
gdal.workspace = true
geojson.workspace = true
log.workspace = true
serde_json.workspace = true
stac.workspace = true
stac-extensions.workspace = true
thiserror.workspace = true
30 changes: 30 additions & 0 deletions crates/gdal/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use thiserror::Error;

/// Crate specific error type.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
/// [gdal::errors::GdalError]
#[error(transparent)]
GdalError(#[from] gdal::errors::GdalError),

/// [stac::Error]
#[error(transparent)]
STACError(#[from] stac::Error),

/// [std::num::ParseIntError]
#[error(transparent)]
ParseIntError(#[from] std::num::ParseIntError),

/// [serde_json::Error]
#[error(transparent)]
SerdeJson(#[from] serde_json::Error),

/// Failed to parse EPSG projection from proj extension.
#[error("Failed to parse EPSG projection from: `{0}`")]
ParseEPSGProjectionError(String),

/// Unsupported STAC extension
#[error("STAC extension `{0}` is not supported")]
UnsupportedExtension(String),
}
Loading

0 comments on commit aa2c652

Please sign in to comment.