use super::{encode::encode_required_insert_count, *};
use crate::{
HttpContext, KnownHeaderName,
h3::H3Error,
headers::{
entry_name::{EntryName, PseudoHeaderName},
qpack::{
ConnectionAccumulator,
decoder_dynamic_table::DecoderDynamicTable,
instruction::encoder::{EncoderInstruction, parse},
},
},
};
use futures_lite::future::block_on;
impl EncoderDynamicTable {
pub(in crate::headers) fn insert_count(&self) -> u64 {
self.state.lock().unwrap().insert_count
}
pub(in crate::headers) fn known_received_count(&self) -> u64 {
self.state.lock().unwrap().known_received_count
}
pub(in crate::headers) fn entry_count(&self) -> usize {
self.state.lock().unwrap().entries.len()
}
pub(in crate::headers) fn current_size(&self) -> usize {
self.state.lock().unwrap().current_size
}
pub(in crate::headers) fn capacity(&self) -> usize {
self.state.lock().unwrap().capacity
}
pub(in crate::headers) fn insert(
&self,
name: EntryName<'_>,
value: FieldLineValue<'_>,
) -> Result<u64, H3Error> {
let mut state = self.state.lock().unwrap();
let abs_idx = state.insert(name, value, None)?;
drop(state);
self.event.notify(usize::MAX);
Ok(abs_idx)
}
pub(in crate::headers) fn set_capacity(&self, new_capacity: usize) -> Result<(), H3Error> {
let mut state = self.state.lock().unwrap();
state.set_capacity(new_capacity)?;
drop(state);
self.event.notify(usize::MAX);
Ok(())
}
pub(in crate::headers) fn find_full_match(
&self,
name: &EntryName,
value: &[u8],
) -> Option<u64> {
let state = self.state.lock().unwrap();
state
.by_name
.get(name)
.and_then(|index| index.by_value.get(value).copied())
}
pub(in crate::headers) fn find_name_match(&self, name: &EntryName) -> Option<u64> {
let state = self.state.lock().unwrap();
state.by_name.get(name).map(|index| index.latest_any)
}
pub(in crate::headers) fn currently_blocked_streams(&self) -> usize {
self.state.lock().unwrap().currently_blocked_streams()
}
pub(in crate::headers) fn is_stream_blocking(&self, stream_id: u64) -> bool {
self.state.lock().unwrap().is_stream_blocking(stream_id)
}
pub(in crate::headers) fn can_block_another_stream(&self, stream_id: u64) -> bool {
let state = self.state.lock().unwrap();
if state.is_stream_blocking(stream_id) {
return true;
}
state.currently_blocked_streams() < state.max_blocked_streams
}
pub(in crate::headers) fn register_outstanding_section(
&self,
stream_id: u64,
refs: SectionRefs,
) {
self.state
.lock()
.unwrap()
.outstanding_sections
.entry(stream_id)
.or_default()
.push_back(refs);
}
}
fn qen(s: &str) -> EntryName<'static> {
EntryName::try_from(s.as_bytes().to_vec()).unwrap()
}
fn fv(s: &'static str) -> FieldLineValue<'static> {
FieldLineValue::Static(s.as_bytes())
}
fn fvo(v: Vec<u8>) -> FieldLineValue<'static> {
FieldLineValue::Owned(v)
}
fn new_table(max_capacity: u64) -> EncoderDynamicTable {
new_table_with_blocked_streams(max_capacity, 0)
}
fn new_table_with_blocked_streams(
max_capacity: u64,
max_blocked_streams: u64,
) -> EncoderDynamicTable {
let context = HttpContext::default().with_config(
crate::HttpConfig::default().with_dynamic_table_capacity(max_capacity as usize),
);
let table = EncoderDynamicTable::new(&context);
table.initialize_from_peer_settings(
H3Settings::default()
.with_qpack_max_table_capacity(max_capacity)
.with_qpack_blocked_streams(max_blocked_streams),
);
table
}
fn drain_instructions(table: &EncoderDynamicTable) -> Vec<EncoderInstruction> {
let bytes: Vec<u8> = table.drain_pending_ops().into_iter().flatten().collect();
parse_all(&bytes)
}
fn parse_all(bytes: &[u8]) -> Vec<EncoderInstruction> {
let mut stream = bytes;
let mut out = Vec::new();
while let Some(instr) = block_on(parse(usize::MAX, &mut stream)).unwrap() {
out.push(instr);
}
out
}
fn apply_ops_to_decoder(table: &EncoderDynamicTable, max_capacity: u64) -> DecoderDynamicTable {
let bytes: Vec<u8> = table.drain_pending_ops().into_iter().flatten().collect();
let decoder = DecoderDynamicTable::new(max_capacity as usize, 0);
let mut stream = &bytes[..];
block_on(decoder.run_reader(&mut stream)).unwrap();
decoder
}
fn blocking_section(ric: u64) -> SectionRefs {
SectionRefs {
required_insert_count: ric,
min_ref_abs_idx: None,
}
}
mod budgets_and_capacity;
mod dup_drain;
mod encode_blocked;
mod encode_dynamic;
mod encode_refs;
mod encode_static;
mod insert;
mod pinning;
mod reverse_index;