From 64dd4811400e15219726c8acc60b3ec9e0305848 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 9 Mar 2026 23:54:10 +0000 Subject: [PATCH] Eliminate remaining conduit unwrap() et al. Signed-off-by: Jason Volk --- Cargo.toml | 2 +- clippy.toml | 2 ++ src/admin/debug/commands.rs | 5 +++-- src/api/client/register.rs | 10 ++++------ src/api/client/voip.rs | 9 ++++----- src/core/config/mod.rs | 4 ++-- src/database/benches/ser.rs | 1 + src/main/benches/main.rs | 1 + src/router/layers.rs | 3 ++- src/router/serve/tls.rs | 19 ++++++++++++++++--- src/service/appservice/request.rs | 9 +++++++-- src/service/benches/state_res.rs | 1 + src/service/rooms/retention/mod.rs | 20 ++++++-------------- src/service/rooms/timeline/redact.rs | 5 ++--- src/service/users/keys.rs | 23 ++++++++++++----------- 15 files changed, 64 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index abd727dc..3cec668f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -984,7 +984,7 @@ unnecessary_safety_doc = "warn" unnecessary_self_imports = "warn" unneeded_field_pattern = "warn" unseparated_literal_suffix = "warn" -#unwrap_used = "warn" # TODO +unwrap_used = "warn" verbose_file_reads = "warn" ################### diff --git a/clippy.toml b/clippy.toml index eaafff4b..74a14dff 100644 --- a/clippy.toml +++ b/clippy.toml @@ -7,6 +7,8 @@ excessive-nesting-threshold = 8 type-complexity-threshold = 250 # reduce me to ~200 cognitive-complexity-threshold = 100 # TODO reduce me ALARA +allow-unwrap-in-tests = true + #disallowed-macros = [ # { path = "log::error", reason = "use tuwunel_core::error" }, # { path = "log::warn", reason = "use tuwunel_core::warn" }, diff --git a/src/admin/debug/commands.rs b/src/admin/debug/commands.rs index 21b7f82c..0d5b08af 100644 --- a/src/admin/debug/commands.rs +++ b/src/admin/debug/commands.rs @@ -25,6 +25,7 @@ use tuwunel_core::{ tokio_metrics::TaskMonitor, trace, utils, utils::{ + math::Expected, stream::{IterStream, ReadyExt}, string::EMPTY, time::now_secs, @@ -377,7 +378,7 @@ pub(super) async fn sign_json(&self) -> Result { return Err!("Expected code block in command body. Add --help for details."); } - let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n"); + let string = self.body[1..self.body.len().expected_sub(1)].join("\n"); let mut value = serde_json::from_str(&string).map_err(|e| err!("Invalid json: {e}"))?; self.services.server_keys.sign_json(&mut value)?; @@ -395,7 +396,7 @@ pub(super) async fn verify_json(&self) -> Result { return Err!("Expected code block in command body. Add --help for details."); } - let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n"); + let string = self.body[1..self.body.len().expected_sub(1)].join("\n"); let value = serde_json::from_str::(&string) .map_err(|e| err!("Invalid json: {e}"))?; diff --git a/src/api/client/register.rs b/src/api/client/register.rs index 4f169320..8e57e0e9 100644 --- a/src/api/client/register.rs +++ b/src/api/client/register.rs @@ -233,8 +233,8 @@ pub(crate) async fn register_route( let proposed_user_id = UserId::parse_with_server_name( utils::random_string(RANDOM_USER_ID_LENGTH).to_lowercase(), services.globals.server_name(), - ) - .unwrap(); + )?; + if !services.users.exists(&proposed_user_id).await { break proposed_user_id; } @@ -295,8 +295,7 @@ pub(crate) async fn register_route( let (worked, uiaainfo) = services .uiaa .try_auth( - &UserId::parse_with_server_name("", services.globals.server_name()) - .unwrap(), + &UserId::parse_with_server_name("", services.globals.server_name())?, "".into(), auth, &uiaainfo, @@ -311,8 +310,7 @@ pub(crate) async fn register_route( | Some(ref json) => { uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); services.uiaa.create( - &UserId::parse_with_server_name("", services.globals.server_name()) - .unwrap(), + &UserId::parse_with_server_name("", services.globals.server_name())?, "".into(), &uiaainfo, json, diff --git a/src/api/client/voip.rs b/src/api/client/voip.rs index d0c441fe..bc7dd886 100644 --- a/src/api/client/voip.rs +++ b/src/api/client/voip.rs @@ -35,20 +35,19 @@ pub(crate) async fn turn_server_route( ) .expect("time is valid"); - let user = body.sender_user.unwrap_or_else(|| { + let random_user_id = || { UserId::parse_with_server_name( utils::random_string(RANDOM_USER_ID_LENGTH).to_lowercase(), &services.server.name, ) - .unwrap() - }); + }; + let user = body.sender_user.map_or_else(random_user_id, Ok)?; let username: String = format!("{}:{}", expiry.get(), user); - let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes()) .expect("HMAC can take key of any size"); - mac.update(username.as_bytes()); + mac.update(username.as_bytes()); let password: String = general_purpose::STANDARD.encode(mac.finalize().into_bytes()); (username, password) diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index effca79a..052bf544 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -3297,7 +3297,7 @@ fn default_jaeger_filter() -> String { fn default_tracing_flame_output_path() -> String { "./tracing.folded".to_owned() } fn default_trusted_servers() -> Vec { - vec![OwnedServerName::try_from("matrix.org").unwrap()] + vec![OwnedServerName::try_from("matrix.org").expect("valid ServerName")] } /// do debug logging by default for debug builds @@ -3499,7 +3499,7 @@ fn default_client_sync_timeout_max() -> u64 { 90000 } fn default_access_token_ttl() -> u64 { 604_800 } fn default_deprioritize_joins_through_servers() -> RegexSet { - RegexSet::new([r"matrix\.org"]).unwrap() + RegexSet::new([r"matrix\.org"]).expect("valid set of regular expressions") } fn default_one_time_key_limit() -> usize { 256 } diff --git a/src/database/benches/ser.rs b/src/database/benches/ser.rs index 996c8504..1095ee94 100644 --- a/src/database/benches/ser.rs +++ b/src/database/benches/ser.rs @@ -1,3 +1,4 @@ +#![cfg(test)] #![allow(unused_features)] // 1.96.0-nightly 2026-03-07 bug use criterion::{Criterion, criterion_group, criterion_main}; diff --git a/src/main/benches/main.rs b/src/main/benches/main.rs index 4e6439a8..001a0f24 100644 --- a/src/main/benches/main.rs +++ b/src/main/benches/main.rs @@ -1,3 +1,4 @@ +#![cfg(test)] #![allow(unused_features)] // 1.96.0-nightly 2026-03-07 bug use criterion::{Criterion, criterion_group, criterion_main}; diff --git a/src/router/layers.rs b/src/router/layers.rs index 17fa393f..75ead23c 100644 --- a/src/router/layers.rs +++ b/src/router/layers.rs @@ -159,7 +159,8 @@ fn cors_layer(server: &Server) -> CorsLayer { header::AUTHORIZATION, header::CONTENT_TYPE, header::ORIGIN, - HeaderName::from_lowercase(b"x-requested-with").unwrap(), + HeaderName::from_lowercase(b"x-requested-with") + .expect("valid HTTP HeaderName from lowercase."), ]; let allow_origin_list = server diff --git a/src/router/serve/tls.rs b/src/router/serve/tls.rs index 09ecce31..f57bbc00 100644 --- a/src/router/serve/tls.rs +++ b/src/router/serve/tls.rs @@ -14,14 +14,26 @@ pub(super) async fn serve( addrs: &[SocketAddr], ) -> Result { let tls = &server.config.tls; - let certs = tls.certs.as_ref().unwrap(); - let key = tls.key.as_ref().unwrap(); + + let certs = tls + .certs + .as_ref() + .ok_or_else(|| err!(Config("tls.certs", "Invalid or missing TLS certificates")))?; + + let key = tls + .key + .as_ref() + .ok_or_else(|| err!(Config("tls.key", "Invalid or missingTLS key")))?; info!( "Note: It is strongly recommended that you use a reverse proxy instead of running \ tuwunel directly with TLS." ); - debug!("Using direct TLS. Certificate path {certs} and certificate private key path {key}",); + + debug!( + "Using direct TLS. Certificate path {certs:?} and certificate private key path {key:?}" + ); + let conf = RustlsConfig::from_pem_file(certs, key) .await .map_err(|e| err!(Config("tls", "Failed to load certificates or key: {e}")))?; @@ -29,6 +41,7 @@ pub(super) async fn serve( let app = app .clone() .into_make_service_with_connect_info::(); + if tls.dual_protocol { for addr in addrs { join_set.spawn_on( diff --git a/src/service/appservice/request.rs b/src/service/appservice/request.rs index 37f1ff8c..978cff09 100644 --- a/src/service/appservice/request.rs +++ b/src/service/appservice/request.rs @@ -52,13 +52,18 @@ where .map(BytesMut::freeze); let mut parts = http_request.uri().clone().into_parts(); - let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); + let old_path_and_query = parts + .path_and_query + .expect("valid request uri path and query") + .as_str() + .to_owned(); + let symbol = if old_path_and_query.contains('?') { "&" } else { "?" }; parts.path_and_query = Some( (old_path_and_query + symbol + "access_token=" + hs_token) .parse() - .unwrap(), + .expect("valid path and query"), ); *http_request.uri_mut() = parts .try_into() diff --git a/src/service/benches/state_res.rs b/src/service/benches/state_res.rs index de9f7975..ce843766 100644 --- a/src/service/benches/state_res.rs +++ b/src/service/benches/state_res.rs @@ -1,3 +1,4 @@ +#![cfg(test)] #![allow(unused_features)] // 1.96.0-nightly 2026-03-07 bug use std::{ diff --git a/src/service/rooms/retention/mod.rs b/src/service/rooms/retention/mod.rs index bd0283bb..4524bada 100644 --- a/src/service/rooms/retention/mod.rs +++ b/src/service/rooms/retention/mod.rs @@ -1,12 +1,11 @@ -use std::{ - sync::Arc, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; +use std::{sync::Arc, time::Duration}; use async_trait::async_trait; use ruma::{CanonicalJsonObject, EventId}; use tuwunel_core::{ - Result, debug_info, expected, implement, matrix::pdu::PduEvent, utils::TryReadyExt, + Result, debug_info, expected, implement, + matrix::pdu::PduEvent, + utils::{TryReadyExt, time::now}, }; use tuwunel_database::{Deserialized, Json, Map}; @@ -35,11 +34,7 @@ impl crate::Service for Service { if retention_seconds != 0 { debug_info!("Cleaning up retained events"); - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(); - + let now = now().as_secs(); let count = self .timeredacted_eventid .keys::<(u64, &EventId)>() @@ -104,10 +99,7 @@ pub async fn save_original_pdu( return; } - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(); + let now = now().as_secs(); self.eventid_originalpdu .raw_put(event_id, Json(pdu)); diff --git a/src/service/rooms/timeline/redact.rs b/src/service/rooms/timeline/redact.rs index 16c6fde4..cec915ea 100644 --- a/src/service/rooms/timeline/redact.rs +++ b/src/service/rooms/timeline/redact.rs @@ -36,8 +36,7 @@ pub async fn redact_pdu( let body = pdu["content"] .as_object() - .unwrap() - .get("body") + .and_then(|obj| obj.get("body")) .and_then(|body| body.as_str()); if let Some(body) = body { @@ -46,7 +45,7 @@ pub async fn redact_pdu( .deindex_pdu(shortroomid, &pdu_id, body); } - let room_id = RoomId::parse(pdu["room_id"].as_str().unwrap()).unwrap(); + let room_id: &RoomId = pdu.get("room_id").try_into()?; let room_version_id = self .services diff --git a/src/service/users/keys.rs b/src/service/users/keys.rs index a2f1f017..5f224d38 100644 --- a/src/service/users/keys.rs +++ b/src/service/users/keys.rs @@ -10,7 +10,11 @@ use ruma::{ }; use tuwunel_core::{ Err, Error, Result, debug_error, err, implement, - utils::{ReadyExt, stream::TryIgnore, string::Unquoted}, + utils::{ + ReadyExt, + stream::{TryExpect, TryIgnore, TryReadyExt}, + string::Unquoted, + }, }; use tuwunel_database::{Deserialized, Ignore, Json}; @@ -117,26 +121,23 @@ pub async fn take_one_time_key( .db .onetimekeyid_onetimekeys .raw_stream_prefix(&prefix) - .ignore_err() - .map(|(key, val)| { + .ready_and_then(|(key, val)| { self.db.onetimekeyid_onetimekeys.remove(key); let key = key .rsplit(|&b| b == 0xFF) .next() - .ok_or_else(|| err!(Database("OneTimeKeyId in db is invalid."))) - .unwrap(); + .ok_or_else(|| err!(Database("OneTimeKeyId in db is invalid.")))?; let key = serde_json::from_slice(key) - .map_err(|e| err!(Database("OneTimeKeyId in db is invalid. {e}"))) - .unwrap(); + .map_err(|e| err!(Database("OneTimeKeyId in db is invalid. {e}")))?; let val = serde_json::from_slice(val) - .map_err(|e| err!(Database("OneTimeKeys in db are invalid. {e}"))) - .unwrap(); + .map_err(|e| err!(Database("OneTimeKeys in db are invalid. {e}")))?; - (key, val) - }); + Ok((key, val)) + }) + .expect_ok(); pin_mut!(one_time_keys); one_time_keys