perfect-postcode/server-rs/src/parsing/h3.rs
2026-03-15 21:15:26 +00:00

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
}