Skip to content

Commit

Permalink
feat: add support for wasm
Browse files Browse the repository at this point in the history
Adds support for compiling to WASM environments that provide JS via
wasm-bindgen. Because there's no standardized socket API the caller must
provide a connection that implements AsyncRead/AsyncWrite to
connect_raw.
  • Loading branch information
zebp committed Jun 3, 2023
1 parent 762f67f commit e69400a
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"codegen",
"postgres",
Expand Down
3 changes: 3 additions & 0 deletions postgres-protocol/Cargo.toml
Expand Up @@ -19,3 +19,6 @@ memchr = "2.0"
rand = "0.8"
sha2 = "0.10"
stringprep = "0.1"

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.9", features = ["js"] }
8 changes: 8 additions & 0 deletions tokio-postgres/Cargo.toml
Expand Up @@ -55,6 +55,14 @@ pin-project-lite = "0.2"
phf = "0.11"
postgres-protocol = { version = "0.6.5", path = "../postgres-protocol" }
postgres-types = { version = "0.2.4", path = "../postgres-types" }
tokio = { version = "1.27", default-features = false }
tokio-util = { version = "0.7", default-features = false }

[target.'cfg(target_arch = "wasm32")'.dependencies]
tokio = { version = "1.27", features = ["io-util"], default-features = false }
tokio-util = { version = "0.7", features = ["codec"], default-features = false }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
socket2 = { version = "0.5", features = ["all"] }
tokio = { version = "1.27", features = ["io-util"] }
tokio-util = { version = "0.7", features = ["codec"] }
Expand Down
42 changes: 31 additions & 11 deletions tokio-postgres/src/config.rs
Expand Up @@ -3,6 +3,7 @@
#[cfg(feature = "runtime")]
use crate::connect::connect;
use crate::connect_raw::connect_raw;
#[cfg(not(target_arch = "wasm32"))]
use crate::keepalive::KeepaliveConfig;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
Expand Down Expand Up @@ -165,6 +166,7 @@ pub struct Config {
pub(crate) connect_timeout: Option<Duration>,
pub(crate) tcp_user_timeout: Option<Duration>,
pub(crate) keepalives: bool,
#[cfg(not(target_arch = "wasm32"))]
pub(crate) keepalive_config: KeepaliveConfig,
pub(crate) target_session_attrs: TargetSessionAttrs,
pub(crate) channel_binding: ChannelBinding,
Expand All @@ -179,11 +181,6 @@ impl Default for Config {
impl Config {
/// Creates a new configuration.
pub fn new() -> Config {
let keepalive_config = KeepaliveConfig {
idle: Duration::from_secs(2 * 60 * 60),
interval: None,
retries: None,
};
Config {
user: None,
password: None,
Expand All @@ -196,7 +193,12 @@ impl Config {
connect_timeout: None,
tcp_user_timeout: None,
keepalives: true,
keepalive_config,
#[cfg(not(target_arch = "wasm32"))]
keepalive_config: KeepaliveConfig {
idle: Duration::from_secs(2 * 60 * 60),
interval: None,
retries: None,
},
target_session_attrs: TargetSessionAttrs::Any,
channel_binding: ChannelBinding::Prefer,
}
Expand Down Expand Up @@ -377,13 +379,15 @@ impl Config {
/// Sets the amount of idle time before a keepalive packet is sent on the connection.
///
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled. Defaults to 2 hours.
#[cfg(not(target_arch = "wasm32"))]
pub fn keepalives_idle(&mut self, keepalives_idle: Duration) -> &mut Config {
self.keepalive_config.idle = keepalives_idle;
self
}

/// Gets the configured amount of idle time before a keepalive packet will
/// be sent on the connection.
#[cfg(not(target_arch = "wasm32"))]
pub fn get_keepalives_idle(&self) -> Duration {
self.keepalive_config.idle
}
Expand All @@ -392,25 +396,29 @@ impl Config {
/// On Windows, this sets the value of the tcp_keepalive struct’s keepaliveinterval field.
///
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
#[cfg(not(target_arch = "wasm32"))]
pub fn keepalives_interval(&mut self, keepalives_interval: Duration) -> &mut Config {
self.keepalive_config.interval = Some(keepalives_interval);
self
}

/// Gets the time interval between TCP keepalive probes.
#[cfg(not(target_arch = "wasm32"))]
pub fn get_keepalives_interval(&self) -> Option<Duration> {
self.keepalive_config.interval
}

/// Sets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
///
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
#[cfg(not(target_arch = "wasm32"))]
pub fn keepalives_retries(&mut self, keepalives_retries: u32) -> &mut Config {
self.keepalive_config.retries = Some(keepalives_retries);
self
}

/// Gets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
#[cfg(not(target_arch = "wasm32"))]
pub fn get_keepalives_retries(&self) -> Option<u32> {
self.keepalive_config.retries
}
Expand Down Expand Up @@ -503,12 +511,14 @@ impl Config {
self.tcp_user_timeout(Duration::from_secs(timeout as u64));
}
}
#[cfg(not(target_arch = "wasm32"))]
"keepalives" => {
let keepalives = value
.parse::<u64>()
.map_err(|_| Error::config_parse(Box::new(InvalidValue("keepalives"))))?;
self.keepalives(keepalives != 0);
}
#[cfg(not(target_arch = "wasm32"))]
"keepalives_idle" => {
let keepalives_idle = value
.parse::<i64>()
Expand All @@ -517,6 +527,7 @@ impl Config {
self.keepalives_idle(Duration::from_secs(keepalives_idle as u64));
}
}
#[cfg(not(target_arch = "wasm32"))]
"keepalives_interval" => {
let keepalives_interval = value.parse::<i64>().map_err(|_| {
Error::config_parse(Box::new(InvalidValue("keepalives_interval")))
Expand All @@ -525,6 +536,7 @@ impl Config {
self.keepalives_interval(Duration::from_secs(keepalives_interval as u64));
}
}
#[cfg(not(target_arch = "wasm32"))]
"keepalives_retries" => {
let keepalives_retries = value.parse::<u32>().map_err(|_| {
Error::config_parse(Box::new(InvalidValue("keepalives_retries")))
Expand Down Expand Up @@ -614,7 +626,8 @@ impl fmt::Debug for Config {
}
}

f.debug_struct("Config")
let mut config_dbg = &mut f.debug_struct("Config");
config_dbg = config_dbg
.field("user", &self.user)
.field("password", &self.password.as_ref().map(|_| Redaction {}))
.field("dbname", &self.dbname)
Expand All @@ -625,10 +638,17 @@ impl fmt::Debug for Config {
.field("port", &self.port)
.field("connect_timeout", &self.connect_timeout)
.field("tcp_user_timeout", &self.tcp_user_timeout)
.field("keepalives", &self.keepalives)
.field("keepalives_idle", &self.keepalive_config.idle)
.field("keepalives_interval", &self.keepalive_config.interval)
.field("keepalives_retries", &self.keepalive_config.retries)
.field("keepalives", &self.keepalives);

#[cfg(not(target_arch = "wasm32"))]
{
config_dbg = config_dbg
.field("keepalives_idle", &self.keepalive_config.idle)
.field("keepalives_interval", &self.keepalive_config.interval)
.field("keepalives_retries", &self.keepalive_config.retries);
}

config_dbg
.field("target_session_attrs", &self.target_session_attrs)
.field("channel_binding", &self.channel_binding)
.finish()
Expand Down
1 change: 1 addition & 0 deletions tokio-postgres/src/lib.rs
Expand Up @@ -163,6 +163,7 @@ mod copy_in;
mod copy_out;
pub mod error;
mod generic_client;
#[cfg(not(target_arch = "wasm32"))]
mod keepalive;
mod maybe_tls_stream;
mod portal;
Expand Down

0 comments on commit e69400a

Please sign in to comment.