refactor: enable clippy::arithmetic_side_effects lint

This commit is contained in:
link2xt
2026-02-14 10:12:15 +00:00
committed by l
parent 5a06d08613
commit 10b93b3943
42 changed files with 104 additions and 0 deletions

View File

@@ -586,6 +586,7 @@ impl Config {
}
#[cfg(not(target_os = "ios"))]
#[expect(clippy::arithmetic_side_effects)]
async fn create_lock_task(dir: PathBuf) -> Result<Option<JoinHandle<anyhow::Result<()>>>> {
let lockfile = dir.join(LOCKFILE_NAME);
let mut lock = fd_lock::RwLock::new(fs::File::create(lockfile).await?);
@@ -752,6 +753,7 @@ impl Config {
}
/// Creates a new account in the account manager directory.
#[expect(clippy::arithmetic_side_effects)]
async fn new_account(&mut self) -> Result<AccountConfig> {
let id = {
let id = self.inner.next_id;
@@ -841,6 +843,7 @@ impl Config {
///
/// Without this workaround removing account may fail on Windows with an error
/// "The process cannot access the file because it is being used by another process. (os error 32)".
#[expect(clippy::arithmetic_side_effects)]
async fn try_many_times<F, Fut, T>(f: F) -> std::result::Result<(), T>
where
F: Fn() -> Fut,

View File

@@ -73,6 +73,7 @@ impl fmt::Display for Aheader {
let keydata = self.public_key.to_base64().chars().enumerate().fold(
String::new(),
|mut res, (i, c)| {
#[expect(clippy::arithmetic_side_effects)]
if i % 78 == 78 - "keydata=".len() {
res.push(' ')
}

View File

@@ -321,6 +321,7 @@ impl<'a> BlobObject<'a> {
/// then the updated user-visible filename will be returned;
/// this may be necessary because the format may be changed to JPG,
/// i.e. "image.png" -> "image.jpg".
#[expect(clippy::arithmetic_side_effects)]
fn check_or_recode_to_size(
&mut self,
context: &Context,

View File

@@ -79,6 +79,7 @@ impl CallInfo {
}
fn remaining_ring_seconds(&self) -> i64 {
#[expect(clippy::arithmetic_side_effects)]
let remaining_seconds = self.msg.timestamp_sent + RINGING_SECONDS - time();
remaining_seconds.clamp(0, RINGING_SECONDS)
}
@@ -175,6 +176,7 @@ impl CallInfo {
}
/// Returns call duration in seconds.
#[expect(clippy::arithmetic_side_effects)]
pub fn duration_seconds(&self) -> i64 {
if let (Some(start), Some(end)) = (
self.msg.param.get_i64(CALL_ACCEPTED_TIMESTAMP),

View File

@@ -941,6 +941,7 @@ SELECT id, rfc724_mid, pre_rfc724_mid, timestamp, ?, 1 FROM msgs WHERE chat_id=?
/// Jaccard similarity coefficient is used to estimate similarity of chat member sets.
///
/// Chat is considered active if something was posted there within the last 42 days.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_similar_chat_ids(self, context: &Context) -> Result<Vec<(ChatId, f64)>> {
// Count number of common members in this and other chats.
let intersection = context
@@ -1145,6 +1146,7 @@ SELECT id, rfc724_mid, pre_rfc724_mid, timestamp, ?, 1 FROM msgs WHERE chat_id=?
/// prefer plaintext emails.
///
/// To get more verbose summary for a contact, including its key fingerprint, use [`Contact::get_encrinfo`].
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_encryption_info(self, context: &Context) -> Result<String> {
let chat = Chat::load_from_db(context, self).await?;
if !chat.is_encrypted(context).await? {
@@ -1730,6 +1732,7 @@ impl Chat {
///
/// If `update_msg_id` is set, that record is reused;
/// if `update_msg_id` is None, a new record is created.
#[expect(clippy::arithmetic_side_effects)]
async fn prepare_msg_raw(
&mut self,
context: &Context,
@@ -2995,6 +2998,7 @@ pub async fn send_text_msg(
}
/// Sends chat members a request to edit the given message's text.
#[expect(clippy::arithmetic_side_effects)]
pub async fn send_edit_request(context: &Context, msg_id: MsgId, new_text: String) -> Result<()> {
let mut original_msg = Message::load_from_db(context, msg_id).await?;
ensure!(
@@ -3100,6 +3104,7 @@ pub async fn get_chat_msgs(context: &Context, chat_id: ChatId) -> Result<Vec<Cha
}
/// Returns messages belonging to the chat according to the given options.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_chat_msgs_ex(
context: &Context,
chat_id: ChatId,
@@ -3978,6 +3983,7 @@ pub(crate) async fn add_contact_to_chat_ex(
/// This function does not check if the avatar is set.
/// If avatar is not set and this function returns `true`,
/// a `Chat-User-Avatar: 0` header should be sent to reset the avatar.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn shall_attach_selfavatar(context: &Context, chat_id: ChatId) -> Result<bool> {
let timestamp_some_days_ago = time() - DC_RESEND_USER_AVATAR_DAYS * 24 * 60 * 60;
let needs_attach = context
@@ -4433,6 +4439,7 @@ pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId)
}
/// Forwards multiple messages to a chat in another context.
#[expect(clippy::arithmetic_side_effects)]
pub async fn forward_msgs_2ctx(
ctx_src: &Context,
msg_ids: &[MsgId],
@@ -4563,6 +4570,7 @@ pub async fn save_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
/// the copy contains a reference to the original message
/// as well as to the original chat in case the original message gets deleted.
/// Returns data needed to add a `SaveMessage` sync item.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn save_copy_in_self_talk(
context: &Context,
src_msg_id: MsgId,
@@ -4741,6 +4749,7 @@ pub(crate) async fn get_chat_id_by_grpid(
///
/// Optional `label` can be provided to ensure that message is added only once.
/// If `important` is true, a notification will be sent.
#[expect(clippy::arithmetic_side_effects)]
pub async fn add_device_msg_with_importance(
context: &Context,
label: Option<&str>,

View File

@@ -7,6 +7,7 @@ use colorutils_rs::{Oklch, Rgb, TransferFunction};
use sha1::{Digest, Sha1};
/// Converts an identifier to Hue angle.
#[expect(clippy::arithmetic_side_effects)]
fn str_to_angle(s: &str) -> f32 {
let bytes = s.as_bytes();
let result = Sha1::digest(bytes);
@@ -19,6 +20,7 @@ fn str_to_angle(s: &str) -> f32 {
///
/// Returns a 24-bit number with 8 least significant bits corresponding to the blue color and 8
/// most significant bits corresponding to the red color.
#[expect(clippy::arithmetic_side_effects)]
fn rgb_to_u32(rgb: Rgb<u8>) -> u32 {
65536 * u32::from(rgb.r) + 256 * u32::from(rgb.g) + u32::from(rgb.b)
}

View File

@@ -673,6 +673,7 @@ impl Contact {
}
/// Returns `true` if this contact was seen recently.
#[expect(clippy::arithmetic_side_effects)]
pub fn was_seen_recently(&self) -> bool {
time() - self.last_seen <= SEEN_RECENTLY_SECONDS
}
@@ -1071,6 +1072,7 @@ VALUES (?, ?, ?, ?, ?, ?)
/// The `addr_book` is a multiline string in the format `Name one\nAddress one\nName two\nAddress two`.
///
/// Returns the number of modified contacts.
#[expect(clippy::arithmetic_side_effects)]
pub async fn add_address_book(context: &Context, addr_book: &str) -> Result<usize> {
let mut modify_cnt = 0;
@@ -1909,6 +1911,7 @@ pub(crate) async fn set_status(
}
/// Updates last seen timestamp of the contact if it is earlier than the given `timestamp`.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn update_last_seen(
context: &Context,
contact_id: ContactId,
@@ -2000,6 +2003,7 @@ pub(crate) async fn mark_contact_id_as_verified(
Ok(())
}
#[expect(clippy::arithmetic_side_effects)]
fn cat_fingerprint(ret: &mut String, name: &str, addr: &str, fingerprint: &str) {
*ret += &format!("\n\n{name} ({addr}):\n{fingerprint}");
}
@@ -2041,6 +2045,7 @@ impl RecentlySeenLoop {
}
}
#[expect(clippy::arithmetic_side_effects)]
async fn run(context: Context, interrupt: Receiver<RecentlySeenInterrupt>) {
type MyHeapElem = (Reverse<i64>, ContactId);

View File

@@ -342,6 +342,7 @@ enum RunningState {
/// actual keys and their values which will be present are not
/// guaranteed. Calling [Context::get_info] also includes information
/// about the context on top of the information here.
#[expect(clippy::arithmetic_side_effects)]
pub fn get_info() -> BTreeMap<&'static str, String> {
let mut res = BTreeMap::new();

View File

@@ -235,6 +235,7 @@ fn str_cb(event_str: &str, dehtml: &mut Dehtml) {
}
}
#[expect(clippy::arithmetic_side_effects)]
fn dehtml_endtag_cb(event: &BytesEnd, dehtml: &mut Dehtml) {
let tag = String::from_utf8_lossy(event.name().as_ref())
.trim()
@@ -280,6 +281,7 @@ fn dehtml_endtag_cb(event: &BytesEnd, dehtml: &mut Dehtml) {
}
}
#[expect(clippy::arithmetic_side_effects)]
fn dehtml_starttag_cb<B: std::io::BufRead>(
event: &BytesStart,
dehtml: &mut Dehtml,
@@ -356,6 +358,7 @@ fn dehtml_starttag_cb<B: std::io::BufRead>(
/// In order to know when a specific tag is closed, we need to count the opening and closing tags.
/// The `counts`s are stored in the `Dehtml` struct.
#[expect(clippy::arithmetic_side_effects)]
fn pop_tag(count: &mut u32) {
if *count > 0 {
*count -= 1;
@@ -364,6 +367,7 @@ fn pop_tag(count: &mut u32) {
/// In order to know when a specific tag is closed, we need to count the opening and closing tags.
/// The `counts`s are stored in the `Dehtml` struct.
#[expect(clippy::arithmetic_side_effects)]
fn maybe_push_tag(
event: &BytesStart,
reader: &Reader<impl BufRead>,

View File

@@ -593,6 +593,7 @@ async fn next_expiration_timestamp(context: &Context) -> Option<i64> {
.min()
}
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn ephemeral_loop(context: &Context, interrupt_receiver: Receiver<()>) {
loop {
let ephemeral_timestamp = next_expiration_timestamp(context).await;
@@ -650,6 +651,7 @@ pub(crate) async fn ephemeral_loop(context: &Context, interrupt_receiver: Receiv
}
/// Schedules expired IMAP messages for deletion.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn delete_expired_imap_messages(context: &Context) -> Result<()> {
let now = time();

View File

@@ -86,6 +86,7 @@ impl HtmlMsgParser {
/// Function takes a raw mime-message string,
/// searches for the main-text part
/// and returns that as parser.html
#[expect(clippy::arithmetic_side_effects)]
pub async fn from_bytes<'a>(
context: &Context,
rawmime: &'a [u8],
@@ -119,6 +120,7 @@ impl HtmlMsgParser {
/// Usually, there is at most one plain-text and one HTML-text part,
/// multiple plain-text parts might be used for mailinglist-footers,
/// therefore we use the first one.
#[expect(clippy::arithmetic_side_effects)]
async fn collect_texts_recursive<'a>(
&'a mut self,
context: &'a Context,

View File

@@ -208,6 +208,7 @@ impl<T: Iterator<Item = (i64, u32, String)>> Iterator for UidGrouper<T> {
// Tuple of folder, row IDs, and UID range as a string.
type Item = (String, Vec<i64>, String);
#[expect(clippy::arithmetic_side_effects)]
fn next(&mut self) -> Option<Self::Item> {
let (_, _, folder) = self.inner.peek().cloned()?;
@@ -543,6 +544,7 @@ impl Imap {
/// Fetches new messages.
///
/// Returns true if at least one message was fetched.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn fetch_new_messages(
&mut self,
context: &Context,
@@ -583,6 +585,7 @@ impl Imap {
}
/// Returns number of messages processed and whether the function should be called again.
#[expect(clippy::arithmetic_side_effects)]
async fn fetch_new_msg_batch(
&mut self,
context: &Context,
@@ -1265,6 +1268,7 @@ impl Session {
///
/// If the message is incorrect or there is a failure to write a message to the database,
/// it is skipped and the error is logged.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn fetch_many_msgs(
&mut self,
context: &Context,
@@ -1429,6 +1433,7 @@ impl Session {
/// We get [`/shared/comment`](https://www.rfc-editor.org/rfc/rfc5464#section-6.2.1)
/// and [`/shared/admin`](https://www.rfc-editor.org/rfc/rfc5464#section-6.2.2)
/// metadata.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn update_metadata(&mut self, context: &Context) -> Result<()> {
let mut lock = context.metadata.write().await;
@@ -2364,6 +2369,7 @@ async fn should_ignore_folder(
/// Builds a list of sequence/uid sets. The returned sets have each no more than around 1000
/// characters because according to <https://tools.ietf.org/html/rfc2683#section-3.2.1.5>
/// command lines should not be much more than 1000 chars (servers should allow at least 8000 chars)
#[expect(clippy::arithmetic_side_effects)]
fn build_sequence_sets(uids: &[u32]) -> Result<Vec<(Vec<u32>, String)>> {
// first, try to find consecutive ranges:
let mut ranges: Vec<UidRange> = vec![];

View File

@@ -127,6 +127,7 @@ impl Session {
/// Prefetch `n_uids` messages starting from `uid_next`. Returns a list of fetch results in the
/// order of ascending delivery time to the server (INTERNALDATE).
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn prefetch(
&mut self,
uid_next: u32,

View File

@@ -293,6 +293,7 @@ impl<R> AsyncRead for ProgressReader<R>
where
R: AsyncRead,
{
#[expect(clippy::arithmetic_side_effects)]
fn poll_read(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
@@ -438,6 +439,7 @@ fn get_next_backup_path(
/// Exports the database to a separate file with the given passphrase.
///
/// Set passphrase to empty string to export the database unencrypted.
#[expect(clippy::arithmetic_side_effects)]
async fn export_backup(context: &Context, dir: &Path, passphrase: String) -> Result<()> {
// get a fine backup file name (the name includes the date so that multiple backup instances are possible)
let now = time();
@@ -511,6 +513,7 @@ impl<W> AsyncWrite for ProgressWriter<W>
where
W: AsyncWrite,
{
#[expect(clippy::arithmetic_side_effects)]
fn poll_write(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
@@ -590,6 +593,7 @@ async fn import_secret_key(context: &Context, path: &Path) -> Result<()> {
/// containing secret keys are imported and the last successfully
/// imported which does not contain "legacy" in its filename
/// is set as the default.
#[expect(clippy::arithmetic_side_effects)]
async fn import_self_keys(context: &Context, path: &Path) -> Result<()> {
let attr = tokio::fs::metadata(path).await?;
@@ -643,6 +647,7 @@ async fn import_self_keys(context: &Context, path: &Path) -> Result<()> {
Ok(())
}
#[expect(clippy::arithmetic_side_effects)]
async fn export_self_keys(context: &Context, dir: &Path) -> Result<()> {
let mut export_errors = 0;

View File

@@ -129,6 +129,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
}
/// Creates a new setup code for Autocrypt Setup Message.
#[expect(clippy::arithmetic_side_effects)]
fn create_setup_code(_context: &Context) -> String {
let mut random_val: u16;
let mut ret = String::new();

View File

@@ -166,6 +166,7 @@ impl BackupProvider {
})
}
#[expect(clippy::arithmetic_side_effects)]
async fn handle_connection(
context: Context,
conn: iroh::endpoint::Connecting,

View File

@@ -17,6 +17,7 @@
clippy::cloned_instead_of_copied,
clippy::manual_is_variant_and
)]
#![cfg_attr(not(test), warn(clippy::arithmetic_side_effects))]
#![cfg_attr(not(test), forbid(clippy::indexing_slicing))]
#![cfg_attr(not(test), forbid(clippy::string_slice))]
#![allow(

View File

@@ -263,6 +263,7 @@ impl Kml {
}
/// Enables location streaming in chat identified by `chat_id` for `seconds` seconds.
#[expect(clippy::arithmetic_side_effects)]
pub async fn send_locations_to_chat(
context: &Context,
chat_id: ChatId,
@@ -385,6 +386,7 @@ pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64
}
/// Searches for locations in the given time range, optionally filtering by chat and contact IDs.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_range(
context: &Context,
chat_id: Option<ChatId>,
@@ -517,6 +519,7 @@ pub(crate) async fn delete_orphaned_poi_locations(context: &Context) -> Result<(
}
/// Returns `location.kml` contents.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result<Option<(String, u32)>> {
let mut last_added_location_id = 0;
@@ -752,6 +755,7 @@ pub(crate) async fn location_loop(context: &Context, interrupt_receiver: Receive
/// Returns number of seconds until the next time location streaming for some chat ends
/// automatically.
#[expect(clippy::arithmetic_side_effects)]
async fn maybe_send_locations(context: &Context) -> Result<Option<u64>> {
let mut next_event: Option<u64> = None;

View File

@@ -76,6 +76,7 @@ impl<S: SessionStream> LoggingStream<S> {
}
impl<S: SessionStream> AsyncRead for LoggingStream<S> {
#[expect(clippy::arithmetic_side_effects)]
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,

View File

@@ -201,6 +201,7 @@ SELECT ?1, rfc724_mid, pre_rfc724_mid, timestamp, ?, ? FROM msgs WHERE id=?1
}
/// Returns detailed message information in a multi-line text form.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_info(self, context: &Context) -> Result<String> {
let msg = Message::load_from_db(context, self).await?;
@@ -822,6 +823,7 @@ impl Message {
///
/// Currently this includes `additional_text`, but this may change in future, when the UIs show
/// the necessary info themselves.
#[expect(clippy::arithmetic_side_effects)]
pub fn get_text(&self) -> String {
self.text.clone() + &self.additional_text
}
@@ -964,6 +966,7 @@ impl Message {
///
/// A message has a deviating timestamp when it is sent on
/// another day as received/sorted by.
#[expect(clippy::arithmetic_side_effects)]
pub fn has_deviating_timestamp(&self) -> bool {
let cnv_to_local = gm2local_offset();
let sort_timestamp = self.get_sort_timestamp() + cnv_to_local;
@@ -2119,6 +2122,7 @@ pub async fn get_request_msg_cnt(context: &Context) -> usize {
/// Returns the number of messages that are older than the given number of seconds.
/// This includes e-mails downloaded due to the `show_emails` option.
/// Messages in the "saved messages" folder are not counted as they will not be deleted automatically.
#[expect(clippy::arithmetic_side_effects)]
pub async fn estimate_deletion_cnt(
context: &Context,
from_server: bool,

View File

@@ -195,6 +195,7 @@ fn new_address_with_name(name: &str, address: String) -> Address<'static> {
}
impl MimeFactory {
#[expect(clippy::arithmetic_side_effects)]
pub async fn from_msg(context: &Context, msg: Message) -> Result<MimeFactory> {
let now = time();
let chat = Chat::load_from_db(context, msg.chat_id).await?;
@@ -726,6 +727,7 @@ impl MimeFactory {
/// Consumes a `MimeFactory` and renders it into a message which is then stored in
/// `smtp`-table to be used by the SMTP loop
#[expect(clippy::arithmetic_side_effects)]
pub async fn render(mut self, context: &Context) -> Result<RenderedEmail> {
let mut headers = Vec::<(&'static str, HeaderType<'static>)>::new();
@@ -2069,6 +2071,7 @@ impl MimeFactory {
}
/// Render an MDN
#[expect(clippy::arithmetic_side_effects)]
fn render_mdn(&mut self) -> Result<MimePart<'static>> {
// RFC 6522, this also requires the `report-type` parameter which is equal
// to the MIME subtype of the second body part of the multipart/report

View File

@@ -266,6 +266,7 @@ impl MimeMessage {
///
/// This method has some side-effects,
/// such as saving blobs and saving found public keys to the database.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn from_bytes(context: &Context, body: &[u8]) -> Result<Self> {
let mail = mailparse::parse_mail(body)?;
@@ -728,6 +729,7 @@ impl MimeMessage {
Ok(parser)
}
#[expect(clippy::arithmetic_side_effects)]
fn get_timestamp_sent(
hdrs: &[mailparse::MailHeader<'_>],
default: i64,
@@ -1005,6 +1007,7 @@ impl MimeMessage {
Ok(())
}
#[expect(clippy::arithmetic_side_effects)]
fn avatar_action_from_header(
&mut self,
context: &Context,
@@ -1506,6 +1509,7 @@ impl MimeMessage {
}
#[expect(clippy::too_many_arguments)]
#[expect(clippy::arithmetic_side_effects)]
async fn do_add_single_file_part(
&mut self,
context: &Context,
@@ -2057,6 +2061,7 @@ impl MimeMessage {
/// Returns parsed `Chat-Group-Member-Timestamps` header contents.
///
/// Returns `None` if there is no such header.
#[expect(clippy::arithmetic_side_effects)]
pub fn chat_group_member_timestamps(&self) -> Option<Vec<i64>> {
let now = time() + constants::TIMESTAMP_SENT_TOLERANCE;
self.get_header(HeaderDef::ChatGroupMemberTimestamps)

View File

@@ -115,6 +115,7 @@ where
}
/// Converts the URL to expiration and stale timestamps.
#[expect(clippy::arithmetic_side_effects)]
fn http_url_cache_timestamps(url: &str, mimetype: Option<&str>) -> (i64, i64) {
let now = time();
@@ -173,6 +174,7 @@ async fn http_cache_put(context: &Context, url: &str, response: &Response) -> Re
/// Retrieves the binary from HTTP cache.
///
/// Also returns if the response is stale and should be revalidated in the background.
#[expect(clippy::arithmetic_side_effects)]
async fn http_cache_get(context: &Context, url: &str) -> Result<Option<(Response, bool)>> {
let now = time();
let Some((blob_name, mimetype, encoding, stale_timestamp)) = context

View File

@@ -174,6 +174,7 @@ pub enum ProxyConfig {
}
/// Constructs HTTP/1.1 `CONNECT` request for HTTP(S) proxy.
#[expect(clippy::arithmetic_side_effects)]
fn http_connect_request(host: &str, port: u16, auth: Option<(&str, &str)>) -> String {
// According to <https://datatracker.ietf.org/doc/html/rfc7230#section-5.4>
// clients MUST send `Host:` header in HTTP/1.1 requests,
@@ -322,6 +323,7 @@ impl ProxyConfig {
/// config into `proxy_url` if `proxy_url` is unset or empty.
///
/// Unsets `socks5_host`, `socks5_port`, `socks5_user` and `socks5_password` in any case.
#[expect(clippy::arithmetic_side_effects)]
async fn migrate_socks_config(sql: &Sql) -> Result<()> {
if sql.get_raw_config("proxy_url").await?.is_none() {
// Load legacy SOCKS5 settings.

View File

@@ -67,6 +67,7 @@ pub async fn get_oauth2_url(
}
}
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn get_oauth2_access_token(
context: &Context,
addr: &str,
@@ -256,6 +257,7 @@ pub(crate) async fn get_oauth2_addr(
}
impl Oauth2 {
#[expect(clippy::arithmetic_side_effects)]
fn from_address(addr: &str) -> Option<Self> {
let addr_normalized = normalize_addr(addr);
if let Some(domain) = addr_normalized

View File

@@ -533,6 +533,7 @@ pub(crate) fn iroh_topic_from_str(topic: &str) -> Result<TopicId> {
Ok(topic)
}
#[expect(clippy::arithmetic_side_effects)]
async fn subscribe_loop(
context: &Context,
mut stream: iroh_gossip::net::GossipReceiver,

View File

@@ -170,6 +170,7 @@ pub enum SeipdVersion {
/// Encrypts `plain` text using `public_keys_for_encryption`
/// and signs it using `private_key_for_signing`.
#[expect(clippy::arithmetic_side_effects)]
pub async fn pk_encrypt(
plain: Vec<u8>,
public_keys_for_encryption: Vec<SignedPublicKey>,

View File

@@ -24,6 +24,7 @@ pub struct PlainText {
impl PlainText {
/// Convert plain text to HTML.
/// The function handles quotes, links, fixed and floating text paragraphs.
#[expect(clippy::arithmetic_side_effects)]
pub fn to_html(&self) -> String {
static LINKIFY_MAIL_RE: LazyLock<regex::Regex> =
LazyLock::new(|| regex::Regex::new(r"\b([\w.\-+]+@[\w.\-]+)\b").unwrap());

View File

@@ -680,6 +680,7 @@ fn decode_account(qr: &str) -> Result<Qr> {
}
/// scheme: `https://t.me/socks?server=foo&port=123` or `https://t.me/socks?server=1.2.3.4&port=123`
#[expect(clippy::arithmetic_side_effects)]
fn decode_tg_socks_proxy(_context: &Context, qr: &str) -> Result<Qr> {
let url = url::Url::parse(qr).context("Invalid t.me/socks url")?;
@@ -1021,6 +1022,7 @@ async fn decode_smtp(context: &Context, qr: &str) -> Result<Qr> {
/// Scheme: `MATMSG:TO:addr...;SUB:subject...;BODY:body...;`
///
/// There may or may not be linebreaks after the fields.
#[expect(clippy::arithmetic_side_effects)]
async fn decode_matmsg(context: &Context, qr: &str) -> Result<Qr> {
// Does not work when the text `TO:` is used in subject/body _and_ TO: is not the first field.
// we ignore this case.

View File

@@ -15,6 +15,7 @@ use crate::securejoin;
use crate::stock_str::{self, backup_transfer_qr};
/// Create a QR code from any input data.
#[expect(clippy::arithmetic_side_effects)]
pub fn create_qr_svg(qrcode_content: &str) -> Result<String> {
let all_size = 512.0;
let qr_code_size = 416.0;
@@ -175,6 +176,7 @@ async fn self_info(context: &Context) -> Result<(Option<Vec<u8>>, String, String
Ok((avatar, displayname, addr, color))
}
#[expect(clippy::arithmetic_side_effects)]
fn inner_generate_secure_join_qr_code(
qrcode_description: &str,
qrcode_content: &str,

View File

@@ -122,6 +122,7 @@ impl Reactions {
}
/// Returns a map from emojis to their frequencies.
#[expect(clippy::arithmetic_side_effects)]
pub fn emoji_frequencies(&self) -> BTreeMap<String, usize> {
let mut emoji_frequencies: BTreeMap<String, usize> = BTreeMap::new();
for reaction in self.reactions.values() {

View File

@@ -1185,6 +1185,7 @@ pub async fn from_field_to_contact_id(
}
}
#[expect(clippy::arithmetic_side_effects)]
async fn decide_chat_assignment(
context: &Context,
mime_parser: &MimeMessage,
@@ -2919,6 +2920,7 @@ async fn create_group(
}
}
#[expect(clippy::arithmetic_side_effects)]
async fn update_chats_contacts_timestamps(
context: &Context,
chat_id: ChatId,
@@ -3418,6 +3420,7 @@ async fn apply_chat_name_avatar_and_description_changes(
}
/// Returns a list of strings that should be shown as info messages, informing about group membership changes.
#[expect(clippy::arithmetic_side_effects)]
async fn group_changes_msgs(
context: &Context,
added_ids: &HashSet<ContactId>,

View File

@@ -303,6 +303,7 @@ impl Context {
///
/// This comes as an HTML from the core so that we can easily improve it
/// and the improvement instantly reaches all UIs.
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_connectivity_html(&self) -> Result<String> {
let mut ret = r#"<!DOCTYPE html>
<html>

View File

@@ -410,6 +410,7 @@ pub(crate) fn get_secure_join_step(mime_message: &MimeMessage) -> Option<SecureJ
///
/// When `handle_securejoin_handshake()` is called, the message is not yet filed in the
/// database; this is done by `receive_imf()` later on as needed.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn handle_securejoin_handshake(
context: &Context,
mime_message: &mut MimeMessage,

View File

@@ -9,6 +9,7 @@ use crate::tools::IsNoneOrEmpty;
/// This escapes a bit more than actually needed by delta (e.g. also lines as "-- footer"),
/// but for non-delta-compatibility, that seems to be better.
/// (to be only compatible with delta, only "[\r\n|\n]-- {0,2}[\r\n|\n]" needs to be replaced)
#[expect(clippy::arithmetic_side_effects)]
pub fn escape_message_footer_marks(text: &str) -> String {
if let Some(text) = text.strip_prefix("--") {
"-\u{200B}-".to_string() + &text.replace("\n--", "\n-\u{200B}-")
@@ -21,6 +22,7 @@ pub fn escape_message_footer_marks(text: &str) -> String {
/// Returns `(lines, footer_lines)` tuple;
/// `footer_lines` is set to `Some` if the footer was actually removed from `lines`
/// (which is equal to the input array otherwise).
#[expect(clippy::arithmetic_side_effects)]
pub(crate) fn remove_message_footer<'a>(
lines: &'a [&str],
) -> (&'a [&'a str], Option<&'a [&'a str]>) {
@@ -175,6 +177,7 @@ fn skip_forward_header<'a>(lines: &'a [&str]) -> (&'a [&'a str], bool) {
}
}
#[expect(clippy::arithmetic_side_effects)]
fn remove_bottom_quote<'a>(lines: &'a [&str]) -> (&'a [&'a str], Option<String>) {
let mut first_quoted_line = lines.len();
let mut last_quoted_line = None;
@@ -217,6 +220,7 @@ fn remove_bottom_quote<'a>(lines: &'a [&str]) -> (&'a [&'a str], Option<String>)
}
}
#[expect(clippy::arithmetic_side_effects)]
fn remove_top_quote<'a>(
lines: &'a [&str],
is_chat_message: bool,
@@ -262,6 +266,7 @@ fn remove_top_quote<'a>(
}
}
#[expect(clippy::arithmetic_side_effects)]
fn render_message(lines: &[&str], is_cut_at_end: bool) -> String {
let mut ret = String::new();
/* we write empty lines only in case and non-empty line follows */

View File

@@ -798,6 +798,7 @@ fn new_connection(path: &Path, passphrase: &str) -> Result<Connection> {
// Tries to clear the freelist to free some space on the disk.
//
// This only works if auto_vacuum is enabled.
#[expect(clippy::arithmetic_side_effects)]
async fn incremental_vacuum(context: &Context) -> Result<()> {
context
.sql
@@ -956,6 +957,7 @@ pub fn row_get_vec(row: &Row, idx: usize) -> rusqlite::Result<Vec<u8>> {
}
/// Enumerates used files in the blobdir and removes unused ones.
#[expect(clippy::arithmetic_side_effects)]
pub async fn remove_unused_files(context: &Context) -> Result<()> {
let mut files_in_use = HashSet::new();
let mut unreferenced_count = 0;

View File

@@ -31,6 +31,7 @@ tokio::task_local! {
static STOP_MIGRATIONS_AT: i32;
}
#[expect(clippy::arithmetic_side_effects)]
pub async fn run(context: &Context, sql: &Sql) -> Result<bool> {
let mut exists_before_update = false;
let mut dbversion_before_update = DBVERSION;
@@ -2202,6 +2203,7 @@ fn migrate_key_contacts(
}
/// Rewrite `from_id`, `to_id` in >= 1000 messages starting from the newest ones, to key-contacts.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn msgs_to_key_contacts(context: &Context) -> Result<()> {
let sql = &context.sql;
if sql

View File

@@ -50,6 +50,7 @@ impl std::fmt::Display for StorageUsage {
}
/// Get storage usage information for the Context's database
#[expect(clippy::arithmetic_side_effects)]
pub async fn get_storage_usage(ctx: &Context) -> Result<StorageUsage> {
let context_clone = ctx.clone();
let blobdir_size =
@@ -121,6 +122,7 @@ pub async fn get_storage_usage(ctx: &Context) -> Result<StorageUsage> {
}
/// Returns storage usage of the blob directory
#[expect(clippy::arithmetic_side_effects)]
pub fn get_blobdir_storage_usage(ctx: &Context) -> u64 {
WalkDir::new(ctx.get_blobdir())
.max_depth(2)

View File

@@ -37,6 +37,7 @@ impl SmearedTimestamp {
/// Allocates `count` unique timestamps.
///
/// Returns the first allocated timestamp.
#[expect(clippy::arithmetic_side_effects)]
pub fn create_n(&self, now: i64, count: i64) -> i64 {
let mut prev = self.smeared_timestamp.load(Ordering::Relaxed);
loop {

View File

@@ -47,6 +47,7 @@ use crate::stock_str;
/// Shortens a string to a specified length and adds "[...]" to the
/// end of the shortened string.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) fn truncate(buf: &str, approx_chars: usize) -> Cow<'_, str> {
let count = buf.chars().count();
if count <= approx_chars + DC_ELLIPSIS.len() {
@@ -77,6 +78,7 @@ pub(crate) fn truncate(buf: &str, approx_chars: usize) -> Cow<'_, str> {
/// end of the shortened string.
///
/// returns tuple with the String and a boolean whether is was truncated
#[expect(clippy::arithmetic_side_effects)]
pub(crate) fn truncate_by_lines(
buf: String,
max_lines: usize,
@@ -256,6 +258,7 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam
false
}
#[expect(clippy::arithmetic_side_effects)]
async fn maybe_warn_on_outdated(context: &Context, now: i64, approx_compile_time: i64) {
if now > approx_compile_time + DC_OUTDATED_WARNING_DAYS * 24 * 60 * 60 {
let mut msg = Message::new_text(stock_str::update_reminder_msg_body(context).await);
@@ -649,6 +652,7 @@ impl ToOption<String> for Option<i32> {
}
}
#[expect(clippy::arithmetic_side_effects)]
pub fn remove_subject_prefix(last_subject: &str) -> String {
let subject_start = if last_subject.starts_with("Chat:") {
0
@@ -671,6 +675,7 @@ pub fn remove_subject_prefix(last_subject: &str) -> String {
// Types and methods to create hop-info for message-info
#[expect(clippy::arithmetic_side_effects)]
fn extract_address_from_receive_header<'a>(header: &'a str, start: &str) -> Option<&'a str> {
let header_len = header.len();
header.find(start).and_then(|mut begin| {
@@ -683,6 +688,7 @@ fn extract_address_from_receive_header<'a>(header: &'a str, start: &str) -> Opti
})
}
#[expect(clippy::arithmetic_side_effects)]
pub(crate) fn parse_receive_header(header: &str) -> String {
let header = header.replace(&['\r', '\n'][..], "");
let mut hop_info = String::from("Hop: ");
@@ -789,6 +795,7 @@ pub(crate) fn normalize_text(text: &str) -> Option<String> {
}
/// Increments `*t` and checks that it equals to `expected` after that.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) fn inc_and_check<T: PrimInt + AddAssign + std::fmt::Debug>(
t: &mut T,
expected: T,

View File

@@ -782,6 +782,7 @@ impl Context {
/// {"payload":"another update data"}]}`
///
/// * `(first, last)`: range of status update serials to send.
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn render_webxdc_status_update_object(
&self,
instance_msg_id: MsgId,

View File

@@ -96,6 +96,7 @@ pub(crate) async fn intercept_send_update(
Ok(())
}
#[expect(clippy::arithmetic_side_effects)]
pub(crate) async fn intercept_get_updates(
context: &Context,
chat_id: Option<ChatId>,