diff --git a/src/asynch/clients/websocket/_std.rs b/src/asynch/clients/websocket/_std.rs index 42b31596..cbf261ea 100644 --- a/src/asynch/clients/websocket/_std.rs +++ b/src/asynch/clients/websocket/_std.rs @@ -1,5 +1,5 @@ use super::exceptions::XRPLWebSocketException; -use super::{WebSocketClosed, WebSocketOpen}; +use super::{ConnectionStatus, WebSocketClosed, WebSocketOpen}; use crate::asynch::clients::client::XRPLClient; use crate::asynch::clients::exceptions::{XRPLClientException, XRPLClientResult}; use crate::asynch::clients::websocket::websocket_base::{MessageHandler, WebsocketBase}; @@ -164,9 +164,10 @@ where impl AsyncWebSocketClient where M: RawMutex, + Status: ConnectionStatus, { pub fn is_open(&self) -> bool { - core::any::type_name::() == core::any::type_name::() + Status::IS_OPEN } } diff --git a/src/asynch/clients/websocket/mod.rs b/src/asynch/clients/websocket/mod.rs index b8a6013e..6baf2010 100644 --- a/src/asynch/clients/websocket/mod.rs +++ b/src/asynch/clients/websocket/mod.rs @@ -30,6 +30,30 @@ use super::exceptions::XRPLClientResult; pub struct WebSocketOpen; pub struct WebSocketClosed; +mod sealed { + pub trait Sealed {} + impl Sealed for super::WebSocketOpen {} + impl Sealed for super::WebSocketClosed {} +} + +/// Type-state marker describing whether a [`websocket`](self) client is open. +/// +/// Implemented only for [`WebSocketOpen`] and [`WebSocketClosed`], this lets +/// `is_open()` resolve from the type state at compile time instead of relying +/// on the unstable [`core::any::type_name`] string representation. +pub trait ConnectionStatus: sealed::Sealed { + /// Whether this state represents an open connection. + const IS_OPEN: bool; +} + +impl ConnectionStatus for WebSocketOpen { + const IS_OPEN: bool = true; +} + +impl ConnectionStatus for WebSocketClosed { + const IS_OPEN: bool = false; +} + #[allow(async_fn_in_trait)] pub trait XRPLAsyncWebsocketIO { async fn xrpl_send(&mut self, message: XRPLRequest<'_>) -> XRPLClientResult<()>; @@ -100,3 +124,19 @@ where } } } + +#[cfg(test)] +mod tests { + use super::{ConnectionStatus, WebSocketClosed, WebSocketOpen}; + + /// Mirrors how `is_open()` reads the constant through the type state. + fn is_open() -> bool { + S::IS_OPEN + } + + #[test] + fn connection_status_is_open_resolves_from_type_state() { + assert!(is_open::()); + assert!(!is_open::()); + } +}