pteropus/src/geonb.rs

89 lines
2.6 KiB
Rust

use {futures::stream::TryStreamExt, geo_types::Point, tokio_util::io::StreamReader};
#[derive(Debug)]
pub struct Error {
pub message: String,
}
impl Error {
pub fn new(message: &str) -> Error {
let message = message.to_string();
Error { message }
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "GeoNB Error: \"{}\"", self.message)
}
}
impl std::error::Error for Error {}
fn convert_err(_err: reqwest::Error) -> std::io::Error {
todo!()
}
pub async fn get_lidar_tile_around_point(
location: Point<f64>,
) -> Result<impl tokio::io::AsyncRead, anyhow::Error> {
let client = reqwest::Client::new();
let query_response_json = &client
.get("https://geonb.snb.ca/arcgis/rest/services/GeoNB_SNB_LidarIndex/MapServer/1/query")
.query(&[
("f", "json"),
("geometryType", "esriGeometryPoint"),
("geometry", &format!("{},{}", location.x(), location.y())),
("returnIdsOnly", "true"),
])
.send()
.await?
.json::<serde_json::Value>()
.await?;
println!(
"{}",
serde_json::to_string_pretty(&query_response_json).expect("JSON")
);
let object_id = query_response_json
.get("objectIds")
.and_then(|object_ids| object_ids.get(0))
.and_then(&serde_json::Value::as_i64)
.ok_or_else(|| Error::new("Could not find \"objectId\" in response."))?;
let object_response_json = client
.get(format!(
"https://geonb.snb.ca/arcgis/rest/services/GeoNB_SNB_LidarIndex/MapServer/1/{}",
object_id
))
.query(&[("f", "json")])
.send()
.await?
.json::<serde_json::Value>()
.await?;
println!(
"{}",
serde_json::to_string_pretty(&object_response_json).expect("JSON")
);
let laz_file_url = object_response_json
.get("feature")
.ok_or_else(|| Error::new("Could not find \"feature\" in response."))?
.get("attributes")
.ok_or_else(|| Error::new("Could not find \"attributes\" in response."))?
.get("FILE_URL")
.ok_or_else(|| Error::new("Could not find \"FILE_URL\" in response."))?
.as_str()
.ok_or_else(|| Error::new("Expected \"FILE_URL\" to be a string but it was not."))?;
println!("LAZ URL: {}", laz_file_url);
Ok(StreamReader::new(
client
.get(laz_file_url)
.send()
.await?
.bytes_stream()
.map_err(convert_err),
))
}