use std::cell::RefCell;
use std::fmt::{self , Write};
use std::str;
use std::time::{Duration, SystemTime};
#[ cfg(feature = "http2" )]
use http::header::HeaderValue;
use httpdate::HttpDate;
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
pub (crate ) const DATE_VALUE_LENGTH: usize = 29 ;
#[ cfg(feature = "http1" )]
pub (crate ) fn extend(dst: &mut Vec<u8>) {
CACHED.with(|cache| {
dst.extend_from_slice(cache.borrow().buffer());
})
}
#[ cfg(feature = "http1" )]
pub (crate ) fn update() {
CACHED.with(|cache| {
cache.borrow_mut().check();
})
}
#[ cfg(feature = "http2" )]
pub (crate ) fn update_and_header_value() -> HeaderValue {
CACHED.with(|cache| {
let mut cache = cache.borrow_mut();
cache.check();
HeaderValue::from_bytes(cache.buffer()).expect("Date format should be valid HeaderValue" )
})
}
struct CachedDate {
bytes: [u8; DATE_VALUE_LENGTH],
pos: usize,
next_update: SystemTime,
}
thread_local!(static CACHED: RefCell<CachedDate> = RefCell::new(CachedDate::new()));
impl CachedDate {
fn new() -> Self {
let mut cache = CachedDate {
bytes: [0 ; DATE_VALUE_LENGTH],
pos: 0 ,
next_update: SystemTime::now(),
};
cache.update(cache.next_update);
cache
}
fn buffer(&self ) -> &[u8] {
&self .bytes[..]
}
fn check(&mut self ) {
let now = SystemTime::now();
if now > self .next_update {
self .update(now);
}
}
fn update(&mut self , now: SystemTime) {
self .render(now);
self .next_update = now + Duration::new(1 , 0 );
}
fn render(&mut self , now: SystemTime) {
self .pos = 0 ;
let _ = write!(self , "{}" , HttpDate::from(now));
debug_assert!(self .pos == DATE_VALUE_LENGTH);
}
}
impl fmt::Write for CachedDate {
fn write_str(&mut self , s: &str) -> fmt::Result {
let len = s.len();
self .bytes[self .pos..self .pos + len].copy_from_slice(s.as_bytes());
self .pos += len;
Ok(())
}
}
#[ cfg(test)]
mod tests {
use super ::*;
#[ cfg(feature = "nightly" )]
use test::Bencher;
#[ test]
fn test_date_len() {
assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT" .len());
}
#[ cfg(feature = "nightly" )]
#[ bench]
fn bench_date_check(b: &mut Bencher) {
let mut date = CachedDate::new();
// cache the first update
date.check();
b.iter(|| {
date.check();
});
}
#[ cfg(feature = "nightly" )]
#[ bench]
fn bench_date_render(b: &mut Bencher) {
let mut date = CachedDate::new();
let now = SystemTime::now();
date.render(now);
b.bytes = date.buffer().len() as u64;
b.iter(|| {
date.render(now);
test::black_box(&date);
});
}
}
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.8 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland