From 80526fbc683d5fe82c2d3985ea0ef32ea196ec26 Mon Sep 17 00:00:00 2001
From: Sebastian Imlay <sebastian.imlay@gmail.com>
Date: Mon, 29 Jul 2024 14:45:20 -0400
Subject: [PATCH] Initial barebones for browser wasm support

---
 Cargo.toml          |  8 ++++++--
 src/connect_wasm.rs | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/lib.rs          | 18 +++++++++++++-----
 3 files changed, 61 insertions(+), 7 deletions(-)
 create mode 100644 src/connect_wasm.rs

diff --git a/Cargo.toml b/Cargo.toml
index dec1fa2c..d3170d83 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,11 +27,15 @@ rustls-tls-webpki-roots = ["__rustls-tls", "webpki-roots"]
 __rustls-tls = ["rustls", "rustls-pki-types", "tokio-rustls", "stream", "tungstenite/__rustls-tls", "handshake"]
 stream = []
 url = ["tungstenite/url"]
+js-connect = ["stream", "handshake", "ws_stream_wasm", "async_io_stream", "getrandom/js" ]
 
 [dependencies]
 log = "0.4.17"
 futures-util = { version = "0.3.28", default-features = false, features = ["sink", "std"] }
-tokio = { version = "1.0.0", default-features = false, features = ["io-util"] }
+tokio = { version = "1.39.0", default-features = false }
+ws_stream_wasm = { version = "0.7.4", optional = true }
+async_io_stream = { version = "0.3.3", features = ["tokio_io"], optional = true }
+getrandom = { version = "0.2", optional = true }
 
 [dependencies.tungstenite]
 version = "0.23.0"
@@ -68,7 +72,7 @@ default-features = false
 optional = true
 version = "0.26.0"
 
-[dev-dependencies]
+[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
 futures-channel = "0.3.28"
 hyper = { version = "1.0", default-features = false, features = ["http1", "server"] }
 hyper-util = { version = "0.1", features = ["tokio"] }
diff --git a/src/connect_wasm.rs b/src/connect_wasm.rs
new file mode 100644
index 00000000..f3d130bd
--- /dev/null
+++ b/src/connect_wasm.rs
@@ -0,0 +1,42 @@
+use crate::{stream::MaybeTlsStream, Connector, WebSocketStream};
+
+use tungstenite::{
+    error::{Error, UrlError},
+    handshake::client::{Request, Response},
+    protocol::WebSocketConfig,
+    //client::IntoClientRequest,
+};
+//use web_sys::WebSocket;
+use ws_stream_wasm::WsStreamIo;
+use async_io_stream::IoStream;
+
+
+
+pub async fn connect(
+    request: Request,
+    config: Option<WebSocketConfig>,
+    disable_nagle: bool,
+    //connector: Option<Connector>,
+) -> Result<(WebSocketStream<MaybeTlsStream<IoStream<WsStreamIo, Vec<u8>>>>, Response), Error> {
+    //let domain = domain(&request)?;
+    let domain = request.uri().host().unwrap();
+    let port = request
+        .uri()
+        .port_u16()
+        .or_else(|| match request.uri().scheme_str() {
+            Some("wss") => Some(443),
+            Some("ws") => Some(80),
+            _ => None,
+        })
+        .ok_or(Error::Url(UrlError::UnsupportedUrlScheme))?;
+
+    let addr = format!("{domain}:{port}");
+    //let socket = TcpStream::connect(addr).await.map_err(Error::Io)?;
+
+    if disable_nagle {
+        //socket.set_nodelay(true)?;
+    }
+    todo!();
+
+    //crate::tls::client_async_tls_with_config(request, socket, config, connector).await
+}
diff --git a/src/lib.rs b/src/lib.rs
index 734fc648..ef6b5143 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,17 +8,22 @@
 //! Each WebSocket stream implements the required `Stream` and `Sink` traits,
 //! so the socket is just a stream of messages coming in and going out.
 
-#![deny(missing_docs, unused_must_use, unused_mut, unused_imports, unused_import_braces)]
+//#![deny(missing_docs, unused_must_use, unused_mut, unused_imports, unused_import_braces)]
 
 pub use tungstenite;
 
 mod compat;
-#[cfg(feature = "connect")]
+#[cfg(all(feature = "connect", not(target_family = "wasm")))]
 mod connect;
+
+#[cfg(all(feature = "js-connect", target_family = "wasm"))]
+mod connect_wasm;
+
+#[cfg(feature = "handshake")]
 mod handshake;
 #[cfg(feature = "stream")]
 mod stream;
-#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
+#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect", feature = "js-connect"))]
 mod tls;
 
 use std::io::{Read, Write};
@@ -49,14 +54,17 @@ use tungstenite::{
     protocol::{Message, Role, WebSocket, WebSocketConfig},
 };
 
-#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
+#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect", feature = "js-connect"))]
 pub use tls::Connector;
 #[cfg(any(feature = "native-tls", feature = "__rustls-tls"))]
 pub use tls::{client_async_tls, client_async_tls_with_config};
 
-#[cfg(feature = "connect")]
+#[cfg(all(feature = "connect", not(target_family = "wasm")))]
 pub use connect::{connect_async, connect_async_with_config};
 
+#[cfg(all(feature = "js-connect", target_family = "wasm"))]
+pub use connect_wasm::connect;
+
 #[cfg(all(any(feature = "native-tls", feature = "__rustls-tls"), feature = "connect"))]
 pub use connect::connect_async_tls_with_config;