use std::collections::BTreeMap;
use martin_tile_utils::{Encoding, Format, TileInfo};
use serde::{Deserialize, Serialize};
use tilejson::{Bounds, TileJSON};
use tracing::warn;
use super::config::PostgresInfo;
use crate::config::file::postgres::utils::patch_json;
use crate::config::file::{CachePolicy, UnrecognizedValues};
pub type FuncInfoSources = BTreeMap<String, FunctionInfo>;
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
pub struct FunctionInfo {
pub schema: String,
pub function: String,
pub minzoom: Option<u8>,
pub maxzoom: Option<u8>,
pub bounds: Option<Bounds>,
pub cache: Option<CachePolicy>,
#[serde(skip)]
pub tilejson: Option<serde_json::Value>,
#[serde(flatten, skip_serializing)]
pub unrecognized: UnrecognizedValues,
}
impl FunctionInfo {
#[must_use]
pub fn new(schema: String, function: String, tilejson: Option<serde_json::Value>) -> Self {
Self {
schema,
function,
tilejson,
..Default::default()
}
}
#[must_use]
pub fn new_extended(
schema: String,
function: String,
minzoom: u8,
maxzoom: u8,
bounds: Bounds,
) -> Self {
Self {
schema,
function,
minzoom: Some(minzoom),
maxzoom: Some(maxzoom),
bounds: Some(bounds),
..Default::default()
}
}
}
impl PostgresInfo for FunctionInfo {
fn format_id(&self) -> String {
format!("{}.{}", self.schema, self.function)
}
fn to_tilejson(&self, source_id: String) -> TileJSON {
let mut tilejson = tilejson::tilejson! {
tiles: vec![], name: source_id,
description: self.format_id(),
};
tilejson.minzoom = self.minzoom;
tilejson.maxzoom = self.maxzoom;
tilejson.bounds = self.bounds;
patch_json(tilejson, self.tilejson.as_ref())
}
fn tile_info(&self) -> TileInfo {
let Some(tj) = &self.tilejson else {
return TileInfo::new(Format::Mvt, Encoding::Uncompressed);
};
let Some(content_type) = tj.get("content_type").and_then(|v| v.as_str()) else {
return TileInfo::new(Format::Mvt, Encoding::Uncompressed);
};
let (supertype, subtype) = content_type.split_once('/').unwrap_or((content_type, ""));
if let Some(format) = Format::from_content_type(supertype, subtype) {
TileInfo::from(format)
} else {
warn!(
"Unrecognized content_type '{}' in SQL comment for {}.{}, defaulting to MVT",
content_type, self.schema, self.function
);
TileInfo::new(Format::Mvt, Encoding::Uncompressed)
}
}
}
impl FunctionInfo {
#[must_use]
pub fn append_cfg_info(&self, cfg_inf: &Self) -> Self {
Self {
tilejson: self.tilejson.clone(),
..cfg_inf.clone()
}
}
}