Skip to content

Commit

Permalink
Minor sprites refactoring (#751)
Browse files Browse the repository at this point in the history
  • Loading branch information
nyurik authored Jul 7, 2023
1 parent 27a5d63 commit 2829212
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 25 deletions.
23 changes: 20 additions & 3 deletions martin/src/sprites/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::collections::HashMap;
use std::fmt::Debug;
use std::path::PathBuf;

use actix_web::error::ErrorNotFound;
use futures::future::try_join_all;
use log::{info, warn};
use spreet::fs::get_svg_input_paths;
Expand All @@ -16,6 +15,9 @@ use crate::file_config::{FileConfigEnum, FileError};

#[derive(thiserror::Error, Debug)]
pub enum SpriteError {
#[error("Sprite {0} not found")]
SpriteNotFound(String),

#[error("IO error {0}: {}", .1.display())]
IoError(std::io::Error, PathBuf),

Expand Down Expand Up @@ -96,10 +98,25 @@ fn add_source(id: String, path: PathBuf, results: &mut SpriteSources) {
pub struct SpriteSources(HashMap<String, SpriteSource>);

impl SpriteSources {
pub fn get_sprite_source(&self, id: &str) -> actix_web::Result<&SpriteSource> {
pub fn get_sprite_source(&self, id: &str) -> Result<&SpriteSource, SpriteError> {
self.0
.get(id)
.ok_or_else(|| ErrorNotFound(format!("Sprite {id} does not exist")))
.ok_or_else(|| SpriteError::SpriteNotFound(id.to_string()))
}

/// Given a list of IDs in a format "id1,id2,id3", return a spritesheet with them all.
/// `ids` may optionally end with "@2x" to request a high-DPI spritesheet.
pub async fn get_sprites(&self, ids: &str) -> Result<Spritesheet, SpriteError> {
let (ids, dpi) = if let Some(ids) = ids.strip_suffix("@2x") {
(ids, 2)
} else {
(ids, 1)
};
let sprite_ids = ids
.split(',')
.map(|id| self.get_sprite_source(id))
.collect::<Result<Vec<_>, SpriteError>>()?;
get_spritesheet(sprite_ids.into_iter(), dpi).await
}
}

Expand Down
42 changes: 20 additions & 22 deletions martin/src/srv/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@ use actix_web::http::Uri;
use actix_web::middleware::TrailingSlash;
use actix_web::web::{Data, Path, Query};
use actix_web::{
error, middleware, route, web, App, Error, HttpMessage, HttpRequest, HttpResponse, HttpServer,
error, middleware, route, web, App, HttpMessage, HttpRequest, HttpResponse, HttpServer,
Responder, Result,
};
use futures::future::try_join_all;
use log::error;
use martin_tile_utils::{Encoding, Format, TileInfo};
use serde::Deserialize;
use spreet::sprite::Spritesheet;
use tilejson::{tilejson, TileJSON};

use crate::config::AllSources;
use crate::source::{Source, Sources, UrlQuery, Xyz};
use crate::sprites::{get_spritesheet, SpriteSources};
use crate::sprites::{SpriteError, SpriteSources};
use crate::srv::config::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT};
use crate::utils::{decode_brotli, decode_gzip, encode_brotli, encode_gzip};
use crate::Error::BindingError;
Expand Down Expand Up @@ -56,11 +55,19 @@ struct TileRequest {
y: u32,
}

fn map_internal_error<T: std::fmt::Display>(e: T) -> Error {
pub fn map_internal_error<T: std::fmt::Display>(e: T) -> actix_web::Error {
error!("{e}");
error::ErrorInternalServerError(e.to_string())
}

pub fn map_sprite_error(e: SpriteError) -> actix_web::Error {
if let SpriteError::SpriteNotFound(_) = e {
error::ErrorNotFound(e.to_string())
} else {
map_internal_error(e)
}
}

/// Root path will eventually have a web front. For now, just a stub.
#[route("/", method = "GET", method = "HEAD")]
#[allow(clippy::unused_async)]
Expand Down Expand Up @@ -95,34 +102,25 @@ async fn get_sprite_png(
path: Path<TileJsonRequest>,
sprites: Data<SpriteSources>,
) -> Result<HttpResponse> {
let ss = get_sprite_int(&path.source_ids, &sprites).await?;
let sheet = sprites
.get_sprites(&path.source_ids)
.await
.map_err(map_sprite_error)?;
Ok(HttpResponse::Ok()
.content_type(ContentType::png())
.body(ss.encode_png().map_err(map_internal_error)?))
.body(sheet.encode_png().map_err(map_internal_error)?))
}

#[route("/sprite/{source_ids}.json", method = "GET", method = "HEAD")]
async fn get_sprite_json(
path: Path<TileJsonRequest>,
sprites: Data<SpriteSources>,
) -> Result<HttpResponse> {
let ss = get_sprite_int(&path.source_ids, &sprites).await?;
Ok(HttpResponse::Ok().json(ss.get_index()))
}

async fn get_sprite_int(ids: &str, sprites: &SpriteSources) -> Result<Spritesheet> {
let (ids, dpi) = if let Some(ids) = ids.strip_suffix("@2x") {
(ids, 2)
} else {
(ids, 1)
};
let sprite_ids = ids
.split(',')
.map(|id| sprites.get_sprite_source(id))
.collect::<Result<Vec<_>>>()?;
get_spritesheet(sprite_ids.into_iter(), dpi)
let sheet = sprites
.get_sprites(&path.source_ids)
.await
.map_err(map_internal_error)
.map_err(map_sprite_error)?;
Ok(HttpResponse::Ok().json(sheet.get_index()))
}

#[route(
Expand Down

0 comments on commit 2829212

Please sign in to comment.