diff options
Diffstat (limited to 'third_party/rust/h2/src/frame/mod.rs')
-rw-r--r-- | third_party/rust/h2/src/frame/mod.rs | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/third_party/rust/h2/src/frame/mod.rs b/third_party/rust/h2/src/frame/mod.rs new file mode 100644 index 0000000000..0e8e7035c3 --- /dev/null +++ b/third_party/rust/h2/src/frame/mod.rs @@ -0,0 +1,171 @@ +use crate::hpack; + +use bytes::Bytes; + +use std::fmt; + +/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with +/// the given identifier, starting at the given offset, into the given integer +/// type. Obviously, the integer type should be able to support at least 4 +/// bytes. +/// +/// # Examples +/// +/// ```ignore +/// # // We ignore this doctest because the macro is not exported. +/// let buf: [u8; 4] = [0, 0, 0, 1]; +/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32)); +/// ``` +macro_rules! unpack_octets_4 { + // TODO: Get rid of this macro + ($buf:expr, $offset:expr, $tip:ty) => { + (($buf[$offset + 0] as $tip) << 24) + | (($buf[$offset + 1] as $tip) << 16) + | (($buf[$offset + 2] as $tip) << 8) + | (($buf[$offset + 3] as $tip) << 0) + }; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_unpack_octets_4() { + let buf: [u8; 4] = [0, 0, 0, 1]; + assert_eq!(1u32, unpack_octets_4!(buf, 0, u32)); + } +} + +mod data; +mod go_away; +mod head; +mod headers; +mod ping; +mod priority; +mod reason; +mod reset; +mod settings; +mod stream_id; +mod util; +mod window_update; + +pub use self::data::Data; +pub use self::go_away::GoAway; +pub use self::head::{Head, Kind}; +pub use self::headers::{ + parse_u64, Continuation, Headers, Pseudo, PushPromise, PushPromiseHeaderError, +}; +pub use self::ping::Ping; +pub use self::priority::{Priority, StreamDependency}; +pub use self::reason::Reason; +pub use self::reset::Reset; +pub use self::settings::Settings; +pub use self::stream_id::{StreamId, StreamIdOverflow}; +pub use self::window_update::WindowUpdate; + +#[cfg(feature = "unstable")] +pub use crate::hpack::BytesStr; + +// Re-export some constants + +pub use self::settings::{ + DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE, + MAX_MAX_FRAME_SIZE, +}; + +pub type FrameSize = u32; + +pub const HEADER_LEN: usize = 9; + +#[derive(Eq, PartialEq)] +pub enum Frame<T = Bytes> { + Data(Data<T>), + Headers(Headers), + Priority(Priority), + PushPromise(PushPromise), + Settings(Settings), + Ping(Ping), + GoAway(GoAway), + WindowUpdate(WindowUpdate), + Reset(Reset), +} + +impl<T> Frame<T> { + pub fn map<F, U>(self, f: F) -> Frame<U> + where + F: FnOnce(T) -> U, + { + use self::Frame::*; + + match self { + Data(frame) => frame.map(f).into(), + Headers(frame) => frame.into(), + Priority(frame) => frame.into(), + PushPromise(frame) => frame.into(), + Settings(frame) => frame.into(), + Ping(frame) => frame.into(), + GoAway(frame) => frame.into(), + WindowUpdate(frame) => frame.into(), + Reset(frame) => frame.into(), + } + } +} + +impl<T> fmt::Debug for Frame<T> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + use self::Frame::*; + + match *self { + Data(ref frame) => fmt::Debug::fmt(frame, fmt), + Headers(ref frame) => fmt::Debug::fmt(frame, fmt), + Priority(ref frame) => fmt::Debug::fmt(frame, fmt), + PushPromise(ref frame) => fmt::Debug::fmt(frame, fmt), + Settings(ref frame) => fmt::Debug::fmt(frame, fmt), + Ping(ref frame) => fmt::Debug::fmt(frame, fmt), + GoAway(ref frame) => fmt::Debug::fmt(frame, fmt), + WindowUpdate(ref frame) => fmt::Debug::fmt(frame, fmt), + Reset(ref frame) => fmt::Debug::fmt(frame, fmt), + } + } +} + +/// Errors that can occur during parsing an HTTP/2 frame. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Error { + /// A length value other than 8 was set on a PING message. + BadFrameSize, + + /// The padding length was larger than the frame-header-specified + /// length of the payload. + TooMuchPadding, + + /// An invalid setting value was provided + InvalidSettingValue, + + /// An invalid window update value + InvalidWindowUpdateValue, + + /// The payload length specified by the frame header was not the + /// value necessary for the specific frame type. + InvalidPayloadLength, + + /// Received a payload with an ACK settings frame + InvalidPayloadAckSettings, + + /// An invalid stream identifier was provided. + /// + /// This is returned if a SETTINGS or PING frame is received with a stream + /// identifier other than zero. + InvalidStreamId, + + /// A request or response is malformed. + MalformedMessage, + + /// An invalid stream dependency ID was provided + /// + /// This is returned if a HEADERS or PRIORITY frame is received with an + /// invalid stream identifier. + InvalidDependencyId, + + /// Failed to perform HPACK decoding + Hpack(hpack::DecoderError), +} |