Skip to content

Commit b0e591c

Browse files
authored
feat: add stac-types and stac-derive (#507)
* refactor: add stac-types and stac-derive * fix: add fields * fix: broken docs links
1 parent fb9ff3f commit b0e591c

33 files changed

+249
-262
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ members = [
44
"crates/api",
55
"crates/cli",
66
"crates/core",
7+
"crates/derive",
78
"crates/duckdb",
89
"crates/extensions",
910
"crates/pgstac",
10-
"python",
1111
"crates/server",
12+
"crates/types",
13+
"python",
1214
]
1315
default-members = [
1416
"crates/api",
1517
"crates/cli",
1618
"crates/core",
19+
"crates/derive",
1720
"crates/extensions",
21+
"crates/types",
1822
]
1923

2024
[workspace.package]
@@ -70,8 +74,10 @@ serde_json = "1.0"
7074
serde_urlencoded = "0.7.1"
7175
stac = { version = "0.10.2", path = "crates/core" }
7276
stac-api = { version = "0.6.1", path = "crates/api" }
77+
stac-derive = { version = "0.1.0", path = "crates/derive" }
7378
stac-duckdb = { version = "0.0.2", path = "crates/duckdb" }
7479
stac-server = { version = "0.3.1", path = "crates/server" }
80+
stac-types = { version = "0.1.0", path = "crates/types" }
7581
syn = "2.0"
7682
tempfile = "3.13"
7783
thiserror = "1.0"

crates/api/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ serde.workspace = true
3333
serde_json.workspace = true
3434
serde_urlencoded.workspace = true
3535
stac.workspace = true
36+
stac-derive.workspace = true
37+
stac-types.workspace = true
3638
thiserror.workspace = true
3739
tracing.workspace = true
3840
tokio = { workspace = true, optional = true }

crates/api/src/collections.rs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use serde::{Deserialize, Serialize};
22
use serde_json::{Map, Value};
3-
use stac::{Collection, Href, Link, Links};
3+
use stac::{Collection, Link};
4+
use stac_derive::{Href, Links};
45

56
/// Object containing an array of collections and an array of links.
6-
#[derive(Debug, Serialize, Deserialize)]
7+
#[derive(Debug, Serialize, Deserialize, Href, Links)]
78
pub struct Collections {
89
/// The [Collection] objects in the [stac::Catalog].
910
pub collections: Vec<Collection>,
@@ -29,25 +30,3 @@ impl From<Vec<Collection>> for Collections {
2930
}
3031
}
3132
}
32-
33-
impl Href for Collections {
34-
fn href(&self) -> Option<&str> {
35-
self.href.as_deref()
36-
}
37-
fn set_href(&mut self, href: impl ToString) {
38-
self.href = Some(href.to_string());
39-
}
40-
fn clear_href(&mut self) {
41-
self.href = None;
42-
}
43-
}
44-
45-
impl Links for Collections {
46-
fn links(&self) -> &[Link] {
47-
&self.links
48-
}
49-
50-
fn links_mut(&mut self) -> &mut Vec<Link> {
51-
&mut self.links
52-
}
53-
}

crates/api/src/item_collection.rs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use crate::{Item, Result};
22
use serde::{Deserialize, Serialize};
33
use serde_json::{Map, Value};
4-
use stac::{Href, Link, Links};
4+
use stac::Link;
5+
use stac_derive::{Href, Links};
56

67
/// The return value of the `/items` and `/search` endpoints.
78
///
89
/// This might be a [stac::ItemCollection], but if the [fields
910
/// extension](https://github.com/stac-api-extensions/fields) is used, it might
1011
/// not be. Defined by the [itemcollection
1112
/// fragment](https://github.com/radiantearth/stac-api-spec/blob/main/fragments/itemcollection/README.md).
12-
#[derive(Debug, Serialize, Deserialize, Default)]
13+
#[derive(Debug, Serialize, Deserialize, Default, Links, Href)]
1314
#[serde(tag = "type", rename = "FeatureCollection")]
1415
pub struct ItemCollection {
1516
/// A possibly-empty array of Item objects.
@@ -118,27 +119,6 @@ impl ItemCollection {
118119
}
119120
}
120121

