-
Notifications
You must be signed in to change notification settings - Fork 0
Restore server typestate and split configuration #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3daf18a
d9cba4e
ebefe6b
65618b6
164e742
4be1d5b
9ae0998
c15dc0b
b8828a8
026f722
1071e96
ff20ace
6f5b12a
7d6288f
3a9388e
34ad468
51bd37d
8035e58
da6dd67
bb5cec0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| //! Binding configuration for [`WireframeServer`]. | ||
|
|
||
| use core::marker::PhantomData; | ||
| use std::{ | ||
| net::{SocketAddr, TcpListener as StdTcpListener}, | ||
| sync::Arc, | ||
| }; | ||
|
|
||
| use tokio::net::TcpListener; | ||
|
|
||
| use super::{Unbound, WireframeServer}; | ||
| use crate::{ | ||
| app::WireframeApp, | ||
| preamble::Preamble, | ||
| server::{Bound, ServerError}, | ||
| }; | ||
|
|
||
| impl<F, T> WireframeServer<F, T, Unbound> | ||
| where | ||
| F: Fn() -> WireframeApp + Send + Sync + Clone + 'static, | ||
| T: Preamble, | ||
| { | ||
| /// Return `None` as the server is not bound. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// assert!( | ||
| /// WireframeServer::new(|| WireframeApp::default()) | ||
| /// .local_addr() | ||
| /// .is_none() | ||
| /// ); | ||
| /// ``` | ||
| #[must_use] | ||
| pub const fn local_addr(&self) -> Option<SocketAddr> { None } | ||
|
|
||
| /// Bind to a fresh address. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use std::net::{Ipv4Addr, SocketAddr}; | ||
| /// | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 0)); | ||
| /// let server = WireframeServer::new(|| WireframeApp::default()) | ||
| /// .bind(addr) | ||
| /// .expect("bind failed"); | ||
| /// assert!(server.local_addr().is_some()); | ||
| /// ``` | ||
| /// | ||
| /// # Errors | ||
| /// Returns a [`ServerError`] if binding or configuring the listener fails. | ||
| pub fn bind(self, addr: SocketAddr) -> Result<WireframeServer<F, T, Bound>, ServerError> { | ||
| let std = StdTcpListener::bind(addr).map_err(ServerError::Bind)?; | ||
| self.bind_listener(std) | ||
| } | ||
|
Comment on lines
+57
to
+60
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Factor out duplicated listener-setup code Both Also applies to: 143-180 🤖 Prompt for AI Agents |
||
|
|
||
| /// Bind to an existing `StdTcpListener`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use std::net::{Ipv4Addr, SocketAddr, TcpListener as StdTcpListener}; | ||
| /// | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// let std = StdTcpListener::bind(SocketAddr::from((Ipv4Addr::LOCALHOST, 0))).unwrap(); | ||
| /// let server = WireframeServer::new(|| WireframeApp::default()) | ||
| /// .bind_listener(std) | ||
| /// .expect("bind failed"); | ||
| /// assert!(server.local_addr().is_some()); | ||
| /// ``` | ||
| /// | ||
| /// # Errors | ||
| /// Returns a [`ServerError`] if configuring the listener fails. | ||
| pub fn bind_listener( | ||
| self, | ||
| std: StdTcpListener, | ||
| ) -> Result<WireframeServer<F, T, Bound>, ServerError> { | ||
| std.set_nonblocking(true).map_err(ServerError::Bind)?; | ||
| let tokio = TcpListener::from_std(std).map_err(ServerError::Bind)?; | ||
| Ok(WireframeServer { | ||
| factory: self.factory, | ||
| workers: self.workers, | ||
| on_preamble_success: self.on_preamble_success, | ||
| on_preamble_failure: self.on_preamble_failure, | ||
| ready_tx: self.ready_tx, | ||
| state: Bound { | ||
| listener: Arc::new(tokio), | ||
| }, | ||
| _preamble: PhantomData, | ||
| }) | ||
| } | ||
|
leynos marked this conversation as resolved.
|
||
| } | ||
|
|
||
| impl<F, T> WireframeServer<F, T, Bound> | ||
| where | ||
| F: Fn() -> WireframeApp + Send + Sync + Clone + 'static, | ||
| T: Preamble, | ||
| { | ||
| /// Returns the bound address, or `None` if retrieving it fails. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use std::net::SocketAddr; | ||
| /// | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// let addr: SocketAddr = "127.0.0.1:0".parse().unwrap(); | ||
| /// let server = WireframeServer::new(|| WireframeApp::default()) | ||
| /// .bind(addr) | ||
| /// .expect("bind failed"); | ||
| /// assert!(server.local_addr().is_some()); | ||
| /// ``` | ||
| #[must_use] | ||
| pub fn local_addr(&self) -> Option<SocketAddr> { self.state.listener.local_addr().ok() } | ||
|
|
||
| /// Rebind to a fresh address. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use std::net::{Ipv4Addr, SocketAddr}; | ||
| /// | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 0)); | ||
| /// let server = WireframeServer::new(|| WireframeApp::default()) | ||
| /// .bind(addr) | ||
| /// .expect("bind failed"); | ||
| /// let addr2 = SocketAddr::from((Ipv4Addr::LOCALHOST, 0)); | ||
| /// let server = server.bind(addr2).expect("rebind failed"); | ||
| /// assert!(server.local_addr().is_some()); | ||
| /// ``` | ||
| /// | ||
| /// # Errors | ||
| /// Returns a [`ServerError`] if binding or configuring the listener fails. | ||
| pub fn bind(self, addr: SocketAddr) -> Result<Self, ServerError> { | ||
| let std = StdTcpListener::bind(addr).map_err(ServerError::Bind)?; | ||
| self.bind_listener(std) | ||
| } | ||
|
|
||
| /// Rebind using an existing `StdTcpListener`. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// use std::net::{Ipv4Addr, SocketAddr, TcpListener as StdTcpListener}; | ||
| /// | ||
| /// use wireframe::{app::WireframeApp, server::WireframeServer}; | ||
| /// | ||
| /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 0)); | ||
| /// let server = WireframeServer::new(|| WireframeApp::default()) | ||
| /// .bind(addr) | ||
| /// .expect("bind failed"); | ||
| /// let std = StdTcpListener::bind(SocketAddr::from((Ipv4Addr::LOCALHOST, 0))).unwrap(); | ||
| /// let server = server.bind_listener(std).expect("rebind failed"); | ||
| /// assert!(server.local_addr().is_some()); | ||
| /// ``` | ||
| /// | ||
| /// # Errors | ||
| /// Returns a [`ServerError`] if configuring the listener fails. | ||
| pub fn bind_listener(self, std: StdTcpListener) -> Result<Self, ServerError> { | ||
| std.set_nonblocking(true).map_err(ServerError::Bind)?; | ||
| let tokio = TcpListener::from_std(std).map_err(ServerError::Bind)?; | ||
| Ok(WireframeServer { | ||
| factory: self.factory, | ||
| workers: self.workers, | ||
| on_preamble_success: self.on_preamble_success, | ||
| on_preamble_failure: self.on_preamble_failure, | ||
| ready_tx: self.ready_tx, | ||
| state: Bound { | ||
| listener: Arc::new(tokio), | ||
| }, | ||
| _preamble: PhantomData, | ||
| }) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.