mirror of
https://github.com/rwf2/Rocket.git
synced 2025-01-30 05:12:13 +00:00
Swap 'Rocket' manually without using 'replace_with'.
This commit is contained in:
parent
3ced188f7d
commit
9277ddafdf
@ -2,7 +2,7 @@ use std::io::{self, Cursor};
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Poll, Context};
|
use std::task::{Poll, Context};
|
||||||
|
|
||||||
use futures::{ready, Future, future::BoxFuture, stream::Stream};
|
use futures::{ready, future::BoxFuture, stream::Stream};
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt as _};
|
use tokio::io::{AsyncRead, AsyncReadExt as _};
|
||||||
|
|
||||||
use crate::http::hyper;
|
use crate::http::hyper;
|
||||||
@ -111,53 +111,3 @@ impl AsyncRead for AsyncReadBody {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The code below was adapted from the `replace_with` crate and reproduced here
|
|
||||||
// under the rights granted by the MIT license. The code is copyright the
|
|
||||||
// `replace_with` developers. See LICENSE-MIT for the full text.
|
|
||||||
|
|
||||||
struct OnUnwind<F: FnOnce()>(std::mem::ManuallyDrop<F>);
|
|
||||||
|
|
||||||
impl<F: FnOnce()> Drop for OnUnwind<F> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn drop(&mut self) {
|
|
||||||
(unsafe { std::ptr::read(&*self.0) })();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub async fn async_on_unwind<F, Fut, T, P: FnOnce()>(f: F, p: P) -> T
|
|
||||||
where F: FnOnce() -> Fut, Fut: Future<Output = T>,
|
|
||||||
{
|
|
||||||
let x = OnUnwind(std::mem::ManuallyDrop::new(p));
|
|
||||||
let t = f().await;
|
|
||||||
let _ = unsafe { std::ptr::read(&*x.0) };
|
|
||||||
std::mem::forget(x);
|
|
||||||
t
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub async fn async_replace_with_or_else<T, Fut, F, D>(dest: &mut T, d: D, f: F)
|
|
||||||
where Fut: Future<Output = T>,
|
|
||||||
F: FnOnce(T) -> Fut,
|
|
||||||
D: FnOnce() -> T,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
let old = std::ptr::read(dest);
|
|
||||||
let new = async_on_unwind(
|
|
||||||
|| async move { f(old).await },
|
|
||||||
|| std::ptr::write(dest, d()),
|
|
||||||
).await;
|
|
||||||
|
|
||||||
std::ptr::write(dest, new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub async fn async_replace_with<T, Fut, F>(dest: &mut T, f: F)
|
|
||||||
where Fut: Future<Output = T>,
|
|
||||||
F: FnOnce(T) -> Fut,
|
|
||||||
{
|
|
||||||
async_replace_with_or_else(dest, || std::process::abort(), f).await
|
|
||||||
}
|
|
||||||
|
@ -24,7 +24,7 @@ use crate::outcome::Outcome;
|
|||||||
use crate::error::{LaunchError, LaunchErrorKind};
|
use crate::error::{LaunchError, LaunchErrorKind};
|
||||||
use crate::fairing::{Fairing, Fairings};
|
use crate::fairing::{Fairing, Fairings};
|
||||||
use crate::logger::PaintExt;
|
use crate::logger::PaintExt;
|
||||||
use crate::ext::{AsyncReadExt, async_replace_with};
|
use crate::ext::AsyncReadExt;
|
||||||
use crate::shutdown::{ShutdownHandle, ShutdownHandleManaged};
|
use crate::shutdown::{ShutdownHandle, ShutdownHandleManaged};
|
||||||
|
|
||||||
use crate::http::{Method, Status, Header};
|
use crate::http::{Method, Status, Header};
|
||||||
@ -109,6 +109,21 @@ impl Rocket {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a "dummy" instance of `Rocket` to use while mem-swapping `self`.
|
||||||
|
fn dummy() -> Rocket {
|
||||||
|
Rocket {
|
||||||
|
manifest: vec![],
|
||||||
|
config: Config::development(),
|
||||||
|
router: Router::new(),
|
||||||
|
default_catchers: HashMap::new(),
|
||||||
|
catchers: HashMap::new(),
|
||||||
|
managed_state: Container::new(),
|
||||||
|
fairings: Fairings::new(),
|
||||||
|
shutdown_handle: ShutdownHandle(mpsc::channel(1).0),
|
||||||
|
shutdown_receiver: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Instead of requiring the user to individually `await` each call to
|
// Instead of requiring the user to individually `await` each call to
|
||||||
// `attach()`, some operations are queued in `self.pending`. Functions that
|
// `attach()`, some operations are queued in `self.pending`. Functions that
|
||||||
// want to provide read access to any data from the Cargo, such as
|
// want to provide read access to any data from the Cargo, such as
|
||||||
@ -133,7 +148,8 @@ impl Rocket {
|
|||||||
PreLaunchOp::Mount(base, routes) => self._mount(base, routes),
|
PreLaunchOp::Mount(base, routes) => self._mount(base, routes),
|
||||||
PreLaunchOp::Register(catchers) => self._register(catchers),
|
PreLaunchOp::Register(catchers) => self._register(catchers),
|
||||||
PreLaunchOp::Attach(fairing) => {
|
PreLaunchOp::Attach(fairing) => {
|
||||||
async_replace_with(self, |rocket| rocket._attach(fairing)).await;
|
let rocket = mem::replace(self, Rocket::dummy());
|
||||||
|
*self = rocket._attach(fairing).await;
|
||||||
self.manifest.append(&mut manifest);
|
self.manifest.append(&mut manifest);
|
||||||
manifest = mem::replace(&mut self.manifest, vec![]);
|
manifest = mem::replace(&mut self.manifest, vec![]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user