use std::fmt; use bytes::{Bytes, IntoBuf}; use http::{self, HeaderMap, HttpTryFrom}; use h2::frame::{self, Frame, StreamId}; use super::SendFrame; pub const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0]; pub const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0]; // ==== helper functions to easily construct h2 Frames ==== pub fn headers(id: T) -> MockHeaders where T: Into, { MockHeaders(frame::Headers::new( id.into(), frame::Pseudo::default(), HeaderMap::default(), )) } pub fn data(id: T, buf: B) -> MockData where T: Into, B: Into, { MockData(frame::Data::new(id.into(), buf.into())) } pub fn window_update(id: T, sz: u32) -> frame::WindowUpdate where T: Into, { frame::WindowUpdate::new(id.into(), sz) } // Headers helpers pub struct MockHeaders(frame::Headers); impl MockHeaders { pub fn request(self, method: M, uri: U) -> Self where M: HttpTryInto, U: HttpTryInto, { let method = method.try_into().unwrap(); let uri = uri.try_into().unwrap(); let (id, _, fields) = self.into_parts(); let frame = frame::Headers::new( id, frame::Pseudo::request(method, uri), fields ); MockHeaders(frame) } pub fn response(self, status: S) -> Self where S: HttpTryInto, { let status = status.try_into().unwrap(); let (id, _, fields) = self.into_parts(); let frame = frame::Headers::new( id, frame::Pseudo::response(status), fields ); MockHeaders(frame) } pub fn fields(self, fields: HeaderMap) -> Self { let (id, pseudo, _) = self.into_parts(); let frame = frame::Headers::new(id, pseudo, fields); MockHeaders(frame) } pub fn eos(mut self) -> Self { self.0.set_end_stream(); self } fn into_parts(self) -> (StreamId, frame::Pseudo, HeaderMap) { assert!(!self.0.is_end_stream(), "eos flag will be lost"); assert!(self.0.is_end_headers(), "unset eoh will be lost"); let id = self.0.stream_id(); let parts = self.0.into_parts(); (id, parts.0, parts.1) } } impl fmt::Debug for MockHeaders { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } impl From for Frame { fn from(src: MockHeaders) -> Self { Frame::Headers(src.0) } } impl From for SendFrame { fn from(src: MockHeaders) -> Self { Frame::Headers(src.0) } } // Data helpers pub struct MockData(frame::Data); impl MockData { pub fn eos(mut self) -> Self { self.0.set_end_stream(true); self } } impl fmt::Debug for MockData { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } impl From for Frame { fn from(src: MockData) -> Self { Frame::Data(src.0) } } impl From for SendFrame { fn from(src: MockData) -> Self { let id = src.0.stream_id(); let eos = src.0.is_end_stream(); let payload = src.0.into_payload(); let mut frame = frame::Data::new(id, payload.into_buf()); frame.set_end_stream(eos); Frame::Data(frame) } } // ==== "trait alias" for types that are HttpTryFrom and have Debug Errors ==== pub trait HttpTryInto { type Error: fmt::Debug; fn try_into(self) -> Result; } impl HttpTryInto for U where T: HttpTryFrom, T::Error: fmt::Debug, { type Error = T::Error; fn try_into(self) -> Result { T::try_from(self) } }