/rust/registry/src/index.crates.io-1949cf8c6b5b557f/http-body-util-0.1.3/src/either.rs
Line | Count | Source |
1 | | use std::error::Error; |
2 | | use std::fmt::Debug; |
3 | | use std::pin::Pin; |
4 | | use std::task::{Context, Poll}; |
5 | | |
6 | | use bytes::Buf; |
7 | | use http_body::{Body, Frame, SizeHint}; |
8 | | use proj::EitherProj; |
9 | | |
10 | | /// Sum type with two cases: [`Left`] and [`Right`], used if a body can be one of |
11 | | /// two distinct types. |
12 | | /// |
13 | | /// [`Left`]: Either::Left |
14 | | /// [`Right`]: Either::Right |
15 | | #[derive(Debug, Clone, Copy)] |
16 | | pub enum Either<L, R> { |
17 | | /// A value of type `L` |
18 | | Left(L), |
19 | | /// A value of type `R` |
20 | | Right(R), |
21 | | } |
22 | | |
23 | | impl<L, R> Either<L, R> { |
24 | | /// This function is part of the generated code from `pin-project-lite`, |
25 | | /// for a more in depth explanation and the rest of the generated code refer |
26 | | /// to the [`proj`] module. |
27 | 0 | pub(crate) fn project(self: Pin<&mut Self>) -> EitherProj<L, R> { |
28 | | unsafe { |
29 | 0 | match self.get_unchecked_mut() { |
30 | 0 | Self::Left(left) => EitherProj::Left(Pin::new_unchecked(left)), |
31 | 0 | Self::Right(right) => EitherProj::Right(Pin::new_unchecked(right)), |
32 | | } |
33 | | } |
34 | 0 | } |
35 | | } |
36 | | |
37 | | impl<L> Either<L, L> { |
38 | | /// Convert [`Either`] into the inner type, if both `Left` and `Right` are |
39 | | /// of the same type. |
40 | 0 | pub fn into_inner(self) -> L { |
41 | 0 | match self { |
42 | 0 | Either::Left(left) => left, |
43 | 0 | Either::Right(right) => right, |
44 | | } |
45 | 0 | } |
46 | | } |
47 | | |
48 | | impl<L, R, Data> Body for Either<L, R> |
49 | | where |
50 | | L: Body<Data = Data>, |
51 | | R: Body<Data = Data>, |
52 | | L::Error: Into<Box<dyn Error + Send + Sync>>, |
53 | | R::Error: Into<Box<dyn Error + Send + Sync>>, |
54 | | Data: Buf, |
55 | | { |
56 | | type Data = Data; |
57 | | type Error = Box<dyn Error + Send + Sync>; |
58 | | |
59 | 0 | fn poll_frame( |
60 | 0 | self: Pin<&mut Self>, |
61 | 0 | cx: &mut Context<'_>, |
62 | 0 | ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> { |
63 | 0 | match self.project() { |
64 | 0 | EitherProj::Left(left) => left |
65 | 0 | .poll_frame(cx) |
66 | 0 | .map(|poll| poll.map(|opt| opt.map_err(Into::into))), |
67 | 0 | EitherProj::Right(right) => right |
68 | 0 | .poll_frame(cx) |
69 | 0 | .map(|poll| poll.map(|opt| opt.map_err(Into::into))), |
70 | | } |
71 | 0 | } |
72 | | |
73 | 0 | fn is_end_stream(&self) -> bool { |
74 | 0 | match self { |
75 | 0 | Either::Left(left) => left.is_end_stream(), |
76 | 0 | Either::Right(right) => right.is_end_stream(), |
77 | | } |
78 | 0 | } |
79 | | |
80 | 0 | fn size_hint(&self) -> SizeHint { |
81 | 0 | match self { |
82 | 0 | Either::Left(left) => left.size_hint(), |
83 | 0 | Either::Right(right) => right.size_hint(), |
84 | | } |
85 | 0 | } |
86 | | } |
87 | | |
88 | | pub(crate) mod proj { |
89 | | //! This code is the (cleaned output) generated by [pin-project-lite], as it |
90 | | //! does not support tuple variants. |
91 | | //! |
92 | | //! This is the altered expansion from the following snippet, expanded by |
93 | | //! `cargo-expand`: |
94 | | //! |
95 | | //! ```rust |
96 | | //! use pin_project_lite::pin_project; |
97 | | //! |
98 | | //! pin_project! { |
99 | | //! #[project = EitherProj] |
100 | | //! pub enum Either<L, R> { |
101 | | //! Left {#[pin] left: L}, |
102 | | //! Right {#[pin] right: R} |
103 | | //! } |
104 | | //! } |
105 | | //! ``` |
106 | | //! |
107 | | //! [pin-project-lite]: https://docs.rs/pin-project-lite/latest/pin_project_lite/ |
108 | | use std::marker::PhantomData; |
109 | | use std::pin::Pin; |
110 | | |
111 | | use super::Either; |
112 | | |
113 | | #[allow(dead_code)] |
114 | | #[allow(single_use_lifetimes)] |
115 | | #[allow(unknown_lints)] |
116 | | #[allow(clippy::mut_mut)] |
117 | | #[allow(clippy::redundant_pub_crate)] |
118 | | #[allow(clippy::ref_option_ref)] |
119 | | #[allow(clippy::type_repetition_in_bounds)] |
120 | | pub(crate) enum EitherProj<'__pin, L, R> |
121 | | where |
122 | | Either<L, R>: '__pin, |
123 | | { |
124 | | Left(Pin<&'__pin mut L>), |
125 | | Right(Pin<&'__pin mut R>), |
126 | | } |
127 | | |
128 | | #[allow(single_use_lifetimes)] |
129 | | #[allow(unknown_lints)] |
130 | | #[allow(clippy::used_underscore_binding)] |
131 | | #[allow(missing_debug_implementations)] |
132 | | const _: () = { |
133 | | #[allow(non_snake_case)] |
134 | | pub struct __Origin<'__pin, L, R> { |
135 | | __dummy_lifetime: PhantomData<&'__pin ()>, |
136 | | _Left: L, |
137 | | _Right: R, |
138 | | } |
139 | | impl<'__pin, L, R> Unpin for Either<L, R> where __Origin<'__pin, L, R>: Unpin {} |
140 | | |
141 | | trait MustNotImplDrop {} |
142 | | #[allow(drop_bounds)] |
143 | | impl<T: Drop> MustNotImplDrop for T {} |
144 | | impl<L, R> MustNotImplDrop for Either<L, R> {} |
145 | | }; |
146 | | } |
147 | | |
148 | | #[cfg(test)] |
149 | | mod tests { |
150 | | use super::*; |
151 | | use crate::{BodyExt, Empty, Full}; |
152 | | |
153 | | #[tokio::test] |
154 | | async fn data_left() { |
155 | | let full = Full::new(&b"hello"[..]); |
156 | | |
157 | | let mut value: Either<_, Empty<&[u8]>> = Either::Left(full); |
158 | | |
159 | | assert_eq!(value.size_hint().exact(), Some(b"hello".len() as u64)); |
160 | | assert_eq!( |
161 | | value.frame().await.unwrap().unwrap().into_data().unwrap(), |
162 | | &b"hello"[..] |
163 | | ); |
164 | | assert!(value.frame().await.is_none()); |
165 | | } |
166 | | |
167 | | #[tokio::test] |
168 | | async fn data_right() { |
169 | | let full = Full::new(&b"hello!"[..]); |
170 | | |
171 | | let mut value: Either<Empty<&[u8]>, _> = Either::Right(full); |
172 | | |
173 | | assert_eq!(value.size_hint().exact(), Some(b"hello!".len() as u64)); |
174 | | assert_eq!( |
175 | | value.frame().await.unwrap().unwrap().into_data().unwrap(), |
176 | | &b"hello!"[..] |
177 | | ); |
178 | | assert!(value.frame().await.is_none()); |
179 | | } |
180 | | |
181 | | #[test] |
182 | | fn into_inner() { |
183 | | let a = Either::<i32, i32>::Left(2); |
184 | | assert_eq!(a.into_inner(), 2) |
185 | | } |
186 | | } |