From 44ff5e5c78c7877c6ba71858ceef68957908af9b Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Fri, 10 May 2019 18:36:02 -0700 Subject: [PATCH] Add DebugFlags helper, improve format of HEADERS and SETTINGS frames --- src/frame/data.rs | 15 ++++---------- src/frame/headers.rs | 33 ++++++++++++++++------------- src/frame/settings.rs | 48 +++++++++++++++++++++++++++++++++++++++---- src/frame/util.rs | 41 ++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src/frame/data.rs b/src/frame/data.rs index 89a4e6e..a781a2d 100644 --- a/src/frame/data.rs +++ b/src/frame/data.rs @@ -225,16 +225,9 @@ impl From for u8 { impl fmt::Debug for DataFlags { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut f = fmt.debug_struct("DataFlags"); - - if self.is_end_stream() { - f.field("end_stream", &true); - } - - if self.is_padded() { - f.field("padded", &true); - } - - f.finish() + util::debug_flags(fmt, self.0) + .flag_if(self.is_end_stream(), "END_STREAM") + .flag_if(self.is_padded(), "PADDED") + .finish() } } diff --git a/src/frame/headers.rs b/src/frame/headers.rs index 6b626fb..d4f54bf 100644 --- a/src/frame/headers.rs +++ b/src/frame/headers.rs @@ -1,4 +1,4 @@ -use super::{StreamDependency, StreamId}; +use super::{util, StreamDependency, StreamId}; use frame::{Error, Frame, Head, Kind}; use hpack; @@ -274,12 +274,17 @@ impl From for Frame { impl fmt::Debug for Headers { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Headers") + let mut builder = f.debug_struct("Headers"); + builder .field("stream_id", &self.stream_id) - .field("stream_dep", &self.stream_dep) - .field("flags", &self.flags) - // `fields` and `pseudo` purposefully not included - .finish() + .field("flags", &self.flags); + + if let Some(ref dep) = self.stream_dep { + builder.field("stream_dep", dep); + } + + // `fields` and `pseudo` purposefully not included + builder.finish() } } @@ -656,11 +661,11 @@ impl From for u8 { impl fmt::Debug for HeadersFlag { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("HeadersFlag") - .field("end_stream", &self.is_end_stream()) - .field("end_headers", &self.is_end_headers()) - .field("padded", &self.is_padded()) - .field("priority", &self.is_priority()) + util::debug_flags(fmt, self.0) + .flag_if(self.is_end_headers(), "END_HEADERS") + .flag_if(self.is_end_stream(), "END_STREAM") + .flag_if(self.is_padded(), "PADDED") + .flag_if(self.is_priority(), "PRIORITY") .finish() } } @@ -704,9 +709,9 @@ impl From for u8 { impl fmt::Debug for PushPromiseFlag { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("PushPromiseFlag") - .field("end_headers", &self.is_end_headers()) - .field("padded", &self.is_padded()) + util::debug_flags(fmt, self.0) + .flag_if(self.is_end_headers(), "END_HEADERS") + .flag_if(self.is_padded(), "PADDED") .finish() } } diff --git a/src/frame/settings.rs b/src/frame/settings.rs index c91a719..9ed82b4 100644 --- a/src/frame/settings.rs +++ b/src/frame/settings.rs @@ -1,7 +1,9 @@ -use bytes::{BufMut, BytesMut}; -use frame::{Error, Frame, FrameSize, Head, Kind, StreamId}; +use std::fmt; -#[derive(Debug, Clone, Default, Eq, PartialEq)] +use bytes::{BufMut, BytesMut}; +use frame::{util, Error, Frame, FrameSize, Head, Kind, StreamId}; + +#[derive(Clone, Default, Eq, PartialEq)] pub struct Settings { flags: SettingsFlags, // Fields @@ -27,7 +29,7 @@ pub enum Setting { MaxHeaderListSize(u32), } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] +#[derive(Copy, Clone, Eq, PartialEq, Default)] pub struct SettingsFlags(u8); const ACK: u8 = 0x1; @@ -231,6 +233,36 @@ impl From for Frame { } } +impl fmt::Debug for Settings { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut builder = f.debug_struct("Settings"); + builder.field("flags", &self.flags); + + self.for_each(|setting| match setting { + Setting::EnablePush(v) => { + builder.field("enable_push", &v); + } + Setting::HeaderTableSize(v) => { + builder.field("header_table_size", &v); + } + Setting::InitialWindowSize(v) => { + builder.field("initial_window_size", &v); + } + Setting::MaxConcurrentStreams(v) => { + builder.field("max_concurrent_streams", &v); + } + Setting::MaxFrameSize(v) => { + builder.field("max_frame_size", &v); + } + Setting::MaxHeaderListSize(v) => { + builder.field("max_header_list_size", &v); + } + }); + + builder.finish() + } +} + // ===== impl Setting ===== impl Setting { @@ -310,3 +342,11 @@ impl From for u8 { src.0 } } + +impl fmt::Debug for SettingsFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + util::debug_flags(f, self.0) + .flag_if(self.is_ack(), "ACK") + .finish() + } +} diff --git a/src/frame/util.rs b/src/frame/util.rs index ceb44b2..f144558 100644 --- a/src/frame/util.rs +++ b/src/frame/util.rs @@ -1,3 +1,5 @@ +use std::fmt; + use super::Error; use bytes::Bytes; @@ -35,3 +37,42 @@ pub fn strip_padding(payload: &mut Bytes) -> Result { Ok(pad_len as u8) } + +pub(super) fn debug_flags<'a, 'f>(fmt: &'a mut fmt::Formatter<'f>, bits: u8) -> DebugFlags<'a, 'f> { + let result = write!(fmt, "({:#x}", bits); + DebugFlags { + fmt, + result, + started: false, + } +} + +pub(super) struct DebugFlags<'a, 'f> { + fmt: &'a mut fmt::Formatter<'f>, + result: fmt::Result, + started: bool, +} + +impl<'a, 'f> DebugFlags<'a, 'f> { + pub(super) fn flag_if(&mut self, enabled: bool, name: &str) -> &mut Self { + if enabled { + self.result = self.result.and_then(|()| { + let prefix = if self.started { + " | " + } else { + self.started = true; + ": " + }; + + write!(self.fmt, "{}{}", prefix, name) + }); + } + self + } + + pub(super) fn finish(&mut self) -> fmt::Result { + self.result.and_then(|()| { + write!(self.fmt, ")") + }) + } +}