75 lines
2.3 KiB
Rust
75 lines
2.3 KiB
Rust
use axum::http::StatusCode;
|
|
use rustc_hash::FxHashMap;
|
|
use tracing::warn;
|
|
|
|
use crate::consts::{H3_PRECOMPUTE_MAX, H3_REQUEST_MAX, H3_REQUEST_MIN};
|
|
|
|
/// Validate that an H3 resolution is within the allowed range and convert to h3o::Resolution.
|
|
pub fn validate_h3_resolution(resolution: u8) -> Result<h3o::Resolution, (StatusCode, String)> {
|
|
if !(H3_REQUEST_MIN..=H3_REQUEST_MAX).contains(&resolution) {
|
|
warn!(
|
|
resolution,
|
|
"Resolution out of range [{}, {}]", H3_REQUEST_MIN, H3_REQUEST_MAX
|
|
);
|
|
return Err((
|
|
StatusCode::BAD_REQUEST,
|
|
format!(
|
|
"resolution must be between {} and {}",
|
|
H3_REQUEST_MIN, H3_REQUEST_MAX
|
|
),
|
|
));
|
|
}
|
|
h3o::Resolution::try_from(resolution).map_err(|error| {
|
|
(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
format!("Invalid H3 resolution {}: {}", resolution, error),
|
|
)
|
|
})
|
|
}
|
|
|
|
/// Resolve a row's H3 cell at the requested resolution, using precomputed max-resolution cells.
|
|
#[inline]
|
|
pub fn cell_for_row(
|
|
row: usize,
|
|
precomputed: &[u64],
|
|
h3_res: h3o::Resolution,
|
|
need_parent: bool,
|
|
) -> u64 {
|
|
let max_cell = precomputed[row];
|
|
if !need_parent || max_cell == 0 {
|
|
return max_cell;
|
|
}
|
|
let cell = h3o::CellIndex::try_from(max_cell).expect("precomputed H3 cell must be valid");
|
|
u64::from(
|
|
cell.parent(h3_res)
|
|
.expect("parent resolution must be valid for precomputed cell"),
|
|
)
|
|
}
|
|
|
|
/// Like cell_for_row but caches parent lookups in the provided map.
|
|
#[inline]
|
|
pub fn cell_for_row_cached(
|
|
row: usize,
|
|
precomputed: &[u64],
|
|
h3_res: h3o::Resolution,
|
|
need_parent: bool,
|
|
cache: &mut FxHashMap<u64, u64>,
|
|
) -> u64 {
|
|
let max_cell = precomputed[row];
|
|
if !need_parent || max_cell == 0 {
|
|
return max_cell;
|
|
}
|
|
*cache.entry(max_cell).or_insert_with(|| {
|
|
let cell = h3o::CellIndex::try_from(max_cell).expect("precomputed H3 cell must be valid");
|
|
u64::from(
|
|
cell.parent(h3_res)
|
|
.expect("parent resolution must be valid"),
|
|
)
|
|
})
|
|
}
|
|
|
|
/// Whether the given resolution requires computing a parent from precomputed cells.
|
|
#[inline]
|
|
pub fn needs_parent(resolution: u8) -> bool {
|
|
resolution < H3_PRECOMPUTE_MAX
|
|
}
|