Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions deltachat-jsonrpc/src/api/types/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub enum EventType {
/// Progress.
///
/// 0=error, 1-999=progress in permille, 1000=success and done
progress: usize,
progress: u16,

/// Progress comment or error, something to display to the user.
comment: Option<String>,
Expand All @@ -282,7 +282,7 @@ pub enum EventType {
#[serde(rename_all = "camelCase")]
ImexProgress {
/// 0=error, 1-999=progress in permille, 1000=success and done
progress: usize,
progress: u16,
},

/// A file has been exported. A file has been written by imex().
Expand Down Expand Up @@ -313,7 +313,7 @@ pub enum EventType {
chat_id: u32,

/// Progress, always 1000.
progress: usize,
progress: u16,
},

/// Progress information of a secure-join handshake from the view of the joiner
Expand All @@ -329,7 +329,7 @@ pub enum EventType {
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
/// (Bob has verified alice and waits until Alice does the same for him)
/// 1000=vg-member-added/vc-contact-confirm received
progress: usize,
progress: u16,
},

/// The connectivity to the server changed.
Expand Down
8 changes: 4 additions & 4 deletions src/events/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ pub enum EventType {
/// Progress.
///
/// 0=error, 1-999=progress in permille, 1000=success and done
progress: usize,
progress: u16,

/// Progress comment or error, something to display to the user.
comment: Option<String>,
Expand All @@ -253,7 +253,7 @@ pub enum EventType {
///
/// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done
/// @param data2 0
ImexProgress(usize),
ImexProgress(u16),

/// A file has been exported. A file has been written by imex().
/// This event may be sent multiple times by a single call to imex().
Expand All @@ -280,7 +280,7 @@ pub enum EventType {
chat_type: Chattype,

/// Progress, always 1000.
progress: usize,
progress: u16,
},

/// Progress information of a secure-join handshake from the view of the joiner
Expand All @@ -295,7 +295,7 @@ pub enum EventType {
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
/// (Bob has verified alice and waits until Alice does the same for him)
/// 1000=vg-member-added/vc-contact-confirm received
progress: usize,
progress: u16,
},

/// The connectivity to the server changed.
Expand Down
29 changes: 16 additions & 13 deletions src/imex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use crate::pgp;
use crate::qr::DCBACKUP_VERSION;
use crate::sql;
use crate::tools::{
TempPathGuard, create_folder, delete_file, get_filesuffix_lc, read_file, time, write_file,
TempPathGuard, create_folder, delete_file, get_filesuffix_lc, read_file, time, usize_to_u64,
write_file,
};

mod key_transfer;
Expand Down Expand Up @@ -263,14 +264,14 @@ struct ProgressReader<R> {
inner: R,

/// Number of bytes successfully read from the internal reader.
read: usize,
read: u64,

/// Total size of the backup .tar file expected to be read from the reader.
/// Used to calculate the progress.
file_size: usize,
file_size: u64,

/// Last progress emitted to avoid emitting the same progress value twice.
last_progress: usize,
last_progress: u16,

/// Context for emitting progress events.
context: Context,
Expand All @@ -281,7 +282,7 @@ impl<R> ProgressReader<R> {
Self {
inner: r,
read: 0,
file_size: file_size as usize,
file_size,
last_progress: 1,
context,
}
Expand All @@ -301,9 +302,11 @@ where
let before = buf.filled().len();
let res = this.inner.poll_read(cx, buf);
if let std::task::Poll::Ready(Ok(())) = res {
*this.read = this.read.saturating_add(buf.filled().len() - before);
*this.read = this
.read
.saturating_add(usize_to_u64(buf.filled().len() - before));

let progress = std::cmp::min(1000 * *this.read / *this.file_size, 999);
let progress = std::cmp::min(1000 * *this.read / *this.file_size, 999) as u16;
if progress > *this.last_progress {
this.context.emit_event(EventType::ImexProgress(progress));
*this.last_progress = progress;
Expand Down Expand Up @@ -490,14 +493,14 @@ struct ProgressWriter<W> {
inner: W,

/// Number of bytes successfully written into the internal writer.
written: usize,
written: u64,

/// Total size of the backup .tar file expected to be written into the writer.
/// Used to calculate the progress.
file_size: usize,
file_size: u64,

/// Last progress emitted to avoid emitting the same progress value twice.
last_progress: usize,
last_progress: u16,

/// Context for emitting progress events.
context: Context,
Expand All @@ -508,7 +511,7 @@ impl<W> ProgressWriter<W> {
Self {
inner: w,
written: 0,
file_size: file_size as usize,
file_size,
last_progress: 1,
context,
}
Expand All @@ -527,9 +530,9 @@ where
let this = self.project();
let res = this.inner.poll_write(cx, buf);
if let std::task::Poll::Ready(Ok(written)) = res {
*this.written = this.written.saturating_add(written);
*this.written = this.written.saturating_add(usize_to_u64(written));

let progress = std::cmp::min(1000 * *this.written / *this.file_size, 999);
let progress = std::cmp::min(1000 * *this.written / *this.file_size, 999) as u16;
if progress > *this.last_progress {
this.context.emit_event(EventType::ImexProgress(progress));
*this.last_progress = progress;
Expand Down
11 changes: 6 additions & 5 deletions src/log/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@ use pin_project::pin_project;

use crate::events::{Event, EventType, Events};
use crate::net::session::SessionStream;
use crate::tools::usize_to_u64;

use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};

#[derive(Debug)]
struct Metrics {
/// Total number of bytes read.
pub total_read: usize,
pub total_read: u64,

/// Total number of bytes written.
pub total_written: usize,
pub total_written: u64,
}

impl Metrics {
Expand Down Expand Up @@ -98,7 +99,7 @@ impl<S: SessionStream> AsyncRead for LoggingStream<S> {
}

let n = old_remaining - buf.remaining();
this.metrics.total_read = this.metrics.total_read.saturating_add(n);
this.metrics.total_read = this.metrics.total_read.saturating_add(usize_to_u64(n));

res
}
Expand All @@ -113,7 +114,7 @@ impl<S: SessionStream> AsyncWrite for LoggingStream<S> {
let this = self.project();
let res = this.inner.poll_write(cx, buf);
if let Poll::Ready(Ok(n)) = res {
this.metrics.total_written = this.metrics.total_written.saturating_add(n);
this.metrics.total_written = this.metrics.total_written.saturating_add(usize_to_u64(n));
}
res
}
Expand All @@ -140,7 +141,7 @@ impl<S: SessionStream> AsyncWrite for LoggingStream<S> {
let this = self.project();
let res = this.inner.poll_write_vectored(cx, bufs);
if let Poll::Ready(Ok(n)) = res {
this.metrics.total_written = this.metrics.total_written.saturating_add(n);
this.metrics.total_written = this.metrics.total_written.saturating_add(usize_to_u64(n));
}
res
}
Expand Down
4 changes: 2 additions & 2 deletions src/securejoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ pub(crate) async fn handle_securejoin_handshake(
"vc-contact-confirm" => {
context.emit_event(EventType::SecurejoinJoinerProgress {
contact_id,
progress: JoinerProgress::Succeeded.to_usize(),
progress: JoinerProgress::Succeeded.into_u16(),
});
Ok(HandshakeMessage::Ignore)
}
Expand All @@ -590,7 +590,7 @@ pub(crate) async fn handle_securejoin_handshake(

context.emit_event(EventType::SecurejoinJoinerProgress {
contact_id,
progress: JoinerProgress::Succeeded.to_usize(),
progress: JoinerProgress::Succeeded.into_u16(),
});
Ok(HandshakeMessage::Propagate)
}
Expand Down
9 changes: 4 additions & 5 deletions src/securejoin/bob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul
// Even if Alice is not verified, we don't send anything.
context.emit_event(EventType::SecurejoinJoinerProgress {
contact_id: invite.contact_id(),
progress: JoinerProgress::Succeeded.to_usize(),
progress: JoinerProgress::Succeeded.into_u16(),
});
return Ok(joining_chat_id);
} else if has_key
Expand All @@ -113,7 +113,7 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul

context.emit_event(EventType::SecurejoinJoinerProgress {
contact_id: invite.contact_id(),
progress: JoinerProgress::RequestWithAuthSent.to_usize(),
progress: JoinerProgress::RequestWithAuthSent.into_u16(),
});
} else {
send_handshake_message(context, &invite, private_chat_id, BobHandshakeMsg::Request)
Expand Down Expand Up @@ -240,7 +240,7 @@ pub(super) async fn handle_auth_required(

context.emit_event(EventType::SecurejoinJoinerProgress {
contact_id: invite.contact_id(),
progress: JoinerProgress::RequestWithAuthSent.to_usize(),
progress: JoinerProgress::RequestWithAuthSent.into_u16(),
});

auth_sent = true;
Expand Down Expand Up @@ -406,8 +406,7 @@ pub(crate) enum JoinerProgress {
}

impl JoinerProgress {
#[expect(clippy::wrong_self_convention)]
pub(crate) fn to_usize(self) -> usize {
pub(crate) fn into_u16(self) -> u16 {
match self {
JoinerProgress::RequestWithAuthSent => 400,
JoinerProgress::Succeeded => 1000,
Expand Down
20 changes: 20 additions & 0 deletions src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,26 @@ pub(crate) fn inc_and_check<T: PrimInt + AddAssign + std::fmt::Debug>(
Ok(())
}

/// Converts usize to u64 without using `as`.
///
/// This is needed for example to convert in-memory buffer sizes
/// to u64 type used for counting all the bytes written.
///
/// On 32-bit systems it is possible to have files
/// larger than 4 GiB or write more than 4 GiB to network connection,
/// in which case we need a 64-bit total counter,
/// but use 32-bit usize for buffer sizes.
///
/// This can only break if usize has more than 64 bits
/// and this is not the case as of 2025 and is
/// unlikely to change for general purpose computers.
/// See <https://github.com/rust-lang/rust/issues/30495>
/// and <https://users.rust-lang.org/t/cant-convert-usize-to-u64/6243>
/// and <https://github.com/rust-lang/rust/issues/106050>.
pub(crate) fn usize_to_u64(v: usize) -> u64 {
u64::try_from(v).unwrap_or(u64::MAX)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just unwrap()? Panics that can't really happen should be fine

Copy link
Collaborator Author

@link2xt link2xt Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with adding unwrap() in places that cannot happen is that once the app without debug info crashes on a phone for some user, you now need to look at all the places which may panic. E.g. you add 100 unwraps(), get one wrong and it actually panics, and then you need to review 100 places. This also includes all the dependencies, so if some dependency crashes with .unwrap(), if we don't have .unwrap() in our code we can immediately know that this is not caused by our own code.

}

/// Returns early with an error if a condition is not satisfied.
/// In non-optimized builds, panics instead if so.
#[macro_export]
Expand Down