use crate::{
action::{action_impl, ParseConnectionString},
error::{Error, Result},
srv::OriginalSrvInfo,
};
use super::{ClientOptions, ConnectionString, ResolvedHostInfo, Tls};
#[action_impl]
impl Action for ParseConnectionString {
type Future = ParseFuture;
async fn execute(self) -> Result<ClientOptions> {
let mut conn_str = self.conn_str?;
#[allow(deprecated)]
if conn_str.socket_timeout.is_some() {
return Err(Error::invalid_argument(
"the Rust driver does not support socketTimeoutMS",
));
}
let auth_source_present = conn_str
.credential
.as_ref()
.and_then(|cred| cred.source.as_ref())
.is_some();
let host_info = std::mem::take(&mut conn_str.host_info);
let mut options = ClientOptions::from_connection_string(conn_str);
#[cfg(feature = "dns-resolver")]
{
options.resolver_config.clone_from(&self.resolver_config);
}
let resolved = host_info
.resolve(self.resolver_config, options.srv_service_name.clone())
.await?;
options.hosts = match resolved {
ResolvedHostInfo::HostIdentifiers(hosts) => hosts,
ResolvedHostInfo::DnsRecord {
hostname,
mut config,
} => {
options.original_srv_info = OriginalSrvInfo {
hostname,
min_ttl: config.min_ttl,
}
.into();
if options.tls.is_none() {
options.tls = Some(Tls::Enabled(Default::default()));
}
if !auth_source_present {
if let Some(auth_source) = config.auth_source.take() {
if let Some(ref mut credential) = options.credential {
credential.source = Some(auth_source);
}
}
}
if options.repl_set_name.is_none() {
if let Some(replica_set) = config.replica_set.take() {
options.repl_set_name = Some(replica_set);
}
}
if options.load_balanced.is_none() {
options.load_balanced = config.load_balanced;
}
if let Some(max) = options.srv_max_hosts {
if max > 0 {
if options.repl_set_name.is_some() {
return Err(Error::invalid_argument(
"srvMaxHosts and replicaSet cannot both be present",
));
}
if options.load_balanced == Some(true) {
return Err(Error::invalid_argument(
"srvMaxHosts and loadBalanced=true cannot both be present",
));
}
config.hosts = crate::sdam::choose_n(&config.hosts, max as usize)
.cloned()
.collect();
}
}
config.hosts
}
};
options.validate()?;
Ok(options)
}
}
impl ClientOptions {
fn from_connection_string(conn_str: ConnectionString) -> Self {
let mut credential = conn_str.credential;
let db = &conn_str.default_database;
if let Some(credential) = credential.as_mut() {
if credential.source.is_none() {
credential.source = match &credential.mechanism {
Some(mechanism) => Some(mechanism.default_source(db.as_deref()).into()),
None => {
db.clone().or_else(|| Some("admin".into()))
}
};
}
}
Self {
hosts: vec![],
app_name: conn_str.app_name,
tls: conn_str.tls,
heartbeat_freq: conn_str.heartbeat_frequency,
local_threshold: conn_str.local_threshold,
read_concern: conn_str.read_concern,
selection_criteria: conn_str.read_preference.map(Into::into),
repl_set_name: conn_str.replica_set,
write_concern: conn_str.write_concern,
max_pool_size: conn_str.max_pool_size,
min_pool_size: conn_str.min_pool_size,
max_idle_time: conn_str.max_idle_time,
max_connecting: conn_str.max_connecting,
server_selection_timeout: conn_str.server_selection_timeout,
#[cfg(any(
feature = "zstd-compression",
feature = "zlib-compression",
feature = "snappy-compression"
))]
compressors: conn_str.compressors,
connect_timeout: conn_str.connect_timeout,
retry_reads: conn_str.retry_reads,
retry_writes: conn_str.retry_writes,
server_monitoring_mode: conn_str.server_monitoring_mode,
direct_connection: conn_str.direct_connection,
default_database: conn_str.default_database,
driver_info: None,
credential,
cmap_event_handler: None,
command_event_handler: None,
original_srv_info: None,
#[cfg(test)]
original_uri: Some(conn_str.original_uri),
#[cfg(feature = "dns-resolver")]
resolver_config: None,
server_api: None,
load_balanced: conn_str.load_balanced,
sdam_event_handler: None,
#[cfg(test)]
test_options: None,
#[cfg(feature = "tracing-unstable")]
tracing_max_document_length_bytes: None,
srv_max_hosts: conn_str.srv_max_hosts,
srv_service_name: conn_str.srv_service_name,
#[cfg(feature = "opentelemetry")]
tracing: None,
#[cfg(feature = "socks5-proxy")]
socks5_proxy: conn_str.socks5_proxy,
adaptive_retries: conn_str.adaptive_retries,
max_adaptive_retries: conn_str.max_adaptive_retries,
enable_overload_retargeting: conn_str.enable_overload_retargeting,
}
}
}