diff --git a/README.md b/README.md index 863b88a7..e9710867 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ A collection of different transport implementations and related tools focused pr 1. [Client API Framework](https://c410-f3r.github.io/wtx/client-api-framework/index.html) 2. [Database Client](https://c410-f3r.github.io/wtx/database-client/index.html) -3. [Database Schema Manager](https://c410-f3r.github.io/wtx/database-schema-managemer/index.html) +3. [Database Schema Manager](https://c410-f3r.github.io/wtx/database-schema-manager/index.html) 4. [gRPC Client/Server](https://c410-f3r.github.io/wtx/grpc/index.html) 5. [HTTP Client Framework](https://c410-f3r.github.io/wtx/http-client-framework/index.html) 6. [HTTP Server Framework](https://c410-f3r.github.io/wtx/http-server-framework/index.html) 7. [HTTP2 Client/Server](https://c410-f3r.github.io/wtx/http2/index.html) -8. [Pool Manager](https://c410-f3r.github.io/wtx/pool-manager/index.html) +8. [Pool Manager](https://c410-f3r.github.io/wtx/pool/index.html) 9. [UI tools](https://c410-f3r.github.io/wtx/ui-tools/index.html) 10. [WebSocket Client/Server](https://c410-f3r.github.io/wtx/web-socket/index.html) diff --git a/wtx-instances/http-server-framework-examples/http-server-framework-session.rs b/wtx-instances/http-server-framework-examples/http-server-framework-session.rs index d2b2dc03..8957cd5d 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework-session.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework-session.rs @@ -58,7 +58,7 @@ async fn main() -> wtx::Result<()> { (SessionDecoder::new(), SessionEnforcer::new([LOGIN, LOGOUT])), (), )?; - let pool = Pool::new(4, PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME")); + let pool = Pool::new(4, PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME".into())); let mut rng = StdRng::default(); let mut key = [0; 16]; rng.fill_slice(&mut key); diff --git a/wtx-instances/http-server-framework-examples/http-server-framework.rs b/wtx-instances/http-server-framework-examples/http-server-framework.rs index 08225183..a698dcfb 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework.rs @@ -41,7 +41,7 @@ async fn main() -> wtx::Result<()> { )?, ), ))?; - let rm = PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME"); + let rm = PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME".into()); let pool = Pool::new(4, rm); ServerFrameworkBuilder::new(router) .with_req_aux(move || pool.clone()) diff --git a/wtx/src/http/req_res_data.rs b/wtx/src/http/req_res_data.rs index 7a08020b..2984c2d0 100644 --- a/wtx/src/http/req_res_data.rs +++ b/wtx/src/http/req_res_data.rs @@ -1,6 +1,6 @@ use crate::{ http::Headers, - misc::{Lease, Uri, UriRef}, + misc::{Lease, LeaseMut, Uri, UriRef}, }; use alloc::boxed::Box; @@ -285,3 +285,16 @@ impl ReqResDataMut for Headers { (&mut [], self, UriRef::_empty("")) } } + +impl ReqResDataMut for (B, H) +where + H: LeaseMut, +{ + #[inline] + fn clear(&mut self) {} + + #[inline] + fn parts_mut(&mut self) -> (&mut Self::Body, &mut Headers, UriRef<'_>) { + (&mut self.0, self.1.lease_mut(), UriRef::_empty("")) + } +} diff --git a/wtx/src/http/request.rs b/wtx/src/http/request.rs index 2670d9a9..596fc167 100644 --- a/wtx/src/http/request.rs +++ b/wtx/src/http/request.rs @@ -15,6 +15,11 @@ impl Request where RRD: ReqResData, { + #[inline] + pub(crate) fn _new(method: Method, rrd: RRD, version: Version) -> Self { + Self { method, rrd, version } + } + /// Constructor that defaults to an HTTP/2 version. #[inline] pub fn http2(method: Method, rrd: RRD) -> Self { diff --git a/wtx/src/http/server_framework/cors_middleware.rs b/wtx/src/http/server_framework/cors_middleware.rs index 06803f22..22ee4cc3 100644 --- a/wtx/src/http/server_framework/cors_middleware.rs +++ b/wtx/src/http/server_framework/cors_middleware.rs @@ -1,6 +1,7 @@ use crate::{ http::{ - server_framework::ResMiddleware, Header, KnownHeaderName, Method, ReqResDataMut, Response, + server_framework::{ConnAux, ResMiddleware}, + Header, KnownHeaderName, Method, ReqResDataMut, Response, }, misc::ArrayVector, }; @@ -106,6 +107,15 @@ impl CorsMiddleware { } } +impl ConnAux for CorsMiddleware { + type Init = CorsMiddleware; + + #[inline] + fn conn_aux(init: Self::Init) -> crate::Result { + Ok(init) + } +} + impl ResMiddleware for CorsMiddleware where E: From, diff --git a/wtx/src/http/server_framework/param_wrappers/path_str.rs b/wtx/src/http/server_framework/param_wrappers/path_str.rs index 1d629334..0df881de 100644 --- a/wtx/src/http/server_framework/param_wrappers/path_str.rs +++ b/wtx/src/http/server_framework/param_wrappers/path_str.rs @@ -1,7 +1,7 @@ use crate::{ http::{ - server_framework::{param_wrappers::manage_path, Endpoint, ResFinalizer}, - ReqResDataMut, Request, StatusCode, + server_framework::{param_wrappers::manage_path, Endpoint, ResFinalizer, StateClean}, + Headers, ReqResDataMut, Request, StatusCode, }, misc::{FnFut, FnFutWrapper}, }; @@ -34,3 +34,29 @@ where self.0.call((PathStr(path),)).await.finalize_response(req) } } + +impl Endpoint + for FnFutWrapper<(StateClean<'_, CA, RA, (&mut RRD::Body, &mut Headers)>, PathStr<'_>), F> +where + E: From, + F: for<'any> FnFut< + (StateClean<'any, CA, RA, (&'any mut RRD::Body, &'any mut Headers)>, PathStr<'any>), + Result = RES, + >, + RES: ResFinalizer, + RRD: ReqResDataMut, +{ + #[inline] + async fn call( + &self, + ca: &mut CA, + path_defs: (u8, &[(&'static str, u8)]), + ra: &mut RA, + req: &mut Request, + ) -> Result { + let (body, headers, uri) = req.rrd.parts_mut(); + let mut new_req = Request::_new(req.method, (body, headers), req.version); + let path = manage_path(path_defs, &uri).map_err(From::from)?; + self.0.call((StateClean::new(ca, ra, &mut new_req), PathStr(path))).await.finalize_response(req) + } +} diff --git a/wtx/src/http2/client_stream.rs b/wtx/src/http2/client_stream.rs index 5f8222b2..2d0aba11 100644 --- a/wtx/src/http2/client_stream.rs +++ b/wtx/src/http2/client_stream.rs @@ -128,7 +128,7 @@ where RRD::Body: Lease<[u8]>, { let _e = self.span._enter(); - _trace!("Sending response"); + _trace!("Sending request"); let uri = match req_uri.into() { ReqUri::Data => &req.rrd.uri(), ReqUri::Param(elem) => elem, diff --git a/wtx/src/misc/stream.rs b/wtx/src/misc/stream.rs index d9b898e3..5ea2d55d 100644 --- a/wtx/src/misc/stream.rs +++ b/wtx/src/misc/stream.rs @@ -9,7 +9,7 @@ macro_rules! _local_write_all_vectored { match $write_many { Err(e) => return Err(e.into()), Ok(0) => return Err(crate::Error::UnexpectedStreamWriteEOF), - Ok(n) => crate::misc::stream::advance_slices(&mut &$bytes[..], &mut $io_slices, n), + Ok(n) => std::io::IoSlice::advance_slices(&mut $io_slices, n), } } } @@ -37,38 +37,6 @@ pub trait Stream: StreamReader + StreamWriter {} impl Stream for T where T: StreamReader + StreamWriter {} -#[expect(clippy::mut_mut, reason = "false-positive")] -#[cfg(feature = "std")] -#[inline] -fn advance_slices<'bytes>( - bytes: &mut &[&'bytes [u8]], - io_slices: &mut &mut [::std::io::IoSlice<'bytes>], - written: usize, -) { - let mut first_slice_idx = written; - let mut slices_idx: usize = 0; - for io_slice in io_slices.iter() { - let Some(diff) = first_slice_idx.checked_sub(io_slice.len()) else { - break; - }; - first_slice_idx = diff; - slices_idx = slices_idx.wrapping_add(1); - } - let Some((local_bytes @ [first_bytes, ..], local_io_slices)) = bytes - .get(slices_idx..) - .and_then(|el| Some((el, core::mem::take(io_slices).get_mut(slices_idx..)?))) - else { - return; - }; - *bytes = local_bytes; - *io_slices = local_io_slices; - let [first_io_slices, ..] = io_slices else { - return; - }; - let slice = first_bytes.get(first_slice_idx..).unwrap_or_default(); - *first_io_slices = ::std::io::IoSlice::new(slice); -} - #[cfg(feature = "std")] #[inline] fn convert_to_io_slices<'buffer, 'bytes>( diff --git a/wtx/src/misc/vector.rs b/wtx/src/misc/vector.rs index fa5c0d92..101d0dba 100644 --- a/wtx/src/misc/vector.rs +++ b/wtx/src/misc/vector.rs @@ -52,6 +52,7 @@ impl core::error::Error for VectorError {} #[cfg_attr(feature = "test-strategy", derive(test_strategy::Arbitrary))] #[cfg_attr(feature = "test-strategy", arbitrary(bound(D: proptest::arbitrary::Arbitrary + 'static)))] #[derive(Clone, Eq, PartialEq)] +#[repr(transparent)] pub struct Vector { data: Vec, } diff --git a/wtx/src/pool/resource_manager.rs b/wtx/src/pool/resource_manager.rs index 4f454f93..40161d4b 100644 --- a/wtx/src/pool/resource_manager.rs +++ b/wtx/src/pool/resource_manager.rs @@ -94,6 +94,7 @@ where #[cfg(feature = "postgres")] pub(crate) mod database { use crate::misc::StdRngSync; + use alloc::string::String; use core::marker::PhantomData; /// Manages generic database executors. @@ -103,7 +104,7 @@ pub(crate) mod database { error: PhantomData E>, rng: StdRngSync, stream: PhantomData, - uri: &'static str, + uri: String, } macro_rules! executor { @@ -125,13 +126,14 @@ pub(crate) mod database { misc::StdRngSync, pool::{PostgresRM, ResourceManager}, }; + use alloc::string::String; use core::{marker::PhantomData, mem}; use tokio::net::TcpStream; impl PostgresRM { /// Resource manager using the `tokio` project. #[inline] - pub fn tokio(uri: &'static str) -> Self { + pub fn tokio(uri: String) -> Self { Self { _certs: None, error: PhantomData, @@ -153,7 +155,7 @@ pub(crate) mod database { #[inline] async fn create(&self, _: &Self::CreateAux) -> Result { - executor!(self.uri, |config, uri| { + executor!(&self.uri, |config, uri| { let eb = ExecutorBuffer::with_default_params(&mut &self.rng)?; Executor::connect( &config, @@ -177,7 +179,7 @@ pub(crate) mod database { ) -> Result<(), Self::Error> { let mut buffer = ExecutorBuffer::_empty(); mem::swap(&mut buffer, &mut resource.eb); - *resource = executor!(self.uri, |config, uri| { + *resource = executor!(&self.uri, |config, uri| { let stream = TcpStream::connect(uri.hostname_with_implied_port()).await.map_err(Into::into)?; Executor::connect(&config, buffer, &mut &self.rng, stream) @@ -197,6 +199,7 @@ pub(crate) mod database { misc::{StdRngSync, TokioRustlsConnector}, pool::{PostgresRM, ResourceManager}, }; + use alloc::string::String; use core::{marker::PhantomData, mem}; use tokio::net::TcpStream; use tokio_rustls::client::TlsStream; @@ -204,7 +207,7 @@ pub(crate) mod database { impl PostgresRM> { /// Resource manager using the `tokio-rustls` project. #[inline] - pub fn tokio_rustls(certs: Option<&'static [u8]>, uri: &'static str) -> Self { + pub fn tokio_rustls(certs: Option<&'static [u8]>, uri: String) -> Self { Self { _certs: certs, error: PhantomData, @@ -226,7 +229,7 @@ pub(crate) mod database { #[inline] async fn create(&self, _: &Self::CreateAux) -> Result { - executor!(self.uri, |config, uri| { + executor!(&self.uri, |config, uri| { Executor::connect_encrypted( &config, ExecutorBuffer::with_default_params(&mut &self.rng)?, @@ -256,7 +259,7 @@ pub(crate) mod database { ) -> Result<(), Self::Error> { let mut buffer = ExecutorBuffer::_empty(); mem::swap(&mut buffer, &mut resource.eb); - *resource = executor!(self.uri, |config, uri| { + *resource = executor!(&self.uri, |config, uri| { Executor::connect_encrypted( &config, ExecutorBuffer::with_default_params(&mut &self.rng)?,