|
1 |
| -use std::{future::Future, task::Poll}; |
| 1 | +use std::{ |
| 2 | + future::Future, |
| 3 | + mem::{ManuallyDrop, MaybeUninit}, |
| 4 | + ops::DerefMut, |
| 5 | + pin::Pin, |
| 6 | + task::Poll, |
| 7 | +}; |
2 | 8 |
|
3 | 9 | use http::{HeaderValue, Request, Response, StatusCode};
|
4 | 10 | use monoio_http::common::body::FixedBody;
|
5 | 11 | use monolake_core::http::{HttpError, HttpHandler, ResponseWithContinue};
|
6 | 12 | use service_async::Service;
|
7 | 13 |
|
8 |
| -pin_project_lite::pin_project! { |
9 |
| - /// AccompanyPair for http decoder and processor. |
10 |
| - /// We have to fill payload when process request |
11 |
| - /// since inner logic may read chunked body; also |
12 |
| - /// fill payload when process response since we |
13 |
| - /// may use the request body stream in response |
14 |
| - /// body stream. |
15 |
| - pub(crate) struct AccompanyPair<FMAIN, FACC, T> { |
16 |
| - #[pin] |
17 |
| - main: FMAIN, |
18 |
| - #[pin] |
19 |
| - accompany: FACC, |
20 |
| - accompany_slot: Option<T> |
| 14 | +union Union<A, B> { |
| 15 | + a: ManuallyDrop<A>, |
| 16 | + b: ManuallyDrop<B>, |
| 17 | +} |
| 18 | + |
| 19 | +/// AccompanyPair for http decoder and processor. |
| 20 | +/// We have to fill payload when process request |
| 21 | +/// since inner logic may read chunked body; also |
| 22 | +/// fill payload when process response since we |
| 23 | +/// may use the request body stream in response |
| 24 | +/// body stream. |
| 25 | +pub(crate) struct AccompanyPairBase<F1, F2, FACC, T> { |
| 26 | + main: MaybeUninit<Union<F1, F2>>, |
| 27 | + accompany: FACC, |
| 28 | + accompany_slot: Option<T>, |
| 29 | +} |
| 30 | + |
| 31 | +impl<F1, F2, FACC, T> AccompanyPairBase<F1, F2, FACC, T> { |
| 32 | + pub(crate) const fn new(accompany: FACC) -> Self { |
| 33 | + Self { |
| 34 | + main: MaybeUninit::uninit(), |
| 35 | + accompany, |
| 36 | + accompany_slot: None, |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + pub(crate) fn stage1( |
| 41 | + mut self: Pin<&mut Self>, |
| 42 | + future1: F1, |
| 43 | + ) -> AccompanyPairS1<F1, F2, FACC, T> { |
| 44 | + unsafe { |
| 45 | + self.as_mut().get_unchecked_mut().main.assume_init_mut().a = ManuallyDrop::new(future1); |
| 46 | + } |
| 47 | + AccompanyPairS1(self) |
| 48 | + } |
| 49 | + |
| 50 | + pub(crate) fn stage2( |
| 51 | + mut self: Pin<&mut Self>, |
| 52 | + future2: F2, |
| 53 | + ) -> AccompanyPairS2<F1, F2, FACC, T> { |
| 54 | + unsafe { |
| 55 | + self.as_mut().get_unchecked_mut().main.assume_init_mut().b = ManuallyDrop::new(future2); |
| 56 | + } |
| 57 | + AccompanyPairS2(self) |
| 58 | + } |
| 59 | + |
| 60 | + pub(crate) const fn stage3(self: Pin<&mut Self>) -> AccompanyPairS3<F1, F2, FACC, T> { |
| 61 | + AccompanyPairS3(self) |
21 | 62 | }
|
22 | 63 | }
|
23 | 64 |
|
24 |
| -pin_project_lite::pin_project! { |
25 |
| - /// Accompany for http decoder and processor. |
26 |
| - pub(crate) struct Accompany<FACC, T> { |
27 |
| - #[pin] |
28 |
| - accompany: FACC, |
29 |
| - accompany_slot: Option<T> |
| 65 | +#[repr(transparent)] |
| 66 | +pub(crate) struct AccompanyPairS1<'a, F1, F2, FACC, T>( |
| 67 | + Pin<&'a mut AccompanyPairBase<F1, F2, FACC, T>>, |
| 68 | +); |
| 69 | + |
| 70 | +impl<F1, F2, FACC, T> Drop for AccompanyPairS1<'_, F1, F2, FACC, T> { |
| 71 | + fn drop(&mut self) { |
| 72 | + unsafe { |
| 73 | + ManuallyDrop::drop(&mut self.0.as_mut().get_unchecked_mut().main.assume_init_mut().a); |
| 74 | + } |
30 | 75 | }
|
31 | 76 | }
|
32 | 77 |
|
33 |
| -impl<FMAIN, FACC, T> Future for AccompanyPair<FMAIN, FACC, T> |
| 78 | +impl<F1, F2, FACC, T> Future for AccompanyPairS1<'_, F1, F2, FACC, T> |
34 | 79 | where
|
35 |
| - FMAIN: Future, |
| 80 | + F1: Future, |
36 | 81 | FACC: Future<Output = T>,
|
37 | 82 | {
|
38 |
| - type Output = FMAIN::Output; |
| 83 | + type Output = F1::Output; |
39 | 84 |
|
40 |
| - fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> { |
41 |
| - let this = self.project(); |
| 85 | + fn poll( |
| 86 | + mut self: std::pin::Pin<&mut Self>, |
| 87 | + cx: &mut std::task::Context<'_>, |
| 88 | + ) -> Poll<Self::Output> { |
| 89 | + let this = unsafe { self.0.as_mut().get_unchecked_mut() }; |
42 | 90 | if this.accompany_slot.is_none()
|
43 |
| - && let Poll::Ready(t) = this.accompany.poll(cx) |
| 91 | + && let Poll::Ready(t) = unsafe { Pin::new_unchecked(&mut this.accompany) }.poll(cx) |
44 | 92 | {
|
45 |
| - *this.accompany_slot = Some(t); |
| 93 | + this.accompany_slot = Some(t); |
46 | 94 | }
|
47 |
| - this.main.poll(cx) |
| 95 | + unsafe { Pin::new_unchecked(this.main.assume_init_mut().a.deref_mut()).poll(cx) } |
48 | 96 | }
|
49 | 97 | }
|
50 | 98 |
|
51 |
| -impl<FACC, T> Future for Accompany<FACC, T> |
| 99 | +#[repr(transparent)] |
| 100 | +pub(crate) struct AccompanyPairS2<'a, F1, F2, FACC, T>( |
| 101 | + Pin<&'a mut AccompanyPairBase<F1, F2, FACC, T>>, |
| 102 | +); |
| 103 | + |
| 104 | +impl<F1, F2, FACC, T> Drop for AccompanyPairS2<'_, F1, F2, FACC, T> { |
| 105 | + fn drop(&mut self) { |
| 106 | + unsafe { |
| 107 | + ManuallyDrop::drop(&mut self.0.as_mut().get_unchecked_mut().main.assume_init_mut().b); |
| 108 | + } |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | +impl<F1, F2, FACC, T> Future for AccompanyPairS2<'_, F1, F2, FACC, T> |
52 | 113 | where
|
| 114 | + F2: Future, |
53 | 115 | FACC: Future<Output = T>,
|
54 | 116 | {
|
55 |
| - type Output = T; |
| 117 | + type Output = F2::Output; |
56 | 118 |
|
57 |
| - fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> { |
58 |
| - let this = self.project(); |
59 |
| - if let Some(t) = this.accompany_slot.take() { |
60 |
| - return Poll::Ready(t); |
| 119 | + fn poll( |
| 120 | + mut self: std::pin::Pin<&mut Self>, |
| 121 | + cx: &mut std::task::Context<'_>, |
| 122 | + ) -> Poll<Self::Output> { |
| 123 | + let this = unsafe { self.0.as_mut().get_unchecked_mut() }; |
| 124 | + if this.accompany_slot.is_none() |
| 125 | + && let Poll::Ready(t) = unsafe { Pin::new_unchecked(&mut this.accompany) }.poll(cx) |
| 126 | + { |
| 127 | + this.accompany_slot = Some(t); |
61 | 128 | }
|
62 |
| - this.accompany.poll(cx) |
| 129 | + unsafe { Pin::new_unchecked(this.main.assume_init_mut().b.deref_mut()).poll(cx) } |
63 | 130 | }
|
64 | 131 | }
|
65 | 132 |
|
66 |
| -impl<FMAIN, FACC, T> AccompanyPair<FMAIN, FACC, T> { |
67 |
| - pub(crate) fn new(main: FMAIN, accompany: FACC) -> Self { |
68 |
| - Self { |
69 |
| - main, |
70 |
| - accompany, |
71 |
| - accompany_slot: None, |
72 |
| - } |
73 |
| - } |
| 133 | +#[repr(transparent)] |
| 134 | +pub(crate) struct AccompanyPairS3<'a, F1, F2, FACC, T>( |
| 135 | + Pin<&'a mut AccompanyPairBase<F1, F2, FACC, T>>, |
| 136 | +); |
74 | 137 |
|
75 |
| - pub(crate) fn replace<FMAIN2>(self, main: FMAIN2) -> AccompanyPair<FMAIN2, FACC, T> { |
76 |
| - AccompanyPair { |
77 |
| - main, |
78 |
| - accompany: self.accompany, |
79 |
| - accompany_slot: self.accompany_slot, |
80 |
| - } |
81 |
| - } |
| 138 | +impl<F1, F2, FACC: Future<Output = T>, T> Future for AccompanyPairS3<'_, F1, F2, FACC, T> { |
| 139 | + type Output = FACC::Output; |
82 | 140 |
|
83 |
| - pub(crate) fn into_accompany(self) -> Accompany<FACC, T> { |
84 |
| - Accompany { |
85 |
| - accompany: self.accompany, |
86 |
| - accompany_slot: self.accompany_slot, |
| 141 | + fn poll( |
| 142 | + mut self: std::pin::Pin<&mut Self>, |
| 143 | + cx: &mut std::task::Context<'_>, |
| 144 | + ) -> Poll<Self::Output> { |
| 145 | + let this = unsafe { self.0.as_mut().get_unchecked_mut() }; |
| 146 | + if let Some(t) = this.accompany_slot.take() { |
| 147 | + return Poll::Ready(t); |
87 | 148 | }
|
| 149 | + unsafe { Pin::new_unchecked(&mut this.accompany) }.poll(cx) |
88 | 150 | }
|
89 | 151 | }
|
90 | 152 |
|
|
0 commit comments