///|
/// Native transport (async/websocket)
///|
/// JS WebSocket state (native)
pub struct JsWebSocketState {
url : String
conn : Ref[@websocket.Conn?]
closed : Ref[Bool]
}
///|
/// Create JS WebSocket state
fn JsWebSocketState::new(url : String) -> JsWebSocketState {
{ url, conn: { val: None }, closed: { val: false } }
}
///|
/// Create WebSocket transport
pub fn Transport::websocket(url : String) -> Transport {
JsWebSocket(JsWebSocketState::new(url))
}
///|
/// Ensure native connection
async fn ensure_native_connected(
state : JsWebSocketState,
) -> Result[@websocket.Conn, TransportError] {
if state.closed.val {
return Err(Closed)
}
match state.conn.val {
Some(conn) => Ok(conn)
None => {
let conn = @websocket.Conn::connect(state.url) catch {
err => return Err(NetworkError(message=err.to_string()))
}
state.conn.val = Some(conn)
Ok(conn)
}
}
}
///|
/// Connect transport
pub async fn Transport::connect(
self : Transport,
) -> Result[Unit, TransportError] {
match self {
JsWebSocket(state) =>
match ensure_native_connected(state) {
Ok(_) => Ok(())
Err(e) => Err(e)
}
ChromePipe(_) => Err(NotSupported(message="ChromePipe not supported on native"))
Custom(custom) => (custom.connect)()
Unsupported(err) => Err(err)
}
}
///|
/// Send message
pub async fn Transport::send(
self : Transport,
message : String,
) -> Result[Unit, TransportError] {
match self {
JsWebSocket(state) =>
match ensure_native_connected(state) {
Ok(conn) =>
try {
conn.send_text(message)
Ok(())
} catch {
err => Err(NetworkError(message=err.to_string()))
}
Err(e) => Err(e)
}
ChromePipe(_) => Err(NotSupported(message="ChromePipe not supported on native"))
Custom(custom) => (custom.send)(message)
Unsupported(err) => Err(err)
}
}
///|
/// Receive message
pub async fn Transport::recv(
self : Transport,
) -> Result[String, TransportError] {
match self {
JsWebSocket(state) =>
match ensure_native_connected(state) {
Ok(conn) =>
try {
let msg = conn.recv()
let text = msg.read_all().text()
Ok(text)
} catch {
err => Err(NetworkError(message=err.to_string()))
}
Err(e) => Err(e)
}
ChromePipe(_) => Err(NotSupported(message="ChromePipe not supported on native"))
Custom(custom) => (custom.recv)()
Unsupported(err) => Err(err)
}
}
///|
/// Close transport
pub fn Transport::close(self : Transport) -> Result[Unit, TransportError] {
match self {
JsWebSocket(state) => {
match state.conn.val {
Some(conn) => conn.close()
None => ()
}
state.closed.val = true
Ok(())
}
ChromePipe(state) => {
state.closed.val = true
Ok(())
}
Custom(custom) => (custom.close)()
Unsupported(err) => Err(err)
}
}