Implement /pgen/1
authorMegaBrutal <code+git@megabrutal.com>
Sun, 17 Jul 2022 17:45:00 +0000 (19:45 +0200)
committerMegaBrutal <code+git@megabrutal.com>
Sun, 17 Jul 2022 17:45:00 +0000 (19:45 +0200)
src/main.rs

index a391e4435bc4a20333bf6dde83e4e204a0fb11ac..293136508771f5ea1bf670e8ebf8be435fa143c2 100644 (file)
@@ -42,7 +42,8 @@ impl ResponseError for ImageError {
 
 #[derive(Debug)]
 enum CanvasError {
-    NotExists
+    NotExists,
+    DimensionMismatch
 }
 
 impl Display for CanvasError {
@@ -54,13 +55,15 @@ impl Display for CanvasError {
 impl ResponseError for CanvasError {
     fn status_code(&self) -> StatusCode {
         match &self {
-            CanvasError::NotExists => StatusCode::NOT_FOUND
+            CanvasError::NotExists => StatusCode::NOT_FOUND,
+            CanvasError::DimensionMismatch => StatusCode::BAD_REQUEST
         }
     }
 
     fn error_response(&self) -> HttpResponse<BoxBody> {
         match &self {
-            CanvasError::NotExists => HttpResponse::NotFound().body("Canvas does not exist.")
+            CanvasError::NotExists => HttpResponse::NotFound().body("Canvas does not exist."),
+            CanvasError::DimensionMismatch => HttpResponse::BadRequest().body("Supplied dimensions don't much the dimensions of existing canvas.")
         }
     }
 }
@@ -209,17 +212,48 @@ async fn img_pgen0(req: HttpRequest, canvas0: web::Data<Arc<Mutex<Option<Canvas>
        .body(cursor.into_inner()))
 }
 
+#[get("/pgen/1/{dim_x}/{dim_y}/{scale}/{data}")]
+async fn img_pgen1(req: HttpRequest, path: web::Path<(u32, u32, u32)>, canvas1: web::Data<Arc<Mutex<Option<Canvas>>>>) -> Result<impl Responder> {
+    let (dim_x, dim_y, scale) = path.into_inner();
+    let data = req.uri().path().split("/").skip(6).next().unwrap();
+    let img: RgbImage = {
+        let canvas_option = &mut *canvas1.lock().unwrap();
+        let canvas = canvas_option.take().unwrap_or_else( || Canvas::new(dim_x, dim_y) );
+        if (dim_x, dim_y) == canvas.img.dimensions() {
+            let canvas = rgb_encode_to_canvas(canvas, percent_decode_str(&data).into_iter().borrow_mut())?;
+            canvas_option.insert(canvas).img.clone()
+        }
+        else {
+            canvas_option.insert(canvas);
+            drop(canvas_option);
+            return Err(CanvasError::DimensionMismatch)?
+        }
+    };
+    let (tdim_x, tdim_y) = img.dimensions();
+    let (tdim_x, tdim_y) = (tdim_x * scale, tdim_y * scale);
+    let img = resize(&img, tdim_x, tdim_y, FilterType::Nearest);
+    let mut cursor = Cursor::new(Vec::new());
+    to_imageresult(write_buffer_with_format(&mut cursor, &img, tdim_x, tdim_y, ColorType::Rgb8, Png))?;
+    Ok(HttpResponse::build(StatusCode::OK)
+       .content_type("image/png")
+       .body(cursor.into_inner()))
+}
+
+
 #[actix_web::main] // or #[tokio::main]
 async fn main() -> std::io::Result<()> {
     env_logger::init();
     let canvas0 = Arc::new(Mutex::new(Some(Canvas::new(32, 32))));
+    let canvas1 = Arc::new(Mutex::new(None as Option<Canvas>));
     HttpServer::new(move || {
         App::new()
             .service(greet)
             .service(img_gen0)
             .service(img_gen1)
             .service(img_pgen0)
+            .service(img_pgen1)
             .app_data(web::Data::new(canvas0.clone()))
+            .app_data(web::Data::new(canvas1.clone()))
     })
     .bind(("127.0.0.1", 8080))?
     .run()