diff --git a/benches/benches/request_headers.rs b/benches/benches/request_headers.rs index f2fc38e22..ec37e1890 100644 --- a/benches/benches/request_headers.rs +++ b/benches/benches/request_headers.rs @@ -84,34 +84,32 @@ fn input() -> Vec { #[bench] fn ohkami_parse(b: &mut test::Bencher) { let input = input(); - b.iter(|| { + b.iter(|| -> RequestHeaders { let mut r = byte_reader::Reader::new(black_box(input.as_slice())); let mut h = RequestHeaders::_init(); while r.consume("\r\n").is_none() { let key_bytes = r.read_while(|b| b != &b':'); r.consume(": ").unwrap(); + + let value = CowSlice::Ref(Slice::from_bytes(r.read_while(|b| b != &b'\r'))); + r.consume("\r\n").unwrap(); + if let Some(key) = RequestHeader::from_bytes(key_bytes) { - h._insert(key, CowSlice::Ref( - Slice::from_bytes(r.read_while(|b| b != &b'\r')) - )); + h._append(key, value); } else { - match key_bytes { - b"Cookie" | b"cookie" => (/* skip now */), - _ => h._insert_custom(Slice::from_bytes(key_bytes), CowSlice::Ref( - Slice::from_bytes(r.read_while(|b| b != &b'\r')) - )) - } + h._insert_custom(Slice::from_bytes(key_bytes), value) } - r.consume("\r\n"); } + + h }) } #[bench] fn fxmap_parse(b: &mut test::Bencher) { let input = input(); - b.iter(|| { + b.iter(|| -> FxMap { let mut r = byte_reader::Reader::new(black_box(input.as_slice())); let mut h = FxMap::new(); @@ -124,13 +122,15 @@ fn input() -> Vec { )); r.consume("\r\n"); } + + h }) } #[bench] fn headerhashmap_parse(b: &mut test::Bencher) { let input = input(); - b.iter(|| { + b.iter(|| -> HeaderHashMap { let mut r = byte_reader::Reader::new(black_box(input.as_slice())); let mut h = HeaderHashMap::default(); @@ -143,13 +143,15 @@ fn input() -> Vec { )); r.consume("\r\n"); } + + h }) } #[bench] fn http_crate_parse(b: &mut test::Bencher) { let input = input(); - b.iter(|| { + b.iter(|| -> HeaderMap { let mut r = byte_reader::Reader::new(black_box(input.as_slice())); let mut h = HeaderMap::new(); @@ -162,13 +164,15 @@ fn input() -> Vec { ); r.consume("\r\n"); } + + h }) } #[bench] fn header_hashbrown_parse(b: &mut test::Bencher) { let input = input(); - b.iter(|| { + b.iter(|| -> HeaderHashBrown:: { let mut r = byte_reader::Reader::new(black_box(input.as_slice())); let mut h = HeaderHashBrown::::new(); @@ -183,5 +187,7 @@ fn input() -> Vec { None => h.insert_from_reqbytes(key_bytes, value_bytes), }; } + + h }) } diff --git a/benches/benches/response_headers.rs b/benches/benches/response_headers.rs index ca8aebab1..857912085 100644 --- a/benches/benches/response_headers.rs +++ b/benches/benches/response_headers.rs @@ -14,9 +14,10 @@ use ohkami_benches::response_headers::{ // heap_ohkami_headers_nosize::HeapOhkamiHeadersWithoutSize, }; -#[bench] fn insert_ohkami(b: &mut test::Bencher) { - let mut h = ResponseHeaders::_new(); - b.iter(|| { +#[bench] +fn ohkami_insert(b: &mut test::Bencher) { + b.iter(|| -> ResponseHeaders { + let mut h = ResponseHeaders::_new(); h.set() .access_control_allow_credentials(black_box("true")) .access_control_allow_headers(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -35,12 +36,14 @@ use ohkami_benches::response_headers::{ .x("x-myapp-data", black_box("myappdata; excellent")) .x("something", black_box("anything")) ; + h }); } /* -#[bench] fn insert_ohkami_only_standard(b: &mut test::Bencher) { - let mut h = ResponseHeaders::_new(); - b.iter(|| { +#[bench] +fn ohkami_only_standard_insert(b: &mut test::Bencher) { + b.iter(|| -> ResponseHeaders { + let mut h = ResponseHeaders::_new(); h.set() .access_control_allow_credentials(black_box("true")) .access_control_allow_headers(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -57,12 +60,14 @@ use ohkami_benches::response_headers::{ .referrer_policy(black_box("same-origin")) .x_frame_options(black_box("DENY")) ; + h }); } -#[bench] fn insert_heap_ohkami_nosize(b: &mut test::Bencher) { - let mut h = HeapOhkamiHeadersWithoutSize::new(); - b.iter(|| { +#[bench] +fn heap_ohkami_nosize_insert(b: &mut test::Bencher) { + b.iter(|| -> ResponseHeaders { + let mut h = HeapOhkamiHeadersWithoutSize::new(); h.set() .AccessControlAllowCredentials(black_box("true")) .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -81,11 +86,13 @@ use ohkami_benches::response_headers::{ .x("x-myapp-data", black_box("myappdata; excellent")) .x("something", black_box("anything")) ; + h }); } -#[bench] fn insert_heap_ohkami_only_standard(b: &mut test::Bencher) { - let mut h = HeapOhkamiHeaders::new(); - b.iter(|| { +#[bench] +fn heap_ohkami_only_standard_insert(b: &mut test::Bencher) { + b.iter(|| -> HeapOhkamiHeaders { + let mut h = HeapOhkamiHeaders::new(); h.set() .AccessControlAllowCredentials(black_box("true")) .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -102,13 +109,15 @@ use ohkami_benches::response_headers::{ .ReferrerPolicy(black_box("same-origin")) .XFrameOptions(black_box("DENY")) ; + h }); } */ -#[bench] fn insert_http_crate(b: &mut test::Bencher) { - let mut h = HeaderMap::new(); - b.iter(|| { +#[bench] +fn http_crate_insert(b: &mut test::Bencher) { + b.iter(|| -> HeaderMap { + let mut h = HeaderMap::new(); h.insert(header::ACCESS_CONTROL_ALLOW_CREDENTIALS, HeaderValue::from_static(black_box("true"))); h.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static(black_box("X-Custom-Header,Upgrade-Insecure-Requests"))); h.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(black_box("https://foo.bar.org"))); @@ -125,12 +134,14 @@ use ohkami_benches::response_headers::{ h.insert(header::X_FRAME_OPTIONS, HeaderValue::from_static("DENY")); h.insert(HeaderName::from_static("x-myapp-data"), HeaderValue::from_static(black_box("myappdata; excellent"))); h.insert(HeaderName::from_static("something"), HeaderValue::from_static(black_box("anything"))); + h }); } -#[bench] fn insert_fxmap(b: &mut test::Bencher) { - let mut h = FxMap::new(); - b.iter(|| { +#[bench] +fn fxmap_insert(b: &mut test::Bencher) { + b.iter(|| -> FxMap { + let mut h = FxMap::new(); h .insert("Access-Control-Allow-Credentials", black_box("true")) .insert("Access-Control-Allow-Headers", black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -148,12 +159,14 @@ use ohkami_benches::response_headers::{ .insert("x-myapp-data", black_box("myappdata; excellent")) .insert("something", black_box("anything")) ; + h }); } -#[bench] fn insert_headermap(b: &mut test::Bencher) { - let mut h = MyHeaderMap::new(); - b.iter(|| { +#[bench] +fn headermap_insert(b: &mut test::Bencher) { + b.iter(|| -> MyHeaderMap { + let mut h = MyHeaderMap::new(); h.set() .AccessControlAllowCredentials(black_box("true")) .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) @@ -171,12 +184,14 @@ use ohkami_benches::response_headers::{ .custom("x-myapp-data", black_box("myappdata; excellent")) .custom("something", black_box("anything")) ; + h }); } -#[bench] fn insert_header_hashbrown(b: &mut test::Bencher) { - let mut h = HeaderHashBrown::::new(); - b.iter(|| { +#[bench] +fn header_hashbrown_insert(b: &mut test::Bencher) { + b.iter(|| -> HeaderHashBrown { + let mut h = HeaderHashBrown::::new(); h .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowCredentials, black_box(b"true")) .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowHeaders, black_box(b"X-Custom-Header,Upgrade-Insecure-Requests")) @@ -194,34 +209,35 @@ use ohkami_benches::response_headers::{ .insert_from_reqbytes(b"x-myapp-data", black_box(b"myappdata; excellent")) .insert_from_reqbytes(b"something", black_box(b"anything")) ; + h }); } -#[bench] fn remove_ohkami(b: &mut test::Bencher) { - let mut h = ResponseHeaders::_new(); - h.set() - .access_control_allow_credentials(black_box("true")) - .access_control_allow_headers(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) - .access_control_allow_origin(black_box("https://foo.bar.org")) - .access_control_allow_methods(black_box("POST,GET,OPTIONS,DELETE")) - .access_control_max_age(black_box("86400")) - .vary(black_box("Origin")) - .server(black_box("ohkami")) - .connection(black_box("Keep-Alive")) - .date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) - .via(black_box("HTTP/1.1 GWA")) - .alt_svc(black_box("h2=\":433\"; ma=2592000;")) - .proxy_authenticate(black_box("Basic realm=\"Access to the internal site\"")) - .referrer_policy(black_box("same-origin")) - .x_frame_options(black_box("DENY")) - .x("x-myapp-data", black_box("myappdata; excellent")) - .x("something", black_box("anything")) - ; - - b.iter(|| { +#[bench] +fn ohkami_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> ResponseHeaders { + let mut h = ResponseHeaders::_new(); + h.set() + .access_control_allow_credentials(black_box("true")) + .access_control_allow_headers(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) + .access_control_allow_origin(black_box("https://foo.bar.org")) + .access_control_allow_methods(black_box("POST,GET,OPTIONS,DELETE")) + .access_control_max_age(black_box("86400")) + .vary(black_box("Origin")) + .server(black_box("ohkami")) + .connection(black_box("Keep-Alive")) + .date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) + .via(black_box("HTTP/1.1 GWA")) + .alt_svc(black_box("h2=\":433\"; ma=2592000;")) + .proxy_authenticate(black_box("Basic realm=\"Access to the internal site\"")) + .referrer_policy(black_box("same-origin")) + .x_frame_options(black_box("DENY")) + .x("x-myapp-data", black_box("myappdata; excellent")) + .x("something", black_box("anything")) + ; h.set() .access_control_allow_credentials(None) .access_control_allow_headers(None) @@ -240,31 +256,32 @@ use ohkami_benches::response_headers::{ .x("x-myapp-data", None) .x("something", None) ; + h }); } /* -#[bench] fn remove_heap_ohkami_nosize(b: &mut test::Bencher) { - let mut h = HeapOhkamiHeadersWithoutSize::new(); - h.set() - .AccessControlAllowCredentials(black_box("true")) - .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) - .AccessControlAllowOrigin(black_box("https://foo.bar.org")) - .AccessControlAllowMethods(black_box("POST,GET,OPTIONS,DELETE")) - .AccessControlMaxAge(black_box("86400")) - .Vary(black_box("Origin")) - .Server(black_box("ohkami")) - .Connection(black_box("Keep-Alive")) - .Date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) - .Via(black_box("HTTP/1.1 GWA")) - .AltSvc(black_box("h2=\":433\"; ma=2592000;")) - .ProxyAuthenticate(black_box("Basic realm=\"Access to the internal site\"")) - .ReferrerPolicy(black_box("same-origin")) - .XFrameOptions(black_box("DENY")) - .custom("x-myapp-data", black_box("myappdata; excellent")) - .custom("something", black_box("anything")) - ; - - b.iter(|| { +#[bench] +fn heap_ohkami_nosize_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> HeapOhkamiHeadersWithoutSize { + let mut h = HeapOhkamiHeadersWithoutSize::new(); + h.set() + .AccessControlAllowCredentials(black_box("true")) + .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) + .AccessControlAllowOrigin(black_box("https://foo.bar.org")) + .AccessControlAllowMethods(black_box("POST,GET,OPTIONS,DELETE")) + .AccessControlMaxAge(black_box("86400")) + .Vary(black_box("Origin")) + .Server(black_box("ohkami")) + .Connection(black_box("Keep-Alive")) + .Date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) + .Via(black_box("HTTP/1.1 GWA")) + .AltSvc(black_box("h2=\":433\"; ma=2592000;")) + .ProxyAuthenticate(black_box("Basic realm=\"Access to the internal site\"")) + .ReferrerPolicy(black_box("same-origin")) + .XFrameOptions(black_box("DENY")) + .custom("x-myapp-data", black_box("myappdata; excellent")) + .custom("something", black_box("anything")) + ; h.set() .AccessControlAllowCredentials(black_box(None)) .AccessControlAllowHeaders(black_box(None)) @@ -283,30 +300,33 @@ use ohkami_benches::response_headers::{ .custom("x-myapp-data", black_box(None)) .custom("something", black_box(None)) ; + h }); } */ -#[bench] fn remove_http_crate(b: &mut test::Bencher) { - let mut h = HeaderMap::new(); - h.insert(header::ACCESS_CONTROL_ALLOW_CREDENTIALS, HeaderValue::from_static(black_box("true"))); - h.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static(black_box("X-Custom-Header,Upgrade-Insecure-Requests"))); - h.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(black_box("https://foo.bar.org"))); - h.insert(header::ACCESS_CONTROL_ALLOW_METHODS, HeaderValue::from_static(black_box("POST,GET,OPTIONS,DELETE"))); - h.insert(header::ACCESS_CONTROL_MAX_AGE, HeaderValue::from_static(black_box("86400"))); - h.insert(header::VARY, HeaderValue::from_static(black_box("Origin"))); - h.insert(header::SERVER, HeaderValue::from_static(black_box("ohkami"))); - h.insert(header::CONNECTION, HeaderValue::from_static(black_box("Keep-Alive"))); - h.insert(header::DATE, HeaderValue::from_static(black_box("Wed, 21 Oct 2015 07:28:00 GMT"))); - h.insert(header::VIA, HeaderValue::from_static(black_box("HTTP/1.1 GWA"))); - h.insert(header::ALT_SVC, HeaderValue::from_static(black_box("h2=\":433\"; ma=2592000;"))); - h.insert(header::PROXY_AUTHENTICATE, HeaderValue::from_static(black_box("Basic realm=\"Access to the internal site\""))); - h.insert(header::REFERRER_POLICY, HeaderValue::from_static("same-origin")); - h.insert(header::X_FRAME_OPTIONS, HeaderValue::from_static("DENY")); - h.insert(HeaderName::from_static("x-myapp-data"), HeaderValue::from_static(black_box("myappdata; excellent"))); - h.insert(HeaderName::from_static("something"), HeaderValue::from_static(black_box("anything"))); - - b.iter(|| { +#[bench] +fn http_crate_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> HeaderMap { + let mut h = HeaderMap::new(); + + h.insert(header::ACCESS_CONTROL_ALLOW_CREDENTIALS, HeaderValue::from_static(black_box("true"))); + h.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static(black_box("X-Custom-Header,Upgrade-Insecure-Requests"))); + h.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(black_box("https://foo.bar.org"))); + h.insert(header::ACCESS_CONTROL_ALLOW_METHODS, HeaderValue::from_static(black_box("POST,GET,OPTIONS,DELETE"))); + h.insert(header::ACCESS_CONTROL_MAX_AGE, HeaderValue::from_static(black_box("86400"))); + h.insert(header::VARY, HeaderValue::from_static(black_box("Origin"))); + h.insert(header::SERVER, HeaderValue::from_static(black_box("ohkami"))); + h.insert(header::CONNECTION, HeaderValue::from_static(black_box("Keep-Alive"))); + h.insert(header::DATE, HeaderValue::from_static(black_box("Wed, 21 Oct 2015 07:28:00 GMT"))); + h.insert(header::VIA, HeaderValue::from_static(black_box("HTTP/1.1 GWA"))); + h.insert(header::ALT_SVC, HeaderValue::from_static(black_box("h2=\":433\"; ma=2592000;"))); + h.insert(header::PROXY_AUTHENTICATE, HeaderValue::from_static(black_box("Basic realm=\"Access to the internal site\""))); + h.insert(header::REFERRER_POLICY, HeaderValue::from_static("same-origin")); + h.insert(header::X_FRAME_OPTIONS, HeaderValue::from_static("DENY")); + h.insert(HeaderName::from_static("x-myapp-data"), HeaderValue::from_static(black_box("myappdata; excellent"))); + h.insert(HeaderName::from_static("something"), HeaderValue::from_static(black_box("anything"))); + h.remove(header::ACCESS_CONTROL_ALLOW_CREDENTIALS); h.remove(header::ACCESS_CONTROL_ALLOW_HEADERS); h.remove(header::ACCESS_CONTROL_ALLOW_ORIGIN); @@ -323,30 +343,32 @@ use ohkami_benches::response_headers::{ h.remove(header::X_FRAME_OPTIONS); h.remove(HeaderName::from_static("x-myapp-data")); h.remove(HeaderName::from_static("something")); + + h }); } -#[bench] fn remove_fxmap(b: &mut test::Bencher) { - let mut h = FxMap::new(); - h - .insert("Access-Control-Allow-Credentials", black_box("true")) - .insert("Access-Control-Allow-Headers", black_box("X-Custom-Header,Upgrade-Insecure-Requests")) - .insert("Access-Control-Allow-Origin", black_box("https://foo.bar.org")) - .insert("Access-Control-Allow-Methods", black_box("POST,GET,OPTIONS,DELETE")) - .insert("Access-Control-Max-Age", black_box("86400")) - .insert("Vary", black_box("Origin")) - .insert("Server", black_box("ohkami")) - .insert("Connection", black_box("Keep-Alive")) - .insert("Date", black_box("Wed, 21 Oct 2015 07:28:00 GMT")) - .insert("Alt-Svc", black_box("h2=\":433\"; ma=2592000")) - .insert("Proxy-Authenticate", black_box("Basic realm=\"Access to the internal site\"")) - .insert("Referer-Policy", black_box("same-origin")) - .insert("X-Frame-Options", black_box("DEBY")) - .insert("x-myapp-data", black_box("myappdata; excellent")) - .insert("something", black_box("anything")) - ; - - b.iter(|| { +#[bench] +fn fxmap_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> FxMap { + let mut h = FxMap::new(); + h + .insert("Access-Control-Allow-Credentials", black_box("true")) + .insert("Access-Control-Allow-Headers", black_box("X-Custom-Header,Upgrade-Insecure-Requests")) + .insert("Access-Control-Allow-Origin", black_box("https://foo.bar.org")) + .insert("Access-Control-Allow-Methods", black_box("POST,GET,OPTIONS,DELETE")) + .insert("Access-Control-Max-Age", black_box("86400")) + .insert("Vary", black_box("Origin")) + .insert("Server", black_box("ohkami")) + .insert("Connection", black_box("Keep-Alive")) + .insert("Date", black_box("Wed, 21 Oct 2015 07:28:00 GMT")) + .insert("Alt-Svc", black_box("h2=\":433\"; ma=2592000")) + .insert("Proxy-Authenticate", black_box("Basic realm=\"Access to the internal site\"")) + .insert("Referer-Policy", black_box("same-origin")) + .insert("X-Frame-Options", black_box("DEBY")) + .insert("x-myapp-data", black_box("myappdata; excellent")) + .insert("something", black_box("anything")) + ; h .remove("Access-Control-Allow-Credentials") .remove("Access-Control-Allow-Headers") @@ -364,31 +386,31 @@ use ohkami_benches::response_headers::{ .remove("x-myapp-data") .remove("something") ; + h }); } -#[bench] fn remove_headermap(b: &mut test::Bencher) { - let mut h = MyHeaderMap::new(); - - h.set() - .AccessControlAllowCredentials(black_box("true")) - .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) - .AccessControlAllowOrigin(black_box("https://foo.bar.org")) - .AccessControlAllowMethods(black_box("POST,GET,OPTIONS,DELETE")) - .AccessControlMaxAge(black_box("86400")) - .Vary(black_box("Origin")) - .Server(black_box("ohkami")) - .Connection(black_box("Keep-Alive")) - .Date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) - .AltSvc(black_box("h2=\":433\"; ma=2592000")) - .ProxyAuthenticate(black_box("Basic realm=\"Access to the internal site\"")) - .ReferrerPolicy(black_box("same-origin")) - .XFrameOptions(black_box("DEBY")) - .custom("x-myapp-data", black_box("myappdata; excellent")) - .custom("something", black_box("anything")) - ; - - b.iter(|| { +#[bench] +fn headermap_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> MyHeaderMap { + let mut h = MyHeaderMap::new(); + h.set() + .AccessControlAllowCredentials(black_box("true")) + .AccessControlAllowHeaders(black_box("X-Custom-Header,Upgrade-Insecure-Requests")) + .AccessControlAllowOrigin(black_box("https://foo.bar.org")) + .AccessControlAllowMethods(black_box("POST,GET,OPTIONS,DELETE")) + .AccessControlMaxAge(black_box("86400")) + .Vary(black_box("Origin")) + .Server(black_box("ohkami")) + .Connection(black_box("Keep-Alive")) + .Date(black_box("Wed, 21 Oct 2015 07:28:00 GMT")) + .AltSvc(black_box("h2=\":433\"; ma=2592000")) + .ProxyAuthenticate(black_box("Basic realm=\"Access to the internal site\"")) + .ReferrerPolicy(black_box("same-origin")) + .XFrameOptions(black_box("DEBY")) + .custom("x-myapp-data", black_box("myappdata; excellent")) + .custom("something", black_box("anything")) + ; h.set() .AccessControlAllowCredentials(None) .AccessControlAllowHeaders(None) @@ -407,30 +429,31 @@ use ohkami_benches::response_headers::{ .custom("x-myapp-data", None) .custom("something", None) ; + h }); } -#[bench] fn remove_header_hashbrown(b: &mut test::Bencher) { - let mut h = HeaderHashBrown::::new(); - h - .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowCredentials, black_box(b"true")) - .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowHeaders, black_box(b"X-Custom-Header,Upgrade-Insecure-Requests")) - .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowOrigin, black_box(b"https://foo.bar.org")) - .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowMethods, black_box(b"POST,GET,OPTIONS,DELETE")) - .insert_standard_from_reqbytes(StandardHeader::AccessControlMaxAge, black_box(b"86400")) - .insert_standard_from_reqbytes(StandardHeader::Vary, black_box(b"Origin")) - .insert_standard_from_reqbytes(StandardHeader::Server, black_box(b"ohkami")) - .insert_standard_from_reqbytes(StandardHeader::Connection, black_box(b"Keep-Alive")) - .insert_standard_from_reqbytes(StandardHeader::Date, black_box(b"Wed, 21 Oct 2015 07:28:00 GMT")) - .insert_standard_from_reqbytes(StandardHeader::AltSvc, black_box(b"h2=\":433\"; ma=2592000")) - .insert_standard_from_reqbytes(StandardHeader::ProxyAuthenticate, black_box(b"Basic realm=\"Access to the internal site\"")) - .insert_standard_from_reqbytes(StandardHeader::ReferrerPolicy, black_box(b"same-origin")) - .insert_standard_from_reqbytes(StandardHeader::XFrameOptions, black_box(b"DEBY")) - .insert_from_reqbytes(b"x-myapp-data", black_box(b"myappdata; excellent")) - .insert_from_reqbytes(b"something", black_box(b"anything")) - ; - - b.iter(|| { +#[bench] +fn header_hashbrown_insert_and_remove(b: &mut test::Bencher) { + b.iter(|| -> HeaderHashBrown { + let mut h = HeaderHashBrown::::new(); + h + .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowCredentials, black_box(b"true")) + .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowHeaders, black_box(b"X-Custom-Header,Upgrade-Insecure-Requests")) + .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowOrigin, black_box(b"https://foo.bar.org")) + .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowMethods, black_box(b"POST,GET,OPTIONS,DELETE")) + .insert_standard_from_reqbytes(StandardHeader::AccessControlMaxAge, black_box(b"86400")) + .insert_standard_from_reqbytes(StandardHeader::Vary, black_box(b"Origin")) + .insert_standard_from_reqbytes(StandardHeader::Server, black_box(b"ohkami")) + .insert_standard_from_reqbytes(StandardHeader::Connection, black_box(b"Keep-Alive")) + .insert_standard_from_reqbytes(StandardHeader::Date, black_box(b"Wed, 21 Oct 2015 07:28:00 GMT")) + .insert_standard_from_reqbytes(StandardHeader::AltSvc, black_box(b"h2=\":433\"; ma=2592000")) + .insert_standard_from_reqbytes(StandardHeader::ProxyAuthenticate, black_box(b"Basic realm=\"Access to the internal site\"")) + .insert_standard_from_reqbytes(StandardHeader::ReferrerPolicy, black_box(b"same-origin")) + .insert_standard_from_reqbytes(StandardHeader::XFrameOptions, black_box(b"DEBY")) + .insert_from_reqbytes(b"x-myapp-data", black_box(b"myappdata; excellent")) + .insert_from_reqbytes(b"something", black_box(b"anything")) + ; h .remove_standard(StandardHeader::AccessControlAllowCredentials) .remove_standard(StandardHeader::AccessControlAllowHeaders) @@ -449,12 +472,14 @@ use ohkami_benches::response_headers::{ .remove("x-myapp-data") .remove("something") ; + h }); } -#[bench] fn write_03_ohkami(b: &mut test::Bencher) { +#[bench] +fn write_ohkami(b: &mut test::Bencher) { let mut h = ResponseHeaders::_new(); h.set() .access_control_allow_credentials(black_box("true")) @@ -475,13 +500,15 @@ use ohkami_benches::response_headers::{ .x("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h._write_to(&mut buf); + buf }); } /* -#[bench] fn write_heap_ohkami_only_standards(b: &mut test::Bencher) { +#[bench] +fn write_heap_ohkami_only_standards(b: &mut test::Bencher) { let mut h = HeapOhkamiHeaders::new(); h.set() .AccessControlAllowCredentials(black_box("true")) @@ -502,12 +529,14 @@ use ohkami_benches::response_headers::{ .custom("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_standards_to(&mut buf); + buf }); } -#[bench] fn write_heap_ohkami_nosize(b: &mut test::Bencher) { +#[bench] +fn write_heap_ohkami_nosize(b: &mut test::Bencher) { let mut h = HeapOhkamiHeadersWithoutSize::new(); h.set() .AccessControlAllowCredentials(black_box("true")) @@ -528,12 +557,14 @@ use ohkami_benches::response_headers::{ .custom("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_to(&mut buf); + buf }); } -#[bench] fn write_heap_ohkami_only_standards_nosize(b: &mut test::Bencher) { +#[bench] +fn write_heap_ohkami_only_standards_nosize(b: &mut test::Bencher) { let mut h = HeapOhkamiHeadersWithoutSize::new(); h.set() .AccessControlAllowCredentials(black_box("true")) @@ -554,14 +585,16 @@ use ohkami_benches::response_headers::{ .custom("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_standards_to(&mut buf); + buf }); } */ -#[bench] fn write_02_http_crate(b: &mut test::Bencher) { +#[bench] +fn write_http_crate(b: &mut test::Bencher) { let mut h = HeaderMap::new(); h.insert(header::ACCESS_CONTROL_ALLOW_CREDENTIALS, HeaderValue::from_static(black_box("true"))); h.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static(black_box("X-Custom-Header,Upgrade-Insecure-Requests"))); @@ -580,8 +613,8 @@ use ohkami_benches::response_headers::{ h.insert(HeaderName::from_static("x-myapp-data"), HeaderValue::from_static(black_box("myappdata; excellent"))); h.insert(HeaderName::from_static("something"), HeaderValue::from_static(black_box("anything"))); - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); for (k, v) in h.iter() { buf.extend_from_slice(k.as_str().as_bytes()); buf.extend(b": "); @@ -589,10 +622,12 @@ use ohkami_benches::response_headers::{ buf.extend(b"\r\n"); } buf.extend(b"\r\n"); + buf }); } -#[bench] fn write_03_fxmap(b: &mut test::Bencher) { +#[bench] +fn write_fxmap(b: &mut test::Bencher) { let mut h = FxMap::new(); h .insert("Access-Control-Allow-Credentials", black_box("true")) @@ -612,13 +647,15 @@ use ohkami_benches::response_headers::{ .insert("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_to(&mut buf); + buf }); } -#[bench] fn write_04_headermap(b: &mut test::Bencher) { +#[bench] +fn write_headermap(b: &mut test::Bencher) { let mut h = MyHeaderMap::new(); h.set() .AccessControlAllowCredentials(black_box("true")) @@ -638,13 +675,15 @@ use ohkami_benches::response_headers::{ .custom("something", black_box("anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_to(&mut buf); + buf }); } -#[bench] fn write_03_header_hashbrown(b: &mut test::Bencher) { +#[bench] +fn write_header_hashbrown(b: &mut test::Bencher) { let mut h = HeaderHashBrown::::new(); h .insert_standard_from_reqbytes(StandardHeader::AccessControlAllowCredentials, black_box(b"true")) @@ -664,8 +703,9 @@ use ohkami_benches::response_headers::{ .insert_from_reqbytes(b"something", black_box(b"anything")) ; - let mut buf = Vec::new(); - b.iter(|| { + b.iter(|| -> Vec { + let mut buf = Vec::new(); h.write_to(&mut buf); + buf }); } diff --git a/benches_rt/tokio/src/bin/headers.rs b/benches_rt/tokio/src/bin/headers.rs new file mode 100644 index 000000000..f0692ea5e --- /dev/null +++ b/benches_rt/tokio/src/bin/headers.rs @@ -0,0 +1,31 @@ +use ohkami::prelude::*; + +#[derive(Clone)] +struct SetHeaders; +impl FangAction for SetHeaders { + async fn back(&self, res: &mut Response) { + res.headers.set() + .server("Ohkami") + .cross_origin_embedder_policy("require-corp") + .cross_origin_resource_policy("same-origin") + .referrer_policy("no-referrer") + .strict_transport_security("max-age=15552000; includeSubDomains") + .x_content_type_options("nosniff") + .x_frame_options("SAMEORIGIN") + ; + } +} + +fn main() { + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .event_interval(11) + .global_queue_interval(31) + .build() + .expect("Failed building the Runtime") + .block_on(Ohkami::new(( + SetHeaders, + "/user/:id" + .GET(|Path(id): Path| async {id}), + )).howl("0.0.0.0:3000")) +} diff --git a/ohkami/src/header/map.rs b/ohkami/src/header/map.rs index a6ca3805e..9282b99ad 100644 --- a/ohkami/src/header/map.rs +++ b/ohkami/src/header/map.rs @@ -1,79 +1,113 @@ -pub(crate) struct IndexMap { - index: [u8; N], - values: Vec<(usize, Value)>, -} +type Byte = u8; + +const NULL: Byte = Byte::MAX; -impl IndexMap { - const NULL: u8 = u8::MAX; +pub(crate) struct ByteArrayMap { + /// using `u8` instead of `usize` to save memory space, + /// with implicitly limiting the capacity to 255 + /// (0-254, since 255 is used as `NULL` to indicate non-existence). + indices: [u8; N], + entries: Vec<(Byte, Value)>, +} +impl ByteArrayMap { + /// SAFETY: `N` must be <= 255. #[inline] pub(crate) fn new() -> Self { Self { - index: [Self::NULL; N], - values: Vec::with_capacity(N / 4) + indices: [NULL; N], + entries: Vec::with_capacity(N / 4) } } #[allow(unused)] #[inline] pub(crate) fn clear(&mut self) { - for idx in &mut self.index {*idx = Self::NULL} - self.values.clear(); + self.indices.fill(NULL); + self.entries.clear(); } + /// SAFETY: the `byte` must be in the range of `0..N`. #[inline(always)] - pub(crate) unsafe fn get(&self, index: usize) -> Option<&Value> { - unsafe {match *self.index.get_unchecked(index) { - Self::NULL => None, - index => Some(&self.values.get_unchecked(index as usize).1) - }} + pub(crate) unsafe fn get(&self, byte: Byte) -> Option<&Value> { + match unsafe {*self.indices.get_unchecked(byte as usize)} { + NULL => None, + index => Some(unsafe {&self.entries.get_unchecked(index as usize).1}) + } } + /// SAFETY: the `byte` must be in the range of `0..N`. #[inline(always)] - pub(crate) unsafe fn get_mut(&mut self, index: usize) -> Option<&mut Value> { - unsafe {match *self.index.get_unchecked(index) { - Self::NULL => None, - index => Some(&mut self.values.get_unchecked_mut(index as usize).1) - }} + pub(crate) unsafe fn get_mut(&mut self, byte: Byte) -> Option<&mut Value> { + match unsafe {*self.indices.get_unchecked(byte as usize)} { + NULL => None, + index => Some(unsafe {&mut self.entries.get_unchecked_mut(index as usize).1}) + } } + /// SAFETY: the `byte` must be in the range of `0..N`. #[inline(always)] - pub(crate) unsafe fn delete(&mut self, index: usize) { - *unsafe {self.index.get_unchecked_mut(index)} = Self::NULL; + pub(crate) unsafe fn delete(&mut self, byte: Byte) { + match std::mem::replace(unsafe {self.indices.get_unchecked_mut(byte as usize)}, NULL) { + NULL => (), + prev_index => { + let prev_index = prev_index as usize; + self.entries.swap_remove(prev_index); + if prev_index == self.entries.len() { + // removed the last element; do nothing + } else { + // the last entry is now moved to `prev_index`; update its index + let moved_byte = unsafe {self.entries.get_unchecked(prev_index).0}; + unsafe {*self.indices.get_unchecked_mut(moved_byte as usize) = prev_index as u8}; + } + } + } } + /// SAFETY: the `byte` must be in the range of `0..N`. #[inline(always)] - pub(crate) unsafe fn set(&mut self, index: usize, value: Value) { - *unsafe {self.index.get_unchecked_mut(index)} = self.values.len() as u8; - self.values.push((index, value)); + pub(crate) unsafe fn insert(&mut self, byte: Byte, value: Value) { + let index_mut = unsafe {self.indices.get_unchecked_mut(byte as usize)}; + match *index_mut { + NULL => { + *index_mut = self.entries.len() as u8; + self.entries.push((byte, value)); + } + index => { + unsafe {self.entries.get_unchecked_mut(index as usize).1 = value}; + } + } } - + /// SAFETY: + /// + /// 1. the `byte` must be in the range of `0..N`. + /// 2. the `byte` must not already exist in the map. #[inline(always)] - pub(crate) fn iter(&self) -> impl Iterator { - self.values.iter() - .enumerate() - .filter_map(|(pos, (index, value))| ( - // `!= Self::NULL` can't correctly handle *over-set after delete*, - // we MUST check the held index to be equal to the current position - *unsafe {self.index.get_unchecked(*index)} == pos as u8 - ).then_some((*index, value))) + pub(crate) unsafe fn insert_new(&mut self, byte: Byte, value: Value) { + #[cfg(debug_assertions)] { + assert_eq!( + unsafe {*self.indices.get_unchecked(byte as usize)}, + NULL, + "ByteArrayMap::insert_new: the byte `{byte}` already exists in the map" + ); + } + unsafe {*self.indices.get_unchecked_mut(byte as usize) = self.entries.len() as u8}; + self.entries.push((byte, value)); } #[inline(always)] - pub(crate) fn into_iter(self) -> impl Iterator { - self.values.into_iter() - .enumerate() - .filter_map(move |(pos, (index, value))| ( - // `!= Self::NULL` can't correctly handle *over-set after delete*, - // we MUST check the held index to be equal to the current position - *unsafe {self.index.get_unchecked(index)} == pos as u8 - ).then_some((index, value))) + pub(crate) fn iter(&self) -> impl Iterator { + self.entries.iter() + } + #[inline(always)] + pub(crate) fn into_iter(self) -> impl Iterator { + self.entries.into_iter() } } const _: () = { - impl PartialEq for IndexMap { + impl PartialEq for ByteArrayMap { fn eq(&self, other: &Self) -> bool { - for i in 0..N { + for i in 0..N as u8 { if unsafe {self.get(i)} != unsafe {other.get(i)} { return false } @@ -81,11 +115,11 @@ const _: () = { } } - impl Clone for IndexMap { + impl Clone for ByteArrayMap { fn clone(&self) -> Self { Self { - index: self.index.clone(), - values: self.values.clone(), + indices: self.indices.clone(), + entries: self.entries.clone(), } } } @@ -94,79 +128,103 @@ const _: () = { #[cfg(test)] mod test { use super::*; + use std::collections::HashMap; #[test] fn test_index_map_iter_simple() { - let mut map = IndexMap::<8, &'static str>::new(); + let mut map = ByteArrayMap::<8, &'static str>::new(); - unsafe {map.set(0, "a")}; - unsafe {map.set(1, "b")}; - unsafe {map.set(2, "c")}; - unsafe {map.set(3, "d")}; + unsafe {map.insert(0, "a")}; + unsafe {map.insert(1, "b")}; + unsafe {map.insert(2, "c")}; + unsafe {map.insert(3, "d")}; assert_eq!( - map.into_iter().collect::>(), - vec![(0, "a"), (1, "b"), (2, "c"), (3, "d")] + map.into_iter().collect::>(), + HashMap::from_iter([(0, "a"), (1, "b"), (2, "c"), (3, "d")]) ); } #[test] fn test_index_map_iter_with_delete() { - let mut map = IndexMap::<8, &'static str>::new(); + let mut map = ByteArrayMap::<8, &'static str>::new(); - unsafe {map.set(0, "a")}; - unsafe {map.set(1, "b")}; - unsafe {map.set(2, "c")}; - unsafe {map.set(3, "d")}; + unsafe {map.insert(0, "a")}; + unsafe {map.insert(1, "b")}; + unsafe {map.insert(2, "c")}; + unsafe {map.insert(3, "d")}; unsafe {map.delete(1)}; unsafe {map.delete(3)}; assert_eq!( - map.into_iter().collect::>(), - vec![(0, "a"), (2, "c")] + map.into_iter().collect::>(), + HashMap::from_iter([(0, "a"), (2, "c")]) ); } #[test] - fn test_index_map_iter_with_delete_and_other_set() { - let mut map = IndexMap::<8, &'static str>::new(); + fn test_index_map_get_with_delete_and_other_set() { + let mut map = ByteArrayMap::<8, &'static str>::new(); - unsafe {map.set(0, "a")}; - unsafe {map.set(1, "b")}; - unsafe {map.set(2, "c")}; - unsafe {map.set(3, "d")}; + unsafe {map.insert(0, "a")}; + unsafe {map.insert(1, "b")}; + unsafe {map.insert(2, "c")}; + unsafe {map.insert(3, "d")}; unsafe {map.delete(1)}; unsafe {map.delete(3)}; - unsafe {map.set(4, "e")}; - unsafe {map.set(5, "f")}; + unsafe {map.insert(4, "e")}; + unsafe {map.insert(5, "f")}; - assert_eq!( - map.into_iter().collect::>(), - vec![(0, "a"), (2, "c"), (4, "e"), (5, "f")] - ); + assert_eq!(unsafe {map.get(0)}, Some(&"a")); + assert_eq!(unsafe {map.get(1)}, None); + assert_eq!(unsafe {map.get(2)}, Some(&"c")); + assert_eq!(unsafe {map.get(3)}, None); + assert_eq!(unsafe {map.get(4)}, Some(&"e")); + assert_eq!(unsafe {map.get(5)}, Some(&"f")); + } + + #[test] + fn test_index_map_get_with_delete_and_overset() { + let mut map = ByteArrayMap::<8, &'static str>::new(); + + unsafe {map.insert(0, "a")}; + unsafe {map.insert(1, "b")}; + unsafe {map.insert(2, "c")}; + unsafe {map.insert(3, "d")}; + + unsafe {map.delete(1)}; + unsafe {map.delete(3)}; + + unsafe {map.insert(1, "e")}; + unsafe {map.insert(3, "f")}; + + assert_eq!(unsafe {map.get(0)}, Some(&"a")); + assert_eq!(unsafe {map.get(1)}, Some(&"e")); + assert_eq!(unsafe {map.get(2)}, Some(&"c")); + assert_eq!(unsafe {map.get(3)}, Some(&"f")); } #[test] fn test_index_map_iter_with_delete_and_overset() { - let mut map = IndexMap::<8, &'static str>::new(); + let mut map = ByteArrayMap::<8, &'static str>::new(); - unsafe {map.set(0, "a")}; - unsafe {map.set(1, "b")}; - unsafe {map.set(2, "c")}; - unsafe {map.set(3, "d")}; + unsafe {map.insert(0, "a")}; + unsafe {map.insert(1, "b")}; + unsafe {map.insert(2, "c")}; + unsafe {map.insert(3, "d")}; unsafe {map.delete(1)}; unsafe {map.delete(3)}; - unsafe {map.set(1, "e")}; - unsafe {map.set(3, "f")}; + unsafe {map.insert(1, "e")}; + unsafe {map.insert(3, "f")}; assert_eq!( - map.into_iter().collect::>(), - vec![(0, "a"), (2, "c"), (1, "e"), (3, "f")] + map.into_iter().collect::>(), + HashMap::from_iter([(0, "a"), (2, "c"), (1, "e"), (3, "f")]) ); } } diff --git a/ohkami/src/header/mod.rs b/ohkami/src/header/mod.rs index 734f68fab..c23d0a235 100644 --- a/ohkami/src/header/mod.rs +++ b/ohkami/src/header/mod.rs @@ -17,4 +17,4 @@ mod setcookie; pub(crate) use setcookie::*; mod map; -pub(crate) use map::IndexMap; +pub(crate) use map::ByteArrayMap; diff --git a/ohkami/src/request/headers.rs b/ohkami/src/request/headers.rs index 505efdc26..59f8f75de 100644 --- a/ohkami/src/request/headers.rs +++ b/ohkami/src/request/headers.rs @@ -1,10 +1,10 @@ -use crate::header::{IndexMap, Append}; +use crate::header::{ByteArrayMap, Append}; use std::borrow::Cow; use ohkami_lib::{CowSlice, Slice, map::TupleMap}; pub struct Headers { - standard: IndexMap, + standard: ByteArrayMap, custom: Option>>, } @@ -200,7 +200,7 @@ macro_rules! Header { .get(&Slice::from_bytes(name.as_bytes())) .or_else(|| { let standard = Header::from_bytes(name.as_bytes())?; - unsafe {self.standard.get(standard as usize)} + unsafe {self.standard.get(standard as u8)} })?; std::str::from_utf8(unsafe {value.as_bytes()}).ok() } @@ -280,7 +280,7 @@ impl Headers { pub(crate) fn iter(&self) -> impl Iterator { self.standard.iter() .filter_map(|(i, v)| Some(( - unsafe {std::mem::transmute::<_, Header>(i as u8).as_str()}, + unsafe {std::mem::transmute::<_, Header>(*i).as_str()}, std::str::from_utf8(v).ok()? ))) .chain(self.custom.as_ref().into_iter() @@ -294,20 +294,23 @@ impl Headers { } impl Headers { - #[inline(always)] pub(crate) fn insert(&mut self, name: Header, value: CowSlice) { - unsafe {self.standard.set(name as usize, value)} + #[inline(always)] + pub(crate) fn insert(&mut self, name: Header, value: CowSlice) { + unsafe {self.standard.insert(name as u8, value)} } #[cfg(feature="DEBUG")] - #[inline(always)] pub fn _insert(&mut self, name: Header, value: CowSlice) { + #[inline(always)] + pub fn _insert(&mut self, name: Header, value: CowSlice) { self.insert(name, value) } pub(crate) fn remove(&mut self, name: Header) { - unsafe {self.standard.delete(name as usize)} + unsafe {self.standard.delete(name as u8)}; } - #[inline] pub(crate) fn get_standard(&self, name: Header) -> Option<&str> { - unsafe {match self.standard.get(name as usize) { + #[inline] + pub(crate) fn get_standard(&self, name: Header) -> Option<&str> { + unsafe {match self.standard.get(name as u8) { Some(cs) => std::str::from_utf8(&cs).ok(), None => None }} @@ -315,18 +318,24 @@ impl Headers { #[inline(always)] pub(crate) fn append(&mut self, name: Header, value: CowSlice) { - unsafe {match self.standard.get_mut(name as usize) { - None => self.standard.set(name as usize, value), + unsafe {match self.standard.get_mut(name as u8) { + None => self.standard.insert_new(name as u8, value), Some(v) => { v.extend_from_slice(b", "); v.extend_from_slice(&value); } }} } + #[cfg(feature="DEBUG")] + #[inline] + pub fn _append(&mut self, name: Header, value: CowSlice) { + self.append(name, value) + } } impl Headers { - #[inline] pub(crate) fn insert_custom(&mut self, name: Slice, value: CowSlice) { + #[inline] + pub(crate) fn insert_custom(&mut self, name: Slice, value: CowSlice) { match &mut self.custom { Some(c) => {c.insert(name, value);} None => self.custom = Some(Box::new(TupleMap::from_iter([ @@ -335,11 +344,13 @@ impl Headers { } } #[cfg(feature="DEBUG")] - #[inline] pub fn _insert_custom(&mut self, name: Slice, value: CowSlice) { + #[inline] + pub fn _insert_custom(&mut self, name: Slice, value: CowSlice) { self.insert_custom(name, value) } - #[inline] pub(crate) fn append_custom(&mut self, name: Slice, value: CowSlice) { + #[inline] + pub(crate) fn append_custom(&mut self, name: Slice, value: CowSlice) { if self.custom.is_none() { self.custom = Some(Box::new(TupleMap::new())) } @@ -363,7 +374,7 @@ impl Headers { #[inline] pub(crate) fn new() -> Self { Self { - standard: IndexMap::new(), + standard: ByteArrayMap::new(), custom: None, } } @@ -389,7 +400,7 @@ impl Headers { )) ))] #[inline] pub(crate) fn get_raw(&self, name: Header) -> Option<&CowSlice> { - unsafe {self.standard.get(name as usize)} + unsafe {self.standard.get(name as u8)} } #[allow(unused)] diff --git a/ohkami/src/request/mod.rs b/ohkami/src/request/mod.rs index 77e379891..3222da302 100644 --- a/ohkami/src/request/mod.rs +++ b/ohkami/src/request/mod.rs @@ -22,7 +22,9 @@ pub use from_request::FromRequest; #[cfg(test)] mod _test_extract; #[cfg(test)] mod _test_headers; -use ohkami_lib::{Slice, CowSlice}; +use ohkami_lib::CowSlice; +#[cfg(feature="__rt__")] +use ohkami_lib::Slice; #[cfg(feature="__rt_native__")] use crate::__rt__::AsyncRead; diff --git a/ohkami/src/response/headers.rs b/ohkami/src/response/headers.rs index ecf9f37c0..03fddb525 100644 --- a/ohkami/src/response/headers.rs +++ b/ohkami/src/response/headers.rs @@ -1,11 +1,11 @@ -use crate::header::{IndexMap, Append, SetCookie, SetCookieBuilder}; +use crate::header::{ByteArrayMap, Append, SetCookie, SetCookieBuilder}; use ohkami_lib::map::TupleMap; use std::borrow::Cow; #[derive(Clone)] pub struct Headers { - standard: IndexMap>, + standard: ByteArrayMap>, custom: Option>>>, pub(super) setcookie: Option>>>, pub(super) size: usize, @@ -311,10 +311,10 @@ impl Headers { #[inline(always)] pub(crate) fn insert(&mut self, name: Header, value: Cow<'static, str>) { let (name_len, value_len) = (name.len(), value.len()); - match unsafe {self.standard.get_mut(name as usize)} { + match unsafe {self.standard.get_mut(name as u8)} { None => { + unsafe {self.standard.insert_new(name as u8, value)}; self.size += name_len + ": ".len() + value_len + "\r\n".len(); - unsafe {self.standard.set(name as usize, value)} } Some(old) => { self.size -= old.len(); self.size += value_len; @@ -343,10 +343,10 @@ impl Headers { #[inline] pub(crate) fn remove(&mut self, name: Header) { let name_len = name.len(); - if let Some(v) = unsafe {self.standard.get(name as usize)} { - self.size -= name_len + ": ".len() + v.len() + "\r\n".len() + if let Some(v) = unsafe {self.standard.get(name as u8)} { + self.size -= name_len + ": ".len() + v.len() + "\r\n".len(); + unsafe {self.standard.delete(name as u8)}; } - unsafe {self.standard.delete(name as usize)} } pub(crate) fn remove_custom(&mut self, name: &'static str) { if let Some(c) = self.custom.as_mut() { @@ -358,7 +358,7 @@ impl Headers { #[inline(always)] pub(crate) fn get_standard(&self, name: Header) -> Option<&str> { - unsafe {self.standard.get(name as usize)}.map(Cow::as_ref) + unsafe {self.standard.get(name as u8)}.map(Cow::as_ref) } #[inline] pub(crate) fn get_custom(&self, name: &'static str) -> Option<&str> { @@ -369,7 +369,7 @@ impl Headers { pub(crate) fn append(&mut self, name: Header, value: Cow<'static, str>) { let value_len = value.len(); - let target = unsafe {self.standard.get_mut(name as usize)}; + let target = unsafe {self.standard.get_mut(name as u8)}; self.size += match target { Some(v) => { @@ -389,7 +389,7 @@ impl Headers { ", ".len() + value_len } None => { - unsafe {self.standard.set(name as usize, value)} + unsafe {self.standard.insert_new(name as u8, value)} name.len() + ": ".len() + value_len + "\r\n".len() } }; @@ -432,7 +432,7 @@ impl Headers { #[inline] pub(crate) fn new() -> Self { let mut this = Self { - standard: IndexMap::new(), + standard: ByteArrayMap::new(), custom: None, setcookie: None, size: "\r\n".len(), @@ -451,7 +451,7 @@ impl Headers { pub(crate) fn iter_standard(&self) -> impl Iterator { self.standard.iter() .map(|(i, v)| ( - unsafe {std::mem::transmute::<_, Header>(i as u8)}.as_str(), + unsafe {std::mem::transmute::<_, Header>(*i)}.as_str(), &**v )) } @@ -471,7 +471,7 @@ impl Headers { pub fn into_iter(self) -> impl Iterator)> { let standard = self.standard.into_iter() .map(|(i, v)| ( - unsafe {std::mem::transmute::<_, Header>(i as u8)}.as_str(), + unsafe {std::mem::transmute::<_, Header>(i)}.as_str(), v )); let custom = self.custom.into_iter() @@ -493,7 +493,7 @@ impl Headers { pub(crate) unsafe fn write_unchecked_to(&self, buf: &mut Vec) { unsafe { for (i, v) in self.standard.iter() { - let h = std::mem::transmute::<_, Header>(i as u8); { + let h = std::mem::transmute::<_, Header>(*i); { crate::push_unchecked!(buf <- h.as_bytes()); crate::push_unchecked!(buf <- b": "); crate::push_unchecked!(buf <- v.as_bytes());