Skip to content

Commit

Permalink
h3i: Remove StreamMap::insert from public API
Browse files Browse the repository at this point in the history
StreamMap is a read-only aggregation of frames that were received over
the connection, so it doesn't make sense to provide a way to insert
frames in after the connection was completed.

This also does some minor internal optimizations/cleanup for StreamMap.
  • Loading branch information
evanrittenhouse committed Dec 17, 2024
1 parent 084bcf5 commit ff24cf5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 40 deletions.
61 changes: 24 additions & 37 deletions h3i/src/client/connection_summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use serde::ser::Serializer;
use serde::Serialize;
use std::cmp;
use std::collections::HashMap;
use std::iter::FromIterator;

use crate::frame::EnrichedHeaders;
use crate::frame::H3iFrame;
Expand Down Expand Up @@ -82,9 +83,13 @@ impl Serialize for ConnectionSummary {
#[derive(Clone, Debug, Default, Serialize)]
pub struct StreamMap(HashMap<u64, Vec<H3iFrame>>);

impl From<HashMap<u64, Vec<H3iFrame>>> for StreamMap {
fn from(value: HashMap<u64, Vec<H3iFrame>>) -> Self {
Self(value)
impl<T> From<T> for StreamMap
where
T: IntoIterator<Item = (u64, Vec<H3iFrame>)>,
{
fn from(value: T) -> Self {
let map = HashMap::from_iter(value);
Self(map)
}
}

Expand All @@ -99,13 +104,12 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
///
/// let mut stream_map = StreamMap::default();
/// use std::iter::FromIterator;
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// let stream_map: StreamMap = [(0, vec![headers.clone()])].into();
/// assert_eq!(stream_map.all_frames(), vec![headers]);
/// ```
pub fn all_frames(&self) -> Vec<H3iFrame> {
Expand All @@ -125,44 +129,20 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// let stream_map: StreamMap = [(0, vec![headers.clone()])].into();
/// assert_eq!(stream_map.stream(0), vec![headers]);
/// ```
pub fn stream(&self, stream_id: u64) -> Vec<H3iFrame> {
self.0.get(&stream_id).cloned().unwrap_or_default()
}

/// Insert a new [`H3iFrame`] into the stream map on a given stream.
///
/// # Example
///
/// ```
/// use h3i::client::connection_summary::StreamMap;
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
///
/// use std::collections::HashMap;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// assert_eq!(stream_map.stream(0), vec![headers]);
/// ```
pub fn insert(&mut self, k: u64, v: H3iFrame) {
self.0.entry(k).or_default().push(v)
}

/// Check if a provided [`H3iFrame`] was received, regardless of what stream
/// it was received on.
///
Expand All @@ -173,13 +153,14 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// let stream_map: StreamMap = [(0, vec![headers.clone()])].into();
/// assert!(stream_map.received_frame(&headers));
/// ```
pub fn received_frame(&self, frame: &H3iFrame) -> bool {
Expand All @@ -195,13 +176,14 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// let stream_map: StreamMap = [(0, vec![headers.clone()])].into();
/// assert!(stream_map.received_frame_on_stream(0, &headers));
/// ```
pub fn received_frame_on_stream(
Expand All @@ -219,14 +201,15 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
/// assert!(stream_map.is_empty());
///
/// let h = Header::new(b"hello", b"world");
/// let headers = H3iFrame::Headers(EnrichedHeaders::from(vec![h]));
/// stream_map.insert(0, headers.clone());
///
/// let stream_map: StreamMap = [(0, vec![headers.clone()])].into();
/// assert!(!stream_map.is_empty());
/// ```
pub fn is_empty(&self) -> bool {
Expand All @@ -242,6 +225,7 @@ impl StreamMap {
/// use h3i::frame::EnrichedHeaders;
/// use h3i::frame::H3iFrame;
/// use quiche::h3::Header;
/// use std::iter::FromIterator;
///
/// let mut stream_map = StreamMap::default();
///
Expand All @@ -251,9 +235,8 @@ impl StreamMap {
/// let data = H3iFrame::QuicheH3(quiche::h3::frame::Frame::Data {
/// payload: b"hello world".to_vec(),
/// });
/// stream_map.insert(0, headers.clone());
/// stream_map.insert(0, data);
///
/// let stream_map: StreamMap = [(0, vec![headers.clone(), data.clone()])].into();
/// assert_eq!(stream_map.headers_on_stream(0), vec![enriched]);
/// ```
pub fn headers_on_stream(&self, stream_id: u64) -> Vec<EnrichedHeaders> {
Expand All @@ -262,6 +245,10 @@ impl StreamMap {
.filter_map(|h3i_frame| h3i_frame.to_enriched_headers())
.collect()
}

pub(crate) fn insert(&mut self, stream_id: u64, frame: H3iFrame) {
self.0.entry(stream_id).or_default().push(frame);
}
}

/// Denotes why the connection was closed.
Expand Down
6 changes: 3 additions & 3 deletions h3i/src/client/sync_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use super::StreamParserMap;

#[derive(Default)]
struct SyncClient {
stream_map: StreamMap,
streams: StreamMap,
stream_parsers: StreamParserMap,
}

Expand All @@ -63,7 +63,7 @@ impl Client for SyncClient {
}

fn handle_response_frame(&mut self, stream_id: u64, frame: H3iFrame) {
self.stream_map.insert(stream_id, frame);
self.streams.insert(stream_id, frame);
}
}

Expand Down Expand Up @@ -371,7 +371,7 @@ pub fn connect(
}

Ok(ConnectionSummary {
stream_map: client.stream_map,
stream_map: client.streams,
stats: Some(conn.stats()),
path_stats: conn.path_stats().collect(),
conn_close_details: ConnectionCloseDetails::new(&conn),
Expand Down

0 comments on commit ff24cf5

Please sign in to comment.