121-
impl Href for ItemCollection {
122-
fn set_href(&mut self, href: impl ToString) {
123-
self.href = Some(href.to_string());
124-
}
125-
fn clear_href(&mut self) {
126-
self.href = None;
127-
}
128-
fn href(&self) -> Option<&str> {
129-
self.href.as_deref()
130-
}
131-
}
132-
133-
impl Links for ItemCollection {
134-
fn links(&self) -> &[Link] {
135-
&self.links
136-
}
137-
fn links_mut(&mut self) -> &mut Vec<Link> {
138-
&mut self.links
139-
}
140-
}
141-
142122
impl From<Vec<Item>> for ItemCollection {
143123
fn from(items: Vec<Item>) -> Self {
144124
ItemCollection {

crates/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ stac = { workspace = true, features = [
4040
stac-api = { workspace = true, features = ["client"] }
4141
stac-duckdb = { workspace = true, optional = true }
4242
stac-server = { workspace = true, features = ["axum"] }
43+
stac-types.workspace = true
4344
thiserror.workspace = true
4445
tokio = { workspace = true, features = [
4546
"macros",

crates/cli/src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ pub enum Error {
4242
#[error(transparent)]
4343
StacServer(#[from] stac_server::Error),
4444

45+
/// [stac_types::Error]
46+
#[error(transparent)]
47+
StacTypes(#[from] stac_types::Error),
48+
4549
/// [tokio::sync::mpsc::error::SendError]
4650
#[error(transparent)]
4751
TokioSend(#[from] tokio::sync::mpsc::error::SendError<Value>),

crates/core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,13 @@ geoarrow = { workspace = true, optional = true }
6161
geojson.workspace = true
6262
jsonschema = { workspace = true, optional = true }
6363
log.workspace = true
64-
mime.workspace = true
6564
object_store = { workspace = true, optional = true }
6665
parquet = { workspace = true, optional = true }
6766
reqwest = { workspace = true, features = ["json", "blocking"], optional = true }
6867
serde = { workspace = true, features = ["derive"] }
6968
serde_json = { workspace = true, features = ["preserve_order"] }
69+
stac-derive.workspace = true
70+
stac-types.workspace = true
7071
thiserror.workspace = true
7172
tokio = { workspace = true, optional = true }
7273
tracing.workspace = true

crates/core/src/asset.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use crate::{Band, DataType, Fields, Statistics};
1+
use crate::{Band, DataType, Statistics};
22
use serde::{Deserialize, Serialize};
33
use serde_json::{Map, Value};
4+
use stac_derive::Fields;
45
use std::collections::HashMap;
56

67
/// An Asset is an object that contains a URI to data associated with the [Item](crate::Item) that can be downloaded or streamed.
7-
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
8+
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Fields)]
89
pub struct Asset {
910
/// URI to the asset object.
1011
///
@@ -159,15 +160,6 @@ impl Asset {
159160
}
160161
}
161162

162-
impl Fields for Asset {
163-
fn fields(&self) -> &Map<String, Value> {
164-
&self.additional_fields
165-
}
166-
fn fields_mut(&mut self) -> &mut Map<String, Value> {
167-
&mut self.additional_fields
168-
}
169-
}
170-
171163
impl From<String> for Asset {
172164
fn from(value: String) -> Self {
173165
Asset::new(value)

crates/core/src/catalog.rs

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use crate::{Error, Fields, Href, Link, Links, Migrate, Result, Version, STAC_VERSION};
1+
use crate::{Error, Link, Result, Version, STAC_VERSION};
22
use serde::{Deserialize, Serialize};
33
use serde_json::{Map, Value};
4+
use stac_derive::{Fields, Href, Links, Migrate};
45

56
/// A STAC Catalog object represents a logical group of other `Catalog`,
67
/// [Collection](crate::Collection), and [Item](crate::Item) objects.
@@ -14,7 +15,7 @@ use serde_json::{Map, Value};
1415
/// A `Catalog` object will typically be the entry point into a STAC catalog.
1516
/// Their purpose is discovery: to be browsed by people or be crawled by clients
1617
/// to build a searchable index.
17-
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
18+
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Href, Migrate, Links, Fields)]
1819
#[serde(tag = "type")]
1920
pub struct Catalog {
2021
/// The STAC version the `Catalog` implements.
@@ -78,29 +79,6 @@ impl Catalog {
7879
}
7980
}
8081

81-
impl Href for Catalog {
82-
fn href(&self) -> Option<&str> {
83-
self.href.as_deref()
84-
}
85-
86-
fn set_href(&mut self, href: impl ToString) {
87-
self.href = Some(href.to_string())
88-
}
89-
90-
fn clear_href(&mut self) {
91-
self.href = None;
92-
}
93-
}
94-
95-
impl Links for Catalog {
96-
fn links(&self) -> &[Link] {
97-
&self.links
98-
}
99-
fn links_mut(&mut self) -> &mut Vec<Link> {
100-
&mut self.links
101-
}
102-
}
103-
10482
impl TryFrom<Catalog> for Map<String, Value> {
10583
type Error = Error;
10684
fn try_from(catalog: Catalog) -> Result<Self> {
@@ -119,17 +97,6 @@ impl TryFrom<Map<String, Value>> for Catalog {
11997
}
12098
}
12199

122-
impl Fields for Catalog {
123-
fn fields(&self) -> &Map<String, Value> {
124-
&self.additional_fields
125-
}
126-
fn fields_mut(&mut self) -> &mut Map<String, Value> {
127-
&mut self.additional_fields
128-
}
129-
}
130-
131-
impl Migrate for Catalog {}
132-
133100
#[cfg(test)]
134101
mod tests {
135102
use super::Catalog;

crates/core/src/collection.rs

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use crate::{
2-
Asset, Assets, Bbox, Error, Fields, Href, Item, ItemAsset, Link, Links, Migrate, Result,
3-
Version, STAC_VERSION,
2+
Asset, Assets, Bbox, Error, Href, Item, ItemAsset, Link, Links, Migrate, Result, Version,
3+
STAC_VERSION,
44
};
55
use chrono::{DateTime, Utc};
66
use serde::{Deserialize, Serialize};
77
use serde_json::{Map, Value};
8+
use stac_derive::{Fields, Href, Links};
89
use std::collections::HashMap;
910

1011
const DEFAULT_LICENSE: &str = "proprietary";
@@ -21,7 +22,7 @@ const DEFAULT_LICENSE: &str = "proprietary";
2122
/// A STAC `Collection` is represented in JSON format. Any JSON object that
2223
/// contains all the required fields is a valid STAC `Collection` and also a valid
2324
/// STAC `Catalog`.
24-
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
25+
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Href, Links, Fields)]
2526
#[serde(tag = "type")]
2627
pub struct Collection {
2728
/// The STAC version the `Collection` implements.
@@ -288,29 +289,6 @@ impl Collection {
288289
}
289290
}
290291

291-
impl Href for Collection {
292-
fn href(&self) -> Option<&str> {
293-
self.href.as_deref()
294-
}
295-
296-
fn set_href(&mut self, href: impl ToString) {
297-
self.href = Some(href.to_string())
298-
}
299-
300-
fn clear_href(&mut self) {
301-
self.href = None;
302-
}
303-
}
304-
305-
impl Links for Collection {
306-
fn links(&self) -> &[Link] {
307-
&self.links
308-
}
309-
fn links_mut(&mut self) -> &mut Vec<Link> {
310-
&mut self.links
311-
}
312-
}
313-
314292
impl Provider {
315293
/// Creates a new provider with the given name.
316294
///
@@ -386,15 +364,6 @@ impl Assets for Collection {
386364
}
387365
}
388366

389-
impl Fields for Collection {
390-
fn fields(&self) -> &Map<String, Value> {
391-
&self.additional_fields
392-
}
393-
fn fields_mut(&mut self) -> &mut Map<String, Value> {
394-
&mut self.additional_fields
395-
}
396-
}
397-
398367
impl TryFrom<Collection> for Map<String, Value> {
399368
type Error = Error;
400369
fn try_from(collection: Collection) -> Result<Self> {

0 commit comments

Comments
 (0)