summaryrefslogtreecommitdiffstats
path: root/third_party/rust/h2/src/frame/data.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/h2/src/frame/data.rs')
-rw-r--r--third_party/rust/h2/src/frame/data.rs233
1 files changed, 233 insertions, 0 deletions
diff --git a/third_party/rust/h2/src/frame/data.rs b/third_party/rust/h2/src/frame/data.rs
new file mode 100644
index 0000000000..e253d5e23d
--- /dev/null
+++ b/third_party/rust/h2/src/frame/data.rs
@@ -0,0 +1,233 @@
+use crate::frame::{util, Error, Frame, Head, Kind, StreamId};
+use bytes::{Buf, BufMut, Bytes};
+
+use std::fmt;
+
+/// Data frame
+///
+/// Data frames convey arbitrary, variable-length sequences of octets associated
+/// with a stream. One or more DATA frames are used, for instance, to carry HTTP
+/// request or response payloads.
+#[derive(Eq, PartialEq)]
+pub struct Data<T = Bytes> {
+ stream_id: StreamId,
+ data: T,
+ flags: DataFlags,
+ pad_len: Option<u8>,
+}
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+struct DataFlags(u8);
+
+const END_STREAM: u8 = 0x1;
+const PADDED: u8 = 0x8;
+const ALL: u8 = END_STREAM | PADDED;
+
+impl<T> Data<T> {
+ /// Creates a new DATA frame.
+ pub fn new(stream_id: StreamId, payload: T) -> Self {
+ assert!(!stream_id.is_zero());
+
+ Data {
+ stream_id,
+ data: payload,
+ flags: DataFlags::default(),
+ pad_len: None,
+ }
+ }
+
+ /// Returns the stream identifier that this frame is associated with.
+ ///
+ /// This cannot be a zero stream identifier.
+ pub fn stream_id(&self) -> StreamId {
+ self.stream_id
+ }
+
+ /// Gets the value of the `END_STREAM` flag for this frame.
+ ///
+ /// If true, this frame is the last that the endpoint will send for the
+ /// identified stream.
+ ///
+ /// Setting this flag causes the stream to enter one of the "half-closed"
+ /// states or the "closed" state (Section 5.1).
+ pub fn is_end_stream(&self) -> bool {
+ self.flags.is_end_stream()
+ }
+
+ /// Sets the value for the `END_STREAM` flag on this frame.
+ pub fn set_end_stream(&mut self, val: bool) {
+ if val {
+ self.flags.set_end_stream();
+ } else {
+ self.flags.unset_end_stream();
+ }
+ }
+
+ /// Returns whether the `PADDED` flag is set on this frame.
+ #[cfg(feature = "unstable")]
+ pub fn is_padded(&self) -> bool {
+ self.flags.is_padded()
+ }
+
+ /// Sets the value for the `PADDED` flag on this frame.
+ #[cfg(feature = "unstable")]
+ pub fn set_padded(&mut self) {
+ self.flags.set_padded();
+ }
+
+ /// Returns a reference to this frame's payload.
+ ///
+ /// This does **not** include any padding that might have been originally
+ /// included.
+ pub fn payload(&self) -> &T {
+ &self.data
+ }
+
+ /// Returns a mutable reference to this frame's payload.
+ ///
+ /// This does **not** include any padding that might have been originally
+ /// included.
+ pub fn payload_mut(&mut self) -> &mut T {
+ &mut self.data
+ }
+
+ /// Consumes `self` and returns the frame's payload.
+ ///
+ /// This does **not** include any padding that might have been originally
+ /// included.
+ pub fn into_payload(self) -> T {
+ self.data
+ }
+
+ pub(crate) fn head(&self) -> Head {
+ Head::new(Kind::Data, self.flags.into(), self.stream_id)
+ }
+
+ pub(crate) fn map<F, U>(self, f: F) -> Data<U>
+ where
+ F: FnOnce(T) -> U,
+ {
+ Data {
+ stream_id: self.stream_id,
+ data: f(self.data),
+ flags: self.flags,
+ pad_len: self.pad_len,
+ }
+ }
+}
+
+impl Data<Bytes> {
+ pub(crate) fn load(head: Head, mut payload: Bytes) -> Result<Self, Error> {
+ let flags = DataFlags::load(head.flag());
+
+ // The stream identifier must not be zero
+ if head.stream_id().is_zero() {
+ return Err(Error::InvalidStreamId);
+ }
+
+ let pad_len = if flags.is_padded() {
+ let len = util::strip_padding(&mut payload)?;
+ Some(len)
+ } else {
+ None
+ };
+
+ Ok(Data {
+ stream_id: head.stream_id(),
+ data: payload,
+ flags,
+ pad_len,
+ })
+ }
+}
+
+impl<T: Buf> Data<T> {
+ /// Encode the data frame into the `dst` buffer.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `dst` cannot contain the data frame.
+ pub(crate) fn encode_chunk<U: BufMut>(&mut self, dst: &mut U) {
+ let len = self.data.remaining() as usize;
+
+ assert!(dst.remaining_mut() >= len);
+
+ self.head().encode(len, dst);
+ dst.put(&mut self.data);
+ }
+}
+
+impl<T> From<Data<T>> for Frame<T> {
+ fn from(src: Data<T>) -> Self {
+ Frame::Data(src)
+ }
+}
+
+impl<T> fmt::Debug for Data<T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let mut f = fmt.debug_struct("Data");
+ f.field("stream_id", &self.stream_id);
+ if !self.flags.is_empty() {
+ f.field("flags", &self.flags);
+ }
+ if let Some(ref pad_len) = self.pad_len {
+ f.field("pad_len", pad_len);
+ }
+ // `data` bytes purposefully excluded
+ f.finish()
+ }
+}
+
+// ===== impl DataFlags =====
+
+impl DataFlags {
+ fn load(bits: u8) -> DataFlags {
+ DataFlags(bits & ALL)
+ }
+
+ fn is_empty(&self) -> bool {
+ self.0 == 0
+ }
+
+ fn is_end_stream(&self) -> bool {
+ self.0 & END_STREAM == END_STREAM
+ }
+
+ fn set_end_stream(&mut self) {
+ self.0 |= END_STREAM
+ }
+
+ fn unset_end_stream(&mut self) {
+ self.0 &= !END_STREAM
+ }
+
+ fn is_padded(&self) -> bool {
+ self.0 & PADDED == PADDED
+ }
+
+ #[cfg(feature = "unstable")]
+ fn set_padded(&mut self) {
+ self.0 |= PADDED
+ }
+}
+
+impl Default for DataFlags {
+ fn default() -> Self {
+ DataFlags(0)
+ }
+}
+
+impl From<DataFlags> for u8 {
+ fn from(src: DataFlags) -> u8 {
+ src.0
+ }
+}
+
+impl fmt::Debug for DataFlags {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ util::debug_flags(fmt, self.0)
+ .flag_if(self.is_end_stream(), "END_STREAM")
+ .flag_if(self.is_padded(), "PADDED")
+ .finish()
+ }
+}