use anyhow::{Context, Result as AnyResult};
use clap::{Parser, ValueEnum};
use h3o::CellIndex;
use serde::Serialize;
#[derive(Parser, Debug)]
pub struct Args {
#[arg(short, long)]
origin: Option<CellIndex>,
#[arg(short, long)]
radius: u32,
#[arg(short, long, default_value_t = false)]
distance: bool,
#[arg(short, long, value_enum, default_value_t = Format::Text)]
format: Format,
#[arg(short, long, default_value_t = false)]
pretty: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueEnum)]
enum Format {
Text,
Json,
}
pub fn run(args: &Args) -> AnyResult<()> {
let indexes = crate::utils::get_cell_indexes(args.origin);
match args.format {
Format::Text => disks_to_text(indexes, args.radius, args.distance),
Format::Json => {
disks_to_json(indexes, args.radius, args.distance, args.pretty)
}
}
.context("gridDisk")?;
Ok(())
}
fn disks_to_text(
indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
radius: u32,
with_distance: bool,
) -> AnyResult<()> {
let disks = indexes
.into_iter()
.map(|input| input.map(|index| index.grid_disk_distances_safe(radius)));
if with_distance {
for disk in disks {
let disk = disk?;
for (index, distance) in disk {
println!("{index} {distance}");
}
}
} else {
for disk in disks {
let disk = disk?;
for (index, _) in disk {
println!("{index}");
}
}
}
Ok(())
}
fn disks_to_json(
indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
radius: u32,
with_distance: bool,
pretty: bool,
) -> AnyResult<()> {
let disks = indexes.into_iter().map(|input| {
input.map(|origin| {
origin
.grid_disk_distances_safe(radius)
.map(|(index, distance)| {
(crate::json::CellIndex::from(index), distance)
})
})
});
if with_distance {
#[derive(Serialize)]
struct Neighbor {
index: crate::json::CellIndex,
distance: u32,
}
let disks = disks
.map(|result| {
result.map(|disk| {
disk.map(|(index, distance)| Neighbor { index, distance })
.collect::<Vec<_>>()
})
})
.collect::<AnyResult<Vec<_>>>()?;
crate::json::print(&disks, pretty)
} else {
let disks = disks
.map(|result| {
result.map(|disk| {
disk.map(|(index, _)| index).collect::<Vec<_>>()
})
})
.collect::<AnyResult<Vec<_>>>()?;
crate::json::print(&disks, pretty)
}
}