chore: migrate to TileJSON v0.3 (#330) (h/t @nyurik)

* use `tilejson!` to generate json object
* use `Bounds` everywhere when appropriate
This commit is contained in:
Yuri Astrakhan 2022-05-27 07:04:27 -04:00 committed by GitHub
parent d0655fd2b3
commit 66876d5254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 162 additions and 141 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
.DS_Store .DS_Store
/target/ /target/
**/*.rs.bk **/*.rs.bk
.idea/
pg_data/ pg_data/
config.yml config.yml

148
Cargo.lock generated
View File

@ -612,7 +612,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"tinytemplate", "tinytemplate",
"tokio 1.18.1", "tokio 1.18.2",
"walkdir", "walkdir",
] ]
@ -1085,7 +1085,7 @@ checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb"
dependencies = [ dependencies = [
"bytes 1.1.0", "bytes 1.1.0",
"fnv", "fnv",
"itoa 1.0.1", "itoa 1.0.2",
] ]
[[package]] [[package]]
@ -1168,9 +1168,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.1" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
@ -1205,9 +1205,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.125" version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]] [[package]]
name = "linked-hash-map" name = "linked-hash-map"
@ -1343,7 +1343,7 @@ dependencies = [
"kernel32-sys", "kernel32-sys",
"libc", "libc",
"log", "log",
"miow 0.2.2", "miow",
"net2", "net2",
"slab", "slab",
"winapi 0.2.8", "winapi 0.2.8",
@ -1351,16 +1351,14 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"miow 0.3.7",
"ntapi",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
"winapi 0.3.9", "windows-sys",
] ]
[[package]] [[package]]
@ -1386,15 +1384,6 @@ dependencies = [
"ws2_32-sys", "ws2_32-sys",
] ]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.37" version = "0.2.37"
@ -1406,15 +1395,6 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "ntapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -1436,9 +1416,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.10.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]] [[package]]
name = "oorandom" name = "oorandom"
@ -1676,7 +1656,7 @@ dependencies = [
"fallible-iterator", "fallible-iterator",
"futures", "futures",
"log", "log",
"tokio 1.18.1", "tokio 1.18.2",
"tokio-postgres", "tokio-postgres",
] ]
@ -1688,7 +1668,7 @@ checksum = "1de0ea6504e07ca78355a6fb88ad0f36cafe9e696cbc6717f16a207f3a60be72"
dependencies = [ dependencies = [
"futures", "futures",
"openssl", "openssl",
"tokio 1.18.1", "tokio 1.18.2",
"tokio-openssl", "tokio-openssl",
"tokio-postgres", "tokio-postgres",
] ]
@ -1740,11 +1720,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.37" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
dependencies = [ dependencies = [
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
@ -1856,9 +1836,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.5.2" version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"crossbeam-deque", "crossbeam-deque",
@ -1868,9 +1848,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.9.2" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
dependencies = [ dependencies = [
"crossbeam-channel 0.5.4", "crossbeam-channel 0.5.4",
"crossbeam-deque", "crossbeam-deque",
@ -1889,9 +1869,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.5" version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -1906,9 +1886,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.25" version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]] [[package]]
name = "resolv-conf" name = "resolv-conf"
@ -1940,9 +1920,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.9" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -2021,15 +2001,36 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.80" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f972498cf015f7c0746cac89ebe1d6ef10c293b94175a243a2d9442c163d9944" checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
dependencies = [ dependencies = [
"itoa 1.0.1", "itoa 1.0.2",
"ryu", "ryu",
"serde", "serde",
] ]
[[package]]
name = "serde_tuple"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427"
dependencies = [
"serde",
"serde_tuple_macros",
]
[[package]]
name = "serde_tuple_macros"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@ -2037,16 +2038,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"itoa 1.0.1", "itoa 1.0.2",
"ryu", "ryu",
"serde", "serde",
] ]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.8.23" version = "0.8.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"ryu", "ryu",
@ -2223,13 +2224,13 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.92" version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
@ -2281,12 +2282,13 @@ dependencies = [
[[package]] [[package]]
name = "tilejson" name = "tilejson"
version = "0.2.4" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b13f37202f3dfa3d0a775b20ccbff170b702b60603480b4fb2b05851cf4e97" checksum = "1eeb0af84b43a1056a3c4768c91174f2daa12aa152853fc70719cd2a4832cb4e"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_tuple",
] ]
[[package]] [[package]]
@ -2375,14 +2377,14 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.18.1" version = "1.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce653fb475565de9f6fb0614b28bca8df2c430c0cf84bcd9c843f15de5414cc" checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
dependencies = [ dependencies = [
"bytes 1.1.0", "bytes 1.1.0",
"libc", "libc",
"memchr", "memchr",
"mio 0.8.2", "mio 0.8.3",
"once_cell", "once_cell",
"pin-project-lite 0.2.9", "pin-project-lite 0.2.9",
"socket2 0.4.4", "socket2 0.4.4",
@ -2398,7 +2400,7 @@ dependencies = [
"futures-util", "futures-util",
"openssl", "openssl",
"openssl-sys", "openssl-sys",
"tokio 1.18.1", "tokio 1.18.2",
] ]
[[package]] [[package]]
@ -2420,8 +2422,8 @@ dependencies = [
"postgres-protocol", "postgres-protocol",
"postgres-types", "postgres-types",
"socket2 0.4.4", "socket2 0.4.4",
"tokio 1.18.1", "tokio 1.18.2",
"tokio-util 0.7.1", "tokio-util 0.7.2",
] ]
[[package]] [[package]]
@ -2441,15 +2443,15 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.1" version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c"
dependencies = [ dependencies = [
"bytes 1.1.0", "bytes 1.1.0",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"pin-project-lite 0.2.9", "pin-project-lite 0.2.9",
"tokio 1.18.1", "tokio 1.18.2",
"tracing", "tracing",
] ]
@ -2547,6 +2549,12 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
version = "0.1.19" version = "0.1.19"
@ -2562,12 +2570,6 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]] [[package]]
name = "url" name = "url"
version = "2.2.2" version = "2.2.2"

