1use crate::{Error, Result};
2use serde::{de::DeserializeOwned, Serialize};
3use stac::Href;
4use std::path::Path;
5use url::Url;
6
7pub async fn read<T>(href: impl ToString) -> Result<T>
19where
20 T: DeserializeOwned + Href,
21{
22 let href = href.to_string();
23 let mut value: T = read_json(&href).await?;
24 value.set_href(href);
25 Ok(value)
26}
27
28pub async fn read_json<T>(href: &str) -> Result<T>
40where
41 T: DeserializeOwned,
42{
43 if let Some(url) = stac::href_to_url(href) {
44 read_json_from_url(url).await
45 } else {
46 read_json_from_path(href).await
47 }
48}
49
50pub async fn write_json_to_path(path: impl AsRef<Path>, value: impl Serialize) -> Result<()> {
61 let string = serde_json::to_string_pretty(&value)?;
62 tokio::fs::write(path, string).await.map_err(Error::from)
63}
64
65async fn read_json_from_url<T>(url: Url) -> Result<T>
66where
67 T: DeserializeOwned,
68{
69 let response = reqwest::get(url).await?;
70 response.json().await.map_err(Error::from)
71}
72
73async fn read_json_from_path<T>(path: impl AsRef<Path>) -> Result<T>
74where
75 T: DeserializeOwned,
76{
77 let string = tokio::fs::read_to_string(path).await?;
78 serde_json::from_str(&string).map_err(Error::from)
79}
80
81#[cfg(test)]
82mod tests {
83 use stac::{Href, Item};
84
85 #[tokio::test]
86 async fn read_filesystem() {
87 let item: Item = super::read("examples/simple-item.json").await.unwrap();
88 assert!(item.href().unwrap().ends_with("examples/simple-item.json"));
89 }
90
91 #[tokio::test]
92 async fn read_network() {
93 let href = "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0/examples/simple-item.json";
94 let item: Item = super::read(href).await.unwrap();
95 assert_eq!(item.href().unwrap(), href);
96 }
97}