diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 473caf1a7..2acc71a7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,10 +56,13 @@ jobs: - uses: Swatinem/rust-cache@v2 if: github.event_name != 'release' && github.event_name != 'workflow_dispatch' - run: cargo fmt --all -- --check - - run: cargo clippy --package martin-tile-utils -- -D warnings - - run: cargo clippy --package mbtiles --no-default-features -- -D warnings - - run: cargo clippy --package mbtiles -- -D warnings - - run: cargo clippy --package martin -- -D warnings + - run: cargo clippy --package martin-tile-utils --tests --lib --bins --benches -- -D warnings + - run: cargo clippy --package mbtiles --tests --lib --bins --benches --no-default-features -- -D warnings + - run: cargo clippy --package mbtiles --tests --lib --bins --benches -- -D warnings + - run: cargo clippy --package martin --tests --lib --bins --benches -- -D warnings + - run: RUSTFLAGS='-D warnings' cargo check --package martin --tests --lib --bins --benches --no-default-features + - run: RUSTFLAGS='-D warnings' cargo check --package martin --tests --lib --bins --benches --no-default-features --features fonts + - run: RUSTFLAGS='-D warnings' cargo check --package martin --tests --lib --bins --benches --no-default-features --features sprites - run: cargo clippy --package martin --features bless-tests -- -D warnings - run: cargo doc --no-deps --workspace env: diff --git a/martin/Cargo.toml b/martin/Cargo.toml index 790abec15..b803ec91c 100644 --- a/martin/Cargo.toml +++ b/martin/Cargo.toml @@ -59,7 +59,9 @@ name = "bench" harness = false [features] -default = [] +default = ["sprites", "fonts"] +sprites = [] +fonts = [] bless-tests = [] [dependencies] diff --git a/martin/src/args/root.rs b/martin/src/args/root.rs index 90c81133f..64f09f9c0 100644 --- a/martin/src/args/root.rs +++ b/martin/src/args/root.rs @@ -97,6 +97,7 @@ impl Args { config.mbtiles = parse_file_args(&mut cli_strings, "mbtiles", false); } + #[cfg(feature = "sprites")] if !self.extras.sprite.is_empty() { config.sprites = FileConfigEnum::new(self.extras.sprite); } diff --git a/martin/src/config.rs b/martin/src/config.rs index 379500032..9a44afd8c 100644 --- a/martin/src/config.rs +++ b/martin/src/config.rs @@ -12,11 +12,13 @@ use serde::{Deserialize, Serialize}; use subst::VariableMap; use crate::file_config::{resolve_files, resolve_files_urls, FileConfigEnum}; +#[cfg(feature = "fonts")] use crate::fonts::FontSources; use crate::mbtiles::MbtSource; use crate::pg::PgConfig; use crate::pmtiles::{PmtFileSource, PmtHttpSource}; use crate::source::{TileInfoSources, TileSources}; +#[cfg(feature = "sprites")] use crate::sprites::SpriteSources; use crate::srv::SrvConfig; use crate::MartinError::{ConfigLoadError, ConfigParseError, ConfigWriteError, NoSources}; @@ -26,7 +28,9 @@ pub type UnrecognizedValues = HashMap; pub struct ServerState { pub tiles: TileSources, + #[cfg(feature = "sprites")] pub sprites: SpriteSources, + #[cfg(feature = "fonts")] pub fonts: FontSources, } @@ -44,6 +48,7 @@ pub struct Config { #[serde(default, skip_serializing_if = "FileConfigEnum::is_none")] pub mbtiles: FileConfigEnum, + #[cfg(feature = "sprites")] #[serde(default, skip_serializing_if = "FileConfigEnum::is_none")] pub sprites: FileConfigEnum, @@ -66,17 +71,22 @@ impl Config { res.extend(self.pmtiles.finalize("pmtiles.")?); res.extend(self.mbtiles.finalize("mbtiles.")?); + #[cfg(feature = "sprites")] res.extend(self.sprites.finalize("sprites.")?); // TODO: support for unrecognized fonts? // res.extend(self.fonts.finalize("fonts.")?); - if self.postgres.is_empty() - && self.pmtiles.is_empty() - && self.mbtiles.is_empty() - && self.sprites.is_empty() - && self.fonts.is_empty() - { + let is_empty = + self.postgres.is_empty() && self.pmtiles.is_empty() && self.mbtiles.is_empty(); + + #[cfg(feature = "sprites")] + let is_empty = is_empty && self.sprites.is_empty(); + + #[cfg(feature = "fonts")] + let is_empty = is_empty && self.fonts.is_empty(); + + if is_empty { Err(NoSources) } else { Ok(res) @@ -86,7 +96,9 @@ impl Config { pub async fn resolve(&mut self, idr: IdResolver) -> MartinResult { Ok(ServerState { tiles: self.resolve_tile_sources(idr).await?, + #[cfg(feature = "sprites")] sprites: SpriteSources::resolve(&mut self.sprites)?, + #[cfg(feature = "fonts")] fonts: FontSources::resolve(&mut self.fonts)?, }) } diff --git a/martin/src/lib.rs b/martin/src/lib.rs index 4d43b8acd..56b15358b 100644 --- a/martin/src/lib.rs +++ b/martin/src/lib.rs @@ -15,10 +15,12 @@ pub use utils::{ pub mod args; pub mod file_config; +#[cfg(feature = "fonts")] pub mod fonts; pub mod mbtiles; pub mod pg; pub mod pmtiles; +#[cfg(feature = "sprites")] pub mod sprites; pub mod srv; diff --git a/martin/src/srv/server.rs b/martin/src/srv/server.rs index 408441aac..ea173a38e 100755 --- a/martin/src/srv/server.rs +++ b/martin/src/srv/server.rs @@ -6,7 +6,7 @@ use actix_http::ContentEncoding; use actix_web::dev::Server; use actix_web::error::{ErrorBadRequest, ErrorInternalServerError, ErrorNotFound}; use actix_web::http::header::{ - AcceptEncoding, ContentType, Encoding as HeaderEnc, Preference, CACHE_CONTROL, CONTENT_ENCODING, + AcceptEncoding, Encoding as HeaderEnc, Preference, CACHE_CONTROL, CONTENT_ENCODING, }; use actix_web::http::Uri; use actix_web::middleware::TrailingSlash; @@ -23,8 +23,10 @@ use serde::{Deserialize, Serialize}; use tilejson::{tilejson, TileJSON}; use crate::config::ServerState; +#[cfg(feature = "fonts")] use crate::fonts::{FontCatalog, FontError, FontSources}; use crate::source::{Source, TileCatalog, TileSources, UrlQuery}; +#[cfg(feature = "sprites")] use crate::sprites::{SpriteCatalog, SpriteError, SpriteSources}; use crate::srv::config::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT}; use crate::utils::{decode_brotli, decode_gzip, encode_brotli, encode_gzip}; @@ -48,7 +50,9 @@ static SUPPORTED_ENCODINGS: &[HeaderEnc] = &[ #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct Catalog { pub tiles: TileCatalog, + #[cfg(feature = "sprites")] pub sprites: SpriteCatalog, + #[cfg(feature = "fonts")] pub fonts: FontCatalog, } @@ -56,7 +60,9 @@ impl Catalog { pub fn new(state: &ServerState) -> MartinResult { Ok(Self { tiles: state.tiles.get_catalog(), + #[cfg(feature = "sprites")] sprites: state.sprites.get_catalog()?, + #[cfg(feature = "fonts")] fonts: state.fonts.get_catalog(), }) } @@ -80,6 +86,7 @@ pub fn map_internal_error(e: T) -> actix_web::Error { ErrorInternalServerError(e.to_string()) } +#[cfg(feature = "sprites")] pub fn map_sprite_error(e: SpriteError) -> actix_web::Error { use SpriteError::SpriteNotFound; match e { @@ -88,6 +95,7 @@ pub fn map_sprite_error(e: SpriteError) -> actix_web::Error { } } +#[cfg(feature = "fonts")] pub fn map_font_error(e: FontError) -> actix_web::Error { #[allow(clippy::enum_glob_use)] use FontError::*; @@ -131,6 +139,7 @@ async fn get_catalog(catalog: Data) -> impl Responder { HttpResponse::Ok().json(catalog) } +#[cfg(feature = "sprites")] #[route("/sprite/{source_ids}.png", method = "GET", method = "HEAD")] async fn get_sprite_png( path: Path, @@ -141,10 +150,11 @@ async fn get_sprite_png( .await .map_err(map_sprite_error)?; Ok(HttpResponse::Ok() - .content_type(ContentType::png()) + .content_type(actix_web::http::header::ContentType::png()) .body(sheet.encode_png().map_err(map_internal_error)?)) } +#[cfg(feature = "sprites")] #[route( "/sprite/{source_ids}.json", method = "GET", @@ -162,6 +172,7 @@ async fn get_sprite_json( Ok(HttpResponse::Ok().json(sheet.get_index())) } +#[cfg(feature = "fonts")] #[derive(Deserialize, Debug)] struct FontRequest { fontstack: String, @@ -169,6 +180,7 @@ struct FontRequest { end: u32, } +#[cfg(feature = "fonts")] #[route( "/font/{fontstack}/{start}-{end}", method = "GET", @@ -495,10 +507,13 @@ pub fn router(cfg: &mut web::ServiceConfig) { .service(get_index) .service(get_catalog) .service(git_source_info) - .service(get_tile) - .service(get_sprite_json) - .service(get_sprite_png) - .service(get_font); + .service(get_tile); + + #[cfg(feature = "sprites")] + cfg.service(get_sprite_json).service(get_sprite_png); + + #[cfg(feature = "fonts")] + cfg.service(get_font); } /// Create a new initialized Actix `App` instance together with the listening address. @@ -515,11 +530,15 @@ pub fn new_server(config: SrvConfig, state: ServerState) -> MartinResult<(Server .allow_any_origin() .allowed_methods(vec!["GET"]); - App::new() - .app_data(Data::new(state.tiles.clone())) - .app_data(Data::new(state.sprites.clone())) - .app_data(Data::new(state.fonts.clone())) - .app_data(Data::new(catalog.clone())) + let app = App::new().app_data(Data::new(state.tiles.clone())); + + #[cfg(feature = "sprites")] + let app = app.app_data(Data::new(state.sprites.clone())); + + #[cfg(feature = "fonts")] + let app = app.app_data(Data::new(state.fonts.clone())); + + app.app_data(Data::new(catalog.clone())) .wrap(cors_middleware) .wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly)) .wrap(middleware::Logger::default()) diff --git a/martin/src/utils/error.rs b/martin/src/utils/error.rs index 3167e8a6d..e4a68e5b6 100644 --- a/martin/src/utils/error.rs +++ b/martin/src/utils/error.rs @@ -6,8 +6,10 @@ use std::path::PathBuf; use mbtiles::MbtError; use crate::file_config::FileError; +#[cfg(feature = "fonts")] use crate::fonts::FontError; use crate::pg::PgError; +#[cfg(feature = "sprites")] use crate::sprites::SpriteError; /// A convenience [`Result`] for Martin crate. @@ -65,9 +67,11 @@ pub enum MartinError { #[error(transparent)] FileError(#[from] FileError), + #[cfg(feature = "sprites")] #[error(transparent)] SpriteError(#[from] SpriteError), + #[cfg(feature = "fonts")] #[error(transparent)] FontError(#[from] FontError),