+use std::convert::From;
use std::io::Cursor;
use std::fmt::Display;
use std::fmt;
#[derive(Debug)]
enum CanvasError {
NotExists,
- DimensionMismatch
+ DimensionMismatch,
+ ImageError(ImageError)
}
impl Display for CanvasError {
fn status_code(&self) -> StatusCode {
match &self {
CanvasError::NotExists => StatusCode::NOT_FOUND,
- CanvasError::DimensionMismatch => StatusCode::BAD_REQUEST
+ CanvasError::DimensionMismatch => StatusCode::BAD_REQUEST,
+ CanvasError::ImageError(e) => e.status_code()
}
}
fn error_response(&self) -> HttpResponse<BoxBody> {
match &self {
CanvasError::NotExists => HttpResponse::NotFound().body("Canvas does not exist."),
- CanvasError::DimensionMismatch => HttpResponse::BadRequest().body("Supplied dimensions don't much the dimensions of existing canvas.")
+ CanvasError::DimensionMismatch => HttpResponse::BadRequest().body("Supplied dimensions don't much the dimensions of existing canvas."),
+ CanvasError::ImageError(e) => e.error_response()
}
}
}
+impl From<ImageError> for CanvasError {
+ fn from(e: ImageError) -> CanvasError {
+ CanvasError::ImageError(e)
+ }
+}
+
struct ToRgbIter<'a, T> where T: AsPrimitive<u8> {
iter: Box<&'a mut dyn Iterator<Item = T>>
}
}
}
+fn to_canvasresult<T: std::fmt::Debug> (result: Result<T, ImageError>) -> Result<T, CanvasError> {
+ println!("Converting to canvasresult: {:?}", result);
+ match result {
+ Ok(v) => Ok(v),
+ Err(e) => Err(CanvasError::ImageError(e))
+ }
+}
+
+#[derive(Debug)]
struct Canvas {
pen: usize,
img: RgbImage
Ok(rgb_encode_to_canvas(Canvas::from_image(img), data)?.img)
}
+fn apply_to_canvas<'a, F>(f: F, canvas_option: &'a mut Option<Canvas>, dimensions: Option<(u32, u32)>, data: &str) -> Result<&'a mut Canvas, CanvasError>
+ where F: Fn(Canvas, &mut dyn Iterator<Item = u8>) -> Result<Canvas, CanvasError>
+{
+ let canvas = match canvas_option.take() {
+ Some(canvas) => match dimensions {
+ Some(dimensions) => {
+ if dimensions == canvas.img.dimensions() {
+ Ok(canvas)
+ }
+ else {
+ _ = canvas_option.insert(canvas);
+ Err(CanvasError::DimensionMismatch)
+ }
+ },
+ None =>
+ Ok(canvas)
+ },
+ None => match dimensions {
+ Some((dim_x, dim_y)) =>
+ Ok(Canvas::new(dim_x, dim_y)),
+ None =>
+ Err(CanvasError::NotExists)
+ }
+ }?;
+
+ Ok(canvas_option.insert(f(canvas, percent_decode_str(&data).into_iter().borrow_mut())?))
+}
+
fn make_png(dim_x: u32, dim_y: u32, scale: u32, data: &mut dyn Iterator<Item = u8>) -> Result<Cursor<Vec<u8>>, ImageError> {
// Image must not be larger than 1 megapixel
if dim_x * dim_y * scale > 1048576 {
let data = req.uri().path().split("/").skip(3).next().unwrap();
let mut cursor = Cursor::new(Vec::new());
let scale = 16;
- let img: RgbImage = {
+ let img: RgbImage = ({
let canvas_option = &mut *canvas0.lock().unwrap();
- let canvas = canvas_option.take().ok_or(CanvasError::NotExists)?;
- let canvas = rgb_encode_to_canvas(canvas, percent_decode_str(&data).into_iter().borrow_mut())?;
- canvas_option.insert(canvas).img.clone()
- };
+ Ok(apply_to_canvas( |c, d| to_canvasresult(rgb_encode_to_canvas(c, d)), canvas_option, None, data)?.img.clone())
+ } as Result<RgbImage, CanvasError>)?;
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);
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 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())?;
- Ok(canvas_option.insert(canvas).img.clone())
- }
- else {
- _ = canvas_option.insert(canvas);
- Err(CanvasError::DimensionMismatch)
- }
- }?;
+ Ok(apply_to_canvas( |c, d| to_canvasresult(rgb_encode_to_canvas(c, d)), canvas_option, Some((dim_x, dim_y)), data)?.img.clone())
+ } as Result<RgbImage, CanvasError>)?;
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);