| 1 | use http::HeaderMap; |
| 2 | |
| 3 | /// A frame of any kind related to an HTTP stream (body). |
| 4 | #[derive (Debug)] |
| 5 | pub struct Frame<T> { |
| 6 | kind: Kind<T>, |
| 7 | } |
| 8 | |
| 9 | #[derive (Debug)] |
| 10 | enum Kind<T> { |
| 11 | // The first two variants are "inlined" since they are undoubtedly |
| 12 | // the most common. This saves us from having to allocate a |
| 13 | // boxed trait object for them. |
| 14 | Data(T), |
| 15 | Trailers(HeaderMap), |
| 16 | //Unknown(Box<dyn Frameish>), |
| 17 | } |
| 18 | |
| 19 | impl<T> Frame<T> { |
| 20 | /// Create a DATA frame with the provided `Buf`. |
| 21 | pub fn data(buf: T) -> Self { |
| 22 | Self { |
| 23 | kind: Kind::Data(buf), |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | /// Create a trailers frame. |
| 28 | pub fn trailers(map: HeaderMap) -> Self { |
| 29 | Self { |
| 30 | kind: Kind::Trailers(map), |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | /// Maps this frame's data to a different type. |
| 35 | pub fn map_data<F, D>(self, f: F) -> Frame<D> |
| 36 | where |
| 37 | F: FnOnce(T) -> D, |
| 38 | { |
| 39 | match self.kind { |
| 40 | Kind::Data(data) => Frame { |
| 41 | kind: Kind::Data(f(data)), |
| 42 | }, |
| 43 | Kind::Trailers(trailers) => Frame { |
| 44 | kind: Kind::Trailers(trailers), |
| 45 | }, |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | /// Returns whether this is a DATA frame. |
| 50 | pub fn is_data(&self) -> bool { |
| 51 | matches!(self.kind, Kind::Data(..)) |
| 52 | } |
| 53 | |
| 54 | /// Consumes self into the buf of the DATA frame. |
| 55 | /// |
| 56 | /// Returns an [`Err`] containing the original [`Frame`] when frame is not a DATA frame. |
| 57 | /// `Frame::is_data` can also be used to determine if the frame is a DATA frame. |
| 58 | pub fn into_data(self) -> Result<T, Self> { |
| 59 | match self.kind { |
| 60 | Kind::Data(data) => Ok(data), |
| 61 | _ => Err(self), |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | /// If this is a DATA frame, returns a reference to it. |
| 66 | /// |
| 67 | /// Returns `None` if not a DATA frame. |
| 68 | pub fn data_ref(&self) -> Option<&T> { |
| 69 | match self.kind { |
| 70 | Kind::Data(ref data) => Some(data), |
| 71 | _ => None, |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | /// If this is a DATA frame, returns a mutable reference to it. |
| 76 | /// |
| 77 | /// Returns `None` if not a DATA frame. |
| 78 | pub fn data_mut(&mut self) -> Option<&mut T> { |
| 79 | match self.kind { |
| 80 | Kind::Data(ref mut data) => Some(data), |
| 81 | _ => None, |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /// Returns whether this is a trailers frame. |
| 86 | pub fn is_trailers(&self) -> bool { |
| 87 | matches!(self.kind, Kind::Trailers(..)) |
| 88 | } |
| 89 | |
| 90 | /// Consumes self into the buf of the trailers frame. |
| 91 | /// |
| 92 | /// Returns an [`Err`] containing the original [`Frame`] when frame is not a trailers frame. |
| 93 | /// `Frame::is_trailers` can also be used to determine if the frame is a trailers frame. |
| 94 | pub fn into_trailers(self) -> Result<HeaderMap, Self> { |
| 95 | match self.kind { |
| 96 | Kind::Trailers(trailers) => Ok(trailers), |
| 97 | _ => Err(self), |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | /// If this is a trailers frame, returns a reference to it. |
| 102 | /// |
| 103 | /// Returns `None` if not a trailers frame. |
| 104 | pub fn trailers_ref(&self) -> Option<&HeaderMap> { |
| 105 | match self.kind { |
| 106 | Kind::Trailers(ref trailers) => Some(trailers), |
| 107 | _ => None, |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | /// If this is a trailers frame, returns a mutable reference to it. |
| 112 | /// |
| 113 | /// Returns `None` if not a trailers frame. |
| 114 | pub fn trailers_mut(&mut self) -> Option<&mut HeaderMap> { |
| 115 | match self.kind { |
| 116 | Kind::Trailers(ref mut trailers) => Some(trailers), |
| 117 | _ => None, |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |