use crate::error::TransparencyError;
pub const TILE_HEIGHT: u32 = 8;
pub const TILE_WIDTH: u64 = 1 << TILE_HEIGHT;
pub fn tile_path(level: u32, index: u64, width: u64) -> Result<String, TransparencyError> {
let index_path = encode_index(index)?;
let mut path = format!("tile/{level}/{index_path}");
if width > 0 && width < TILE_WIDTH {
path.push_str(&format!(".p/{width}"));
}
Ok(path)
}
fn encode_index(index: u64) -> Result<String, TransparencyError> {
if index == 0 {
return Ok("000".into());
}
let mut segments = Vec::new();
let mut remaining = index;
while remaining > 0 {
#[allow(clippy::cast_possible_truncation)]
let segment = (remaining % 1000) as u16;
segments.push(segment);
remaining /= 1000;
}
segments.reverse();
let mut parts = Vec::with_capacity(segments.len());
for (i, &seg) in segments.iter().enumerate() {
if i < segments.len() - 1 {
parts.push(format!("x{seg:03}"));
} else {
parts.push(format!("{seg:03}"));
}
}
Ok(parts.join("/"))
}
pub fn leaf_tile(leaf_index: u64) -> (u64, u64) {
(leaf_index / TILE_WIDTH, leaf_index % TILE_WIDTH)
}
pub fn tile_count(size: u64) -> (u64, u64) {
(size / TILE_WIDTH, size % TILE_WIDTH)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode_index_zero() {
assert_eq!(encode_index(0).unwrap(), "000");
}
#[test]
fn encode_index_small() {
assert_eq!(encode_index(5).unwrap(), "005");
assert_eq!(encode_index(42).unwrap(), "042");
assert_eq!(encode_index(999).unwrap(), "999");
}
#[test]
fn encode_index_multi_segment() {
assert_eq!(encode_index(1000).unwrap(), "x001/000");
assert_eq!(encode_index(1234).unwrap(), "x001/234");
assert_eq!(encode_index(1234067).unwrap(), "x001/x234/067");
}
#[test]
fn tile_path_data_tile() {
assert_eq!(tile_path(0, 0, 0).unwrap(), "tile/0/000");
assert_eq!(tile_path(0, 5, 0).unwrap(), "tile/0/005");
}
#[test]
fn tile_path_partial() {
assert_eq!(tile_path(0, 0, 42).unwrap(), "tile/0/000.p/42");
}
#[test]
fn tile_path_hash_tile() {
assert_eq!(tile_path(1, 3, 0).unwrap(), "tile/1/003");
}
#[test]
fn tile_path_large_index() {
assert_eq!(tile_path(0, 1234067, 0).unwrap(), "tile/0/x001/x234/067");
}
#[test]
fn leaf_tile_computation() {
assert_eq!(leaf_tile(0), (0, 0));
assert_eq!(leaf_tile(255), (0, 255));
assert_eq!(leaf_tile(256), (1, 0));
assert_eq!(leaf_tile(300), (1, 44));
}
#[test]
fn tile_count_computation() {
assert_eq!(tile_count(0), (0, 0));
assert_eq!(tile_count(256), (1, 0));
assert_eq!(tile_count(300), (1, 44));
assert_eq!(tile_count(512), (2, 0));
}
}