From 475db6af797fa80996fe2a8f50ce006c95c3b2a2 Mon Sep 17 00:00:00 2001 From: Emi Tatsuo Date: Thu, 19 Nov 2020 11:09:53 -0500 Subject: [PATCH] Adapted a type from futures-util allowing us to drop the dep and remove a big chunk of the dep tree --- Cargo.toml | 1 - src/lib.rs | 5 ++--- src/util.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 62743e8..9ad991d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ mime = "0.3.16" uriparse = "0.6.3" percent-encoding = "2.1.0" futures-core = "0.3.7" -futures-util = "0.3.7" log = "0.4.11" webpki = "0.21.0" lazy_static = "1.4.0" diff --git a/src/lib.rs b/src/lib.rs index 2083e0f..9b1ad5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ use std::{ time::Duration, }; use futures_core::future::BoxFuture; -use futures_util::future::FutureExt; use tokio::{ prelude::*, io::{self, BufStream}, @@ -33,7 +32,7 @@ pub const REQUEST_URI_MAX_LEN: usize = 1024; pub const GEMINI_PORT: u16 = 1965; type Handler = Arc HandlerResponse + Send + Sync>; -type HandlerResponse = BoxFuture<'static, Result>; +pub (crate) type HandlerResponse = BoxFuture<'static, Result>; #[derive(Clone)] pub struct Server { @@ -94,7 +93,7 @@ impl Server { let handler = (self.handler)(request); let handler = AssertUnwindSafe(handler); - let response = handler.catch_unwind().await + let response = util::HandlerCatchUnwind::new(handler).await .unwrap_or_else(|_| Response::server_error("")) .or_else(|err| { error!("Handler failed: {:?}", err); diff --git a/src/util.rs b/src/util.rs index ac774a2..628b018 100644 --- a/src/util.rs +++ b/src/util.rs @@ -11,6 +11,9 @@ use tokio::{ }; #[cfg(feature="serve_dir")] use crate::types::{Response, Document, document::HeadingLevel::*}; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::task::Poll; +use futures_core::future::Future; #[cfg(feature="serve_dir")] pub async fn serve_file>(path: P, mime: &Mime) -> Result { @@ -123,3 +126,32 @@ where C: AsRef + Into, T: ToOwned + ?Sized, {} + +/// A utility for catching unwinds on Futures. +/// +/// This is adapted from the futures-rs CatchUnwind, in an effort to reduce the large +/// amount of dependencies tied into the feature that provides this simple struct. +#[must_use = "futures do nothing unless polled"] +pub (crate) struct HandlerCatchUnwind { + future: AssertUnwindSafe, +} + +impl HandlerCatchUnwind { + pub(super) fn new(future: AssertUnwindSafe) -> Self { + Self { future } + } +} + +impl Future for HandlerCatchUnwind { + type Output = Result, Box>; + + fn poll( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context + ) -> Poll { + match catch_unwind(AssertUnwindSafe(|| self.future.as_mut().poll(cx))) { + Ok(res) => res.map(Ok), + Err(e) => Poll::Ready(Err(e)) + } + } +}