use flatgeobuf::{FallibleStreamingIterator as _, FeatureProperties as _};
use geo::Contains as _;
use geozero::ToGeo as _;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("flatgeobuf: {0}")]
Flatgeobuf(#[from] flatgeobuf::Error),
#[error("geozero: {0}")]
Geozero(#[from] geozero::error::GeozeroError),
}
pub fn lookup_with_fgb(fgb: &[u8], [x, y]: [f64; 2]) -> Result<Vec<String>, Error> {
let point = geo::Point::new(x, y);
let mut fgb =
flatgeobuf::FgbReader::open(std::io::Cursor::new(fgb))?.select_bbox(x, y, x, y)?;
let mut tzs = Vec::with_capacity(fgb.size_hint().0);
while let Some(feature) = fgb.next().unwrap() {
let Some(tzid) = match feature.property::<String>("tzid") {
Ok(tzid) => Ok(Some(tzid)),
Err(geozero::error::GeozeroError::ColumnNotFound) => Ok(None),
Err(e) => Err(e),
}?
else {
continue;
};
if !feature.to_geo().unwrap().contains(&point) {
continue;
}
tzs.push(tzid);
}
Ok(tzs)
}
#[cfg(any(feature = "with-data", doc))]
pub fn lookup([x, y]: [f64; 2]) -> Result<Vec<String>, Error> {
#[cfg(doc)]
panic!("cannot be called in a docs build");
#[cfg(not(doc))]
lookup_with_fgb(geotz_data::DATA, [x, y])
}