View File

@ -37,7 +37,7 @@ serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_yaml = "0.8" serde_yaml = "0.8"
tilejson = "0.2" tilejson = "0.3"
[dev-dependencies.criterion] [dev-dependencies.criterion]
version = "0.3.4" version = "0.3.4"

View File

@ -1,7 +1,7 @@
use itertools::Itertools; use itertools::Itertools;
use std::io; use std::io;
use tilejson::{TileJSON, TileJSONBuilder}; use tilejson::{tilejson, Bounds, TileJSON};
use crate::db::Connection; use crate::db::Connection;
use crate::source::{Query, Source, Tile, Xyz}; use crate::source::{Query, Source, Tile, Xyz};
@ -62,18 +62,21 @@ impl CompositeSource {
.max() .max()
} }
pub fn get_bounds(&self) -> Option<Vec<f32>> { pub fn get_bounds(&self) -> Option<Bounds> {
self.table_sources self.table_sources
.iter() .iter()
.filter_map(|table_source| table_source.bounds.as_ref()) .filter_map(|table_source| table_source.bounds)
.map(|bounds| bounds.to_vec()) .reduce(|a: Bounds, b: Bounds| -> Bounds {
.reduce(|a, b| { Bounds::new(
vec![ if a.left < b.left { a.left } else { b.left },
if a[0] < b[0] { a[0] } else { b[0] }, if a.bottom < b.bottom {
if a[1] < b[1] { a[1] } else { b[1] }, a.bottom
if a[2] > b[2] { a[2] } else { b[2] }, } else {
if a[3] > b[3] { a[3] } else { b[3] }, b.bottom
] },
if a.right > b.right { a.right } else { b.right },
if a.top > b.top { a.top } else { b.top },
)
}) })
} }
} }
@ -84,24 +87,27 @@ impl Source for CompositeSource {
} }
fn get_tilejson(&self) -> Result<TileJSON, io::Error> { fn get_tilejson(&self) -> Result<TileJSON, io::Error> {
let mut tilejson_builder = TileJSONBuilder::new(); let mut tilejson = tilejson! {
tilejson: "2.2.0".to_string(),
tilejson_builder.scheme("xyz"); tiles: vec![], // tile source is required, but not yet known
tilejson_builder.name(&self.id); name: self.id.to_string(),
};
if let Some(minzoom) = self.get_minzoom() { if let Some(minzoom) = self.get_minzoom() {
tilejson_builder.minzoom(minzoom); tilejson.minzoom = Some(minzoom);
}; };
if let Some(maxzoom) = self.get_maxzoom() { if let Some(maxzoom) = self.get_maxzoom() {
tilejson_builder.maxzoom(maxzoom); tilejson.maxzoom = Some(maxzoom);
}; };
if let Some(bounds) = self.get_bounds() { if let Some(bounds) = self.get_bounds() {
tilejson_builder.bounds(bounds); tilejson.bounds = Some(bounds);
}; };
Ok(tilejson_builder.finalize()) // TODO: consider removing - this is not needed per TileJSON spec
tilejson.set_missing_defaults();
Ok(tilejson)
} }
fn get_tile( fn get_tile(

View File

@ -11,6 +11,7 @@ use crate::db_actor::DbActor;
use crate::function_source::{FunctionSource, FunctionSources}; use crate::function_source::{FunctionSource, FunctionSources};
use crate::server::AppState; use crate::server::AppState;
use crate::table_source::{TableSource, TableSources}; use crate::table_source::{TableSource, TableSources};
use crate::utils::max_bounds;
pub fn mock_table_sources(sources: Vec<TableSource>) -> TableSources { pub fn mock_table_sources(sources: Vec<TableSource>) -> TableSources {
let mut table_sources: TableSources = HashMap::new(); let mut table_sources: TableSources = HashMap::new();
@ -30,7 +31,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 4326, srid: 4326,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -47,7 +48,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom1".to_owned(), geometry_column: "geom1".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 4326, srid: 4326,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -64,7 +65,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom2".to_owned(), geometry_column: "geom2".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 4326, srid: 4326,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -81,7 +82,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 4326, srid: 4326,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -98,7 +99,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 4326, srid: 4326,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -115,7 +116,7 @@ pub fn mock_default_table_sources() -> TableSources {
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
srid: 3857, srid: 3857,
extent: Some(4096), extent: Some(4096),
buffer: Some(64), buffer: Some(64),
@ -150,7 +151,7 @@ pub fn mock_default_function_sources() -> FunctionSources {
function: "function_source".to_owned(), function: "function_source".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
}; };
let function_source_query_params = FunctionSource { let function_source_query_params = FunctionSource {
@ -159,7 +160,7 @@ pub fn mock_default_function_sources() -> FunctionSources {
function: "function_source_query_params".to_owned(), function: "function_source_query_params".to_owned(),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
}; };
mock_function_sources(vec![function_source, function_source_query_params]) mock_function_sources(vec![function_source, function_source_query_params])

View File

@ -3,7 +3,7 @@ use postgres_protocol::escape::escape_identifier;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
use tilejson::{TileJSON, TileJSONBuilder}; use tilejson::{tilejson, Bounds, TileJSON};
use crate::db::Connection; use crate::db::Connection;
use crate::source::{Query, Source, Tile, Xyz}; use crate::source::{Query, Source, Tile, Xyz};
@ -32,7 +32,7 @@ pub struct FunctionSource {
// latitude and longitude values, in the order left, bottom, right, top. // latitude and longitude values, in the order left, bottom, right, top.
// Values may be integers or floating point numbers. // Values may be integers or floating point numbers.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub bounds: Option<Vec<f32>>, pub bounds: Option<Bounds>,
} }
pub type FunctionSources = HashMap<String, Box<FunctionSource>>; pub type FunctionSources = HashMap<String, Box<FunctionSource>>;
@ -43,25 +43,27 @@ impl Source for FunctionSource {
} }
fn get_tilejson(&self) -> Result<TileJSON, io::Error> { fn get_tilejson(&self) -> Result<TileJSON, io::Error> {
let mut tilejson_builder = TileJSONBuilder::new(); let mut tilejson = tilejson! {
tilejson: "2.2.0".to_string(),
tilejson_builder.scheme("xyz"); tiles: vec![], // tile source is required, but not yet known
tilejson_builder.name(&self.id); name: self.id.to_string(),
tilejson_builder.tiles(vec![]); };
if let Some(minzoom) = &self.minzoom { if let Some(minzoom) = &self.minzoom {
tilejson_builder.minzoom(*minzoom); tilejson.minzoom = Some(*minzoom);
}; };
if let Some(maxzoom) = &self.maxzoom { if let Some(maxzoom) = &self.maxzoom {
tilejson_builder.maxzoom(*maxzoom); tilejson.maxzoom = Some(*maxzoom);
}; };
if let Some(bounds) = &self.bounds { if let Some(bounds) = &self.bounds {
tilejson_builder.bounds(bounds.to_vec()); tilejson.bounds = Some(*bounds);
}; };
Ok(tilejson_builder.finalize()) // TODO: consider removing - this is not needed per TileJSON spec
tilejson.set_missing_defaults();
Ok(tilejson)
} }
fn get_tile( fn get_tile(

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::io; use std::io;
use tilejson::{TileJSON, TileJSONBuilder}; use tilejson::{tilejson, Bounds, TileJSON};
use crate::db::Connection; use crate::db::Connection;
use crate::source::{Query, Source, Tile, Xyz}; use crate::source::{Query, Source, Tile, Xyz};
@ -42,7 +42,7 @@ pub struct TableSource {
// latitude and longitude values, in the order left, bottom, right, top. // latitude and longitude values, in the order left, bottom, right, top.
// Values may be integers or floating point numbers. // Values may be integers or floating point numbers.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub bounds: Option<Vec<f32>>, pub bounds: Option<Bounds>,
// Tile extent in tile coordinate space // Tile extent in tile coordinate space
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -129,24 +129,27 @@ impl Source for TableSource {
} }
fn get_tilejson(&self) -> Result<TileJSON, io::Error> { fn get_tilejson(&self) -> Result<TileJSON, io::Error> {
let mut tilejson_builder = TileJSONBuilder::new(); let mut tilejson = tilejson! {
tilejson: "2.2.0".to_string(),
tilejson_builder.scheme("xyz"); tiles: vec![], // tile source is required, but not yet known
tilejson_builder.name(&self.id); name: self.id.to_string(),
};
if let Some(minzoom) = &self.minzoom { if let Some(minzoom) = &self.minzoom {
tilejson_builder.minzoom(*minzoom); tilejson.minzoom = Some(*minzoom);
}; };
if let Some(maxzoom) = &self.maxzoom { if let Some(maxzoom) = &self.maxzoom {
tilejson_builder.maxzoom(*maxzoom); tilejson.maxzoom = Some(*maxzoom);
}; };
if let Some(bounds) = &self.bounds { if let Some(bounds) = &self.bounds {
tilejson_builder.bounds(bounds.to_vec()); tilejson.bounds = Some(*bounds);
}; };
Ok(tilejson_builder.finalize()) // TODO: consider removing - this is not needed per TileJSON spec
tilejson.set_missing_defaults();
Ok(tilejson)
} }
fn get_tile( fn get_tile(
@ -219,7 +222,7 @@ pub fn get_table_sources(
let bounds_query = utils::get_source_bounds(&id, srid as u32, &geometry_column); let bounds_query = utils::get_source_bounds(&id, srid as u32, &geometry_column);
let bounds: Option<Vec<f32>> = conn let bounds: Option<Bounds> = conn
.query_one(bounds_query.as_str(), &[]) .query_one(bounds_query.as_str(), &[])
.map(|row| row.get("bounds")) .map(|row| row.get("bounds"))
.ok() .ok()

View File

@ -5,6 +5,7 @@ use actix_web::http;
use postgis::{ewkb, LineString, Point, Polygon}; use postgis::{ewkb, LineString, Point, Polygon};
use postgres::types::Json; use postgres::types::Json;
use serde_json::Value; use serde_json::Value;
use tilejson::Bounds;
pub fn prettify_error<E: std::fmt::Display>(message: String) -> impl Fn(E) -> std::io::Error { pub fn prettify_error<E: std::fmt::Display>(message: String) -> impl Fn(E) -> std::io::Error {
move |error| std::io::Error::new(std::io::ErrorKind::Other, format!("{message}: {error}")) move |error| std::io::Error::new(std::io::ErrorKind::Other, format!("{message}: {error}"))
@ -78,16 +79,16 @@ pub fn get_source_bounds(id: &str, srid: u32, geometry_column: &str) -> String {
) )
} }
pub fn polygon_to_bbox(polygon: ewkb::Polygon) -> Option<Vec<f32>> { pub fn polygon_to_bbox(polygon: ewkb::Polygon) -> Option<Bounds> {
polygon.rings().next().and_then(|linestring| { polygon.rings().next().and_then(|linestring| {
let mut points = linestring.points(); let mut points = linestring.points();
if let (Some(bottom_left), Some(top_right)) = (points.next(), points.nth(1)) { if let (Some(bottom_left), Some(top_right)) = (points.next(), points.nth(1)) {
Some(vec![ Some(Bounds::new(
bottom_left.x() as f32, bottom_left.x(),
bottom_left.y() as f32, bottom_left.y(),
top_right.x() as f32, top_right.x(),
top_right.y() as f32, top_right.y(),
]) ))
} else { } else {
None None
} }
@ -101,3 +102,7 @@ pub fn parse_x_rewrite_url(header: &http::HeaderValue) -> Option<String> {
.and_then(|header| header.parse::<http::Uri>().ok()) .and_then(|header| header.parse::<http::Uri>().ok())
.map(|uri| uri.path().trim_end_matches(".json").to_owned()) .map(|uri| uri.path().trim_end_matches(".json").to_owned())
} }
pub fn max_bounds() -> Bounds {
Bounds::new(-180.0, -90.0, 180.0, 90.0)
}

View File

@ -9,6 +9,7 @@ use martin::dev;
use martin::function_source::{FunctionSource, FunctionSources}; use martin::function_source::{FunctionSource, FunctionSources};
use martin::server::router; use martin::server::router;
use martin::table_source::{TableSource, TableSources}; use martin::table_source::{TableSource, TableSources};
use martin::utils::max_bounds;
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
@ -56,7 +57,7 @@ async fn test_get_table_source_ok() {
table: "table_source".to_owned(), table: "table_source".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: Some(0), minzoom: Some(0),
maxzoom: Some(30), maxzoom: Some(30),
srid: 4326, srid: 4326,
@ -99,7 +100,7 @@ async fn test_get_table_source_ok() {
); );
assert_eq!(result.minzoom, Some(0)); assert_eq!(result.minzoom, Some(0));
assert_eq!(result.maxzoom, Some(30)); assert_eq!(result.maxzoom, Some(30));
assert_eq!(result.bounds, Some(vec![-180.0, -90.0, 180.0, 90.0])); assert_eq!(result.bounds, Some(max_bounds()));
} }
#[actix_rt::test] #[actix_rt::test]
@ -156,7 +157,7 @@ async fn test_get_table_source_tile_minmax_zoom_ok() {
table: "points1".to_owned(), table: "points1".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: Some(6), minzoom: Some(6),
maxzoom: Some(12), maxzoom: Some(12),
srid: 4326, srid: 4326,
@ -173,7 +174,7 @@ async fn test_get_table_source_tile_minmax_zoom_ok() {
table: "points2".to_owned(), table: "points2".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: None, minzoom: None,
maxzoom: None, maxzoom: None,
srid: 4326, srid: 4326,
@ -190,7 +191,7 @@ async fn test_get_table_source_tile_minmax_zoom_ok() {
table: "points3857".to_owned(), table: "points3857".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: Some(6), minzoom: Some(6),
maxzoom: None, maxzoom: None,
srid: 4326, srid: 4326,
@ -207,7 +208,7 @@ async fn test_get_table_source_tile_minmax_zoom_ok() {
table: "table_source".to_owned(), table: "table_source".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: None, minzoom: None,
maxzoom: Some(6), maxzoom: Some(6),
srid: 4326, srid: 4326,
@ -383,7 +384,7 @@ async fn test_get_composite_source_tile_minmax_zoom_ok() {
table: "points1".to_owned(), table: "points1".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: Some(6), minzoom: Some(6),
maxzoom: Some(13), maxzoom: Some(13),
srid: 4326, srid: 4326,
@ -400,7 +401,7 @@ async fn test_get_composite_source_tile_minmax_zoom_ok() {
table: "points2".to_owned(), table: "points2".to_owned(),
id_column: None, id_column: None,
geometry_column: "geom".to_owned(), geometry_column: "geom".to_owned(),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
minzoom: Some(13), minzoom: Some(13),
maxzoom: Some(20), maxzoom: Some(20),
srid: 4326, srid: 4326,
@ -588,7 +589,7 @@ async fn test_get_function_source_tile_minmax_zoom_ok() {
function: "function_source".to_owned(), function: "function_source".to_owned(),
minzoom: None, minzoom: None,
maxzoom: None, maxzoom: None,
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
}; };
let function_source2 = FunctionSource { let function_source2 = FunctionSource {
@ -597,7 +598,7 @@ async fn test_get_function_source_tile_minmax_zoom_ok() {
function: "function_source".to_owned(), function: "function_source".to_owned(),
minzoom: Some(6), minzoom: Some(6),
maxzoom: Some(12), maxzoom: Some(12),
bounds: Some(vec![-180.0, -90.0, 180.0, 90.0]), bounds: Some(max_bounds()),
}; };
let state = dev::mock_state( let state = dev::mock_state(