From 275c54e866cdd60f13e2df3215ba766180e90239 Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Tue, 8 Oct 2024 20:21:36 -0400 Subject: [PATCH 1/2] feat(cli): improve handling for invalid STAC --- cli/src/args/validate.rs | 22 ++++++++++++++++------ cli/src/error.rs | 4 ++++ cli/src/input.rs | 32 ++++++++++++++++++++++++++++++++ core/src/error.rs | 2 +- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/cli/src/args/validate.rs b/cli/src/args/validate.rs index 29c33951..c286a5e7 100644 --- a/cli/src/args/validate.rs +++ b/cli/src/args/validate.rs @@ -15,14 +15,24 @@ pub(crate) struct Args { impl Run for Args { async fn run(self, input: Input, _: Option>) -> Result> { - let value = input.get().await?; + let value = input.get_json().await?; let result = value.validate().await; if let Err(stac::Error::Validation(ref errors)) = result { - let message_base = match value { - stac::Value::Item(item) => format!("[item={}] ", item.id), - stac::Value::Catalog(catalog) => format!("[catalog={}] ", catalog.id), - stac::Value::Collection(collection) => format!("[collection={}] ", collection.id), - stac::Value::ItemCollection(_) => "[item-collection] ".to_string(), + let id = value + .get("id") + .and_then(|v| v.as_str()) + .map(|v| format!("={}", v)) + .unwrap_or_default(); + let message_base = match value + .get("type") + .and_then(|v| v.as_str()) + .unwrap_or_default() + { + "Feature" => format!("[item={}] ", id), + "Catalog" => format!("[catalog={}] ", id), + "Collection" => format!("[collection={}] ", id), + "FeatureCollection" => "[item-collection] ".to_string(), + _ => String::new(), }; for error in errors { eprintln!( diff --git a/cli/src/error.rs b/cli/src/error.rs index 96fd0d25..645e2626 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -57,6 +57,10 @@ pub enum Error { /// Unsupported format. #[error("unsupported (or unknown) format: {0}")] UnsupportedFormat(String), + + /// [url::ParseError] + #[error(transparent)] + UrlParse(#[from] url::ParseError), } impl Error { diff --git a/cli/src/input.rs b/cli/src/input.rs index ce44a046..b06c0463 100644 --- a/cli/src/input.rs +++ b/cli/src/input.rs @@ -55,4 +55,36 @@ impl Input { .map_err(Error::from) } } + + /// Gets a serde_json value from the input. + pub(crate) async fn get_json(&self) -> Result { + if let Some(href) = self.href.as_deref() { + let (object_store, path) = + object_store::parse_url_opts(&href.parse()?, self.options.iter())?; + let get_result = object_store.get(&path).await?; + let bytes = get_result.bytes().await?; + let format = self + .format + .or_else(|| Format::infer_from_href(href)) + .unwrap_or_default(); + match format { + Format::Json(..) => serde_json::from_slice(&bytes).map_err(Error::from), + _ => { + let value: Value = format.from_bytes(bytes)?; + serde_json::to_value(value).map_err(Error::from) + } + } + } else { + let mut buf = Vec::new(); + let _ = std::io::stdin().read_to_end(&mut buf); + let format = self.format.unwrap_or_default(); + match format { + Format::Json(..) => serde_json::from_slice(&buf).map_err(Error::from), + _ => { + let value: Value = format.from_bytes(buf)?; + serde_json::to_value(value).map_err(Error::from) + } + } + } + } } diff --git a/core/src/error.rs b/core/src/error.rs index 591a1310..ac7dbcc5 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -107,7 +107,7 @@ pub enum Error { NoHref, /// There is no type. - #[error("no type")] + #[error("no type field")] NoType, /// No version field on an object. From 0e9e8ac5b050c4ea33eb4b0c19f20d410758c88f Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Tue, 8 Oct 2024 20:29:57 -0400 Subject: [PATCH 2/2] deps: lock duckdb on v1.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index feb4a978..721a7245 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ bb8-postgres = "0.8.1" bytes = "1.7" chrono = "0.4.38" clap = "4.5" -duckdb = "1.0" +duckdb = "=1.0" fluent-uri = "0.3.1" futures = "0.3.31" gdal = "0.17.1"