use std::sync::Arc;
use crate::{
DynViewPart,
buffer::{InstructionPtr, ViewBuffer},
};
#[derive(Debug, Clone, Copy)]
pub struct StaticStrPtr(usize);
#[derive(Debug, Clone, Copy)]
pub struct StringPtr(usize);
#[derive(Debug, Clone, Copy)]
pub struct StrPtr {
pub(crate) offset: usize,
pub(crate) len: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct DynPtr(usize);
#[derive(Debug, Clone, Copy)]
pub struct ViewPtr(usize);
#[cfg(feature = "http")]
#[derive(Debug, Clone, Copy)]
pub struct HeadersPtr(usize);
#[derive(Debug, Default)]
pub struct ConstBuffer {
static_strs: Vec<&'static str>,
strings: Vec<String>,
strs: String,
dyns: Vec<Box<dyn DynViewPart>>,
views: Vec<(Arc<ViewBuffer>, InstructionPtr)>,
#[cfg(feature = "http")]
headers: Vec<http::HeaderMap>,
}
impl ConstBuffer {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn push_static_str(&mut self, value: &'static str) -> StaticStrPtr {
self.static_strs.push(value);
StaticStrPtr(self.static_strs.len() - 1)
}
#[must_use]
pub fn fetch_static_str(&self, ptr: StaticStrPtr) -> &'static str {
self.static_strs[ptr.0]
}
pub fn push_string(&mut self, value: String) -> StringPtr {
self.strings.push(value);
StringPtr(self.strings.len() - 1)
}
#[must_use]
pub fn fetch_string(&self, ptr: StringPtr) -> &str {
&self.strings[ptr.0]
}
pub fn push_str(&mut self, value: &str) -> StrPtr {
let offset = self.strs.len();
let len = u32::try_from(value.len()).expect("string exceeds the buffer's length limit");
self.strs.push_str(value);
StrPtr { offset, len }
}
#[must_use]
pub fn fetch_str(&self, ptr: StrPtr) -> &str {
&self.strs[ptr.offset..ptr.offset + ptr.len as usize]
}
pub fn push_dyn(&mut self, value: Box<dyn DynViewPart>) -> DynPtr {
self.dyns.push(value);
DynPtr(self.dyns.len() - 1)
}
#[must_use]
pub fn fetch_dyn(&self, ptr: DynPtr) -> &dyn DynViewPart {
&*self.dyns[ptr.0]
}
pub fn push_view(&mut self, buffer: Arc<ViewBuffer>, entry: InstructionPtr) -> ViewPtr {
self.views.push((buffer, entry));
ViewPtr(self.views.len() - 1)
}
#[must_use]
pub fn fetch_view(&self, ptr: ViewPtr) -> (&ViewBuffer, InstructionPtr) {
let (buffer, entry) = &self.views[ptr.0];
(buffer, *entry)
}
#[cfg(feature = "http")]
pub fn push_headers(&mut self, value: http::HeaderMap) -> HeadersPtr {
self.headers.push(value);
HeadersPtr(self.headers.len() - 1)
}
#[cfg(feature = "http")]
#[must_use]
pub fn fetch_headers(&self, ptr: HeadersPtr) -> &http::HeaderMap {
&self.headers[ptr.0]
}
#[allow(unused)]
pub(crate) fn print_stats(&self) {
println!("ConstBuffer {{");
println!(" static_strs: {}", self.static_strs.len());
println!(" strings: {}", self.strings.len());
println!(" strs: {} bytes", self.strs.len());
println!(" dyns: {}", self.dyns.len());
#[cfg(feature = "http")]
println!(" headers: {}", self.headers.len());
println!("}}");
}
}