(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn open_trampoline(
this: *mut ffi::GApplication,
@@ -56,6 +59,76 @@ pub trait ApplicationExtManual: IsA {
}
}
+ #[doc(alias = "command-line")]
+ fn connect_command_line ExitCode + 'static>(
+ &self,
+ f: F,
+ ) -> SignalHandlerId {
+ unsafe extern "C" fn command_line_trampoline<
+ P: IsA,
+ F: Fn(&P, &ApplicationCommandLine) -> ExitCode + 'static,
+ >(
+ this: *mut ffi::GApplication,
+ command_line: *mut ffi::GApplicationCommandLine,
+ f: glib::ffi::gpointer,
+ ) -> std::ffi::c_int {
+ let f: &F = &*(f as *const F);
+ f(
+ Application::from_glib_borrow(this).unsafe_cast_ref(),
+ &from_glib_borrow(command_line),
+ )
+ .into()
+ }
+ unsafe {
+ let f: Box_ = Box_::new(f);
+ connect_raw(
+ self.as_ptr() as *mut _,
+ c"command-line".as_ptr() as *const _,
+ Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
+ command_line_trampoline:: as *const (),
+ )),
+ Box_::into_raw(f),
+ )
+ }
+ }
+
+ #[doc(alias = "handle-local-options")]
+ fn connect_handle_local_options<
+ F: Fn(&Self, &glib::VariantDict) -> ControlFlow + 'static,
+ >(
+ &self,
+ f: F,
+ ) -> SignalHandlerId {
+ unsafe extern "C" fn handle_local_options_trampoline<
+ P: IsA,
+ F: Fn(&P, &glib::VariantDict) -> ControlFlow + 'static,
+ >(
+ this: *mut ffi::GApplication,
+ options: *mut glib::ffi::GVariantDict,
+ f: glib::ffi::gpointer,
+ ) -> std::ffi::c_int {
+ let f: &F = &*(f as *const F);
+ f(
+ Application::from_glib_borrow(this).unsafe_cast_ref(),
+ &from_glib_borrow(options),
+ )
+ .break_value()
+ .map(i32::from)
+ .unwrap_or(-1)
+ }
+ unsafe {
+ let f: Box_ = Box_::new(f);
+ connect_raw(
+ self.as_ptr() as *mut _,
+ c"handle-local-options".as_ptr() as *const _,
+ Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
+ handle_local_options_trampoline:: as *const (),
+ )),
+ Box_::into_raw(f),
+ )
+ }
+ }
+
#[doc(alias = "g_application_hold")]
fn hold(&self) -> ApplicationHoldGuard {
unsafe {
diff --git a/gio/src/auto/application.rs b/gio/src/auto/application.rs
index 009a68e0eaa4..86908faf9b89 100644
--- a/gio/src/auto/application.rs
+++ b/gio/src/auto/application.rs
@@ -3,8 +3,7 @@
// DO NOT EDIT
use crate::{
- ffi, ActionGroup, ActionMap, ApplicationCommandLine, ApplicationFlags, Cancellable,
- DBusConnection, File, Notification,
+ ffi, ActionGroup, ActionMap, ApplicationFlags, Cancellable, DBusConnection, File, Notification,
};
use glib::{
object::ObjectType as _,
@@ -464,70 +463,6 @@ pub trait ApplicationExt: IsA + 'static {
}
}
- #[doc(alias = "command-line")]
- fn connect_command_line i32 + 'static>(
- &self,
- f: F,
- ) -> SignalHandlerId {
- unsafe extern "C" fn command_line_trampoline<
- P: IsA,
- F: Fn(&P, &ApplicationCommandLine) -> i32 + 'static,
- >(
- this: *mut ffi::GApplication,
- command_line: *mut ffi::GApplicationCommandLine,
- f: glib::ffi::gpointer,
- ) -> std::ffi::c_int {
- let f: &F = &*(f as *const F);
- f(
- Application::from_glib_borrow(this).unsafe_cast_ref(),
- &from_glib_borrow(command_line),
- )
- }
- unsafe {
- let f: Box_ = Box_::new(f);
- connect_raw(
- self.as_ptr() as *mut _,
- c"command-line".as_ptr() as *const _,
- Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
- command_line_trampoline:: as *const (),
- )),
- Box_::into_raw(f),
- )
- }
- }
-
- #[doc(alias = "handle-local-options")]
- fn connect_handle_local_options i32 + 'static>(
- &self,
- f: F,
- ) -> SignalHandlerId {
- unsafe extern "C" fn handle_local_options_trampoline<
- P: IsA,
- F: Fn(&P, &glib::VariantDict) -> i32 + 'static,
- >(
- this: *mut ffi::GApplication,
- options: *mut glib::ffi::GVariantDict,
- f: glib::ffi::gpointer,
- ) -> std::ffi::c_int {
- let f: &F = &*(f as *const F);
- f(
- Application::from_glib_borrow(this).unsafe_cast_ref(),
- &from_glib_borrow(options),
- )
- }
- unsafe {
- let f: Box_ = Box_::new(f);
- connect_raw(
- self.as_ptr() as *mut _,
- c"handle-local-options".as_ptr() as *const _,
- Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
- handle_local_options_trampoline:: as *const (),
- )),
- Box_::into_raw(f),
- )
- }
- }
-
#[cfg(feature = "v2_60")]
#[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
#[doc(alias = "name-lost")]
diff --git a/gio/src/subclass/application.rs b/gio/src/subclass/application.rs
index 559233edc434..40e0c6752894 100644
--- a/gio/src/subclass/application.rs
+++ b/gio/src/subclass/application.rs
@@ -1,6 +1,11 @@
// Take a look at the license at the top of the repository in the LICENSE file.
-use std::{ffi::OsString, fmt, ops::Deref, ptr};
+use std::{
+ ffi::OsString,
+ fmt,
+ ops::{ControlFlow, Deref},
+ ptr,
+};
use glib::{
prelude::*, subclass::prelude::*, translate::*, Error, ExitCode, Propagation, VariantDict,
@@ -85,7 +90,7 @@ pub trait ApplicationImpl:
self.parent_command_line(command_line)
}
- fn local_command_line(&self, arguments: &mut ArgumentList) -> Option {
+ fn local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow {
self.parent_local_command_line(arguments)
}
@@ -109,7 +114,7 @@ pub trait ApplicationImpl:
self.parent_startup()
}
- fn handle_local_options(&self, options: &VariantDict) -> ExitCode {
+ fn handle_local_options(&self, options: &VariantDict) -> ControlFlow {
self.parent_handle_local_options(options)
}
@@ -177,11 +182,12 @@ pub trait ApplicationImplExt: ApplicationImpl {
self.obj().unsafe_cast_ref::().to_glib_none().0,
command_line.to_glib_none().0,
)
- .into()
+ .try_into()
+ .unwrap()
}
}
- fn parent_local_command_line(&self, arguments: &mut ArgumentList) -> Option {
+ fn parent_local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GApplicationClass;
@@ -198,8 +204,8 @@ pub trait ApplicationImplExt: ApplicationImpl {
arguments.refresh();
match res {
- glib::ffi::GFALSE => None,
- _ => Some(exit_status.into()),
+ glib::ffi::GFALSE => ControlFlow::Continue(()),
+ _ => ControlFlow::Break(exit_status.try_into().unwrap()),
}
}
}
@@ -264,19 +270,22 @@ pub trait ApplicationImplExt: ApplicationImpl {
}
}
- fn parent_handle_local_options(&self, options: &VariantDict) -> ExitCode {
+ fn parent_handle_local_options(&self, options: &VariantDict) -> ControlFlow {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GApplicationClass;
if let Some(f) = (*parent_class).handle_local_options {
- f(
+ let ret = f(
self.obj().unsafe_cast_ref::().to_glib_none().0,
options.to_glib_none().0,
- )
- .into()
+ );
+
+ match ret {
+ -1 => ControlFlow::Continue(()),
+ _ => ControlFlow::Break(ret.try_into().unwrap()),
+ }
} else {
- // Continue default handling
- ExitCode::from(-1)
+ ControlFlow::Continue(())
}
}
}
@@ -406,15 +415,15 @@ unsafe extern "C" fn application_local_command_line(
let imp = instance.imp();
let mut args = ArgumentList::new(arguments);
- let res = imp.local_command_line(&mut args).map(i32::from);
+ let res = imp.local_command_line(&mut args);
args.refresh();
match res {
- Some(ret) => {
- *exit_status = ret;
+ ControlFlow::Break(ret) => {
+ *exit_status = ret.into();
glib::ffi::GTRUE
}
- None => glib::ffi::GFALSE,
+ ControlFlow::Continue(()) => glib::ffi::GFALSE,
}
}
unsafe extern "C" fn application_open(
@@ -461,7 +470,10 @@ unsafe extern "C" fn application_handle_local_options(
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
- imp.handle_local_options(&from_glib_borrow(options)).into()
+ imp.handle_local_options(&from_glib_borrow(options))
+ .break_value()
+ .map(i32::from)
+ .unwrap_or(-1)
}
unsafe extern "C" fn application_dbus_register(
@@ -513,7 +525,7 @@ mod tests {
use super::*;
use crate::prelude::*;
- const EXIT_STATUS: i32 = 20;
+ const EXIT_STATUS: u8 = 20;
mod imp {
use super::*;
@@ -545,7 +557,7 @@ mod tests {
EXIT_STATUS.into()
}
- fn local_command_line(&self, arguments: &mut ArgumentList) -> Option {
+ fn local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow {
let mut rm = Vec::new();
for (i, line) in arguments.iter().enumerate() {
@@ -562,7 +574,7 @@ mod tests {
arguments.remove(*i);
}
- None
+ ControlFlow::Continue(())
}
}
}
diff --git a/glib-build-tools/README.md b/glib-build-tools/README.md
index 6fcf89e0610a..bf8f20dfdd60 100644
--- a/glib-build-tools/README.md
+++ b/glib-build-tools/README.md
@@ -4,7 +4,7 @@ Crate containing helpers for building GIO-based applications.
## Minimum supported Rust version
-Currently, the minimum supported Rust version is `1.80.0`.
+Currently, the minimum supported Rust version is `1.83.0`.
## Documentation
diff --git a/glib/README.md b/glib/README.md
index 8f611427cf6e..0f2d4cbd627b 100644
--- a/glib/README.md
+++ b/glib/README.md
@@ -16,7 +16,7 @@ crates.
## Minimum supported Rust version
-Currently, the minimum supported Rust version is `1.80.0`.
+Currently, the minimum supported Rust version is `1.83.0`.
## Dynamic typing
diff --git a/glib/src/exit_code.rs b/glib/src/exit_code.rs
index 4a275c9263be..6202b6cafc06 100644
--- a/glib/src/exit_code.rs
+++ b/glib/src/exit_code.rs
@@ -1,33 +1,87 @@
// Take a look at the license at the top of the repository in the LICENSE file.
-use std::process::Termination;
-
#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)]
-pub struct ExitCode(i32);
+pub struct ExitCode(u8);
impl ExitCode {
- pub const SUCCESS: Self = Self(0);
- pub const FAILURE: Self = Self(1);
+ const MIN: i32 = u8::MIN as i32;
+ const MAX: i32 = u8::MAX as i32;
+
+ // rustdoc-stripper-ignore-next
+ /// The canonical ExitCode for successful termination on this platform.
+ pub const SUCCESS: Self = Self(libc::EXIT_SUCCESS as u8);
+
+ // rustdoc-stripper-ignore-next
+ /// The canonical ExitCode for unsuccessful termination on this platform.
+ pub const FAILURE: Self = Self(libc::EXIT_FAILURE as u8);
- pub fn value(&self) -> i32 {
+ pub const fn new(code: u8) -> Self {
+ Self(code)
+ }
+
+ pub const fn get(&self) -> u8 {
self.0
}
}
-impl From for ExitCode {
- fn from(value: i32) -> Self {
+#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)]
+pub struct InvalidExitCode(i32);
+
+impl InvalidExitCode {
+ pub const fn new(code: i32) -> Option {
+ match code {
+ ExitCode::MIN..=ExitCode::MAX => None,
+ _ => Some(Self(code)),
+ }
+ }
+
+ pub const fn get(&self) -> i32 {
+ self.0
+ }
+}
+
+impl std::fmt::Display for InvalidExitCode {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let Self(code) = self;
+ write!(f, "{code} is not a valid glib exit code")
+ }
+}
+
+impl std::error::Error for InvalidExitCode {}
+
+impl From for ExitCode {
+ fn from(value: u8) -> Self {
Self(value)
}
}
-impl From for i32 {
- fn from(value: ExitCode) -> Self {
- value.0
+impl TryFrom for ExitCode {
+ type Error = InvalidExitCode;
+
+ fn try_from(code: i32) -> Result {
+ match code {
+ ExitCode::MIN..=ExitCode::MAX => Ok(Self(code as _)),
+ _ => Err(InvalidExitCode(code)),
+ }
}
}
-impl Termination for ExitCode {
+macro_rules! impl_from_exit_code_0 {
+ ($($ty:ty)*) => {
+ $(
+ impl From for $ty {
+ fn from(code: ExitCode) -> Self {
+ <$ty>::from(code.0)
+ }
+ }
+ )*
+ };
+}
+
+impl_from_exit_code_0! { u8 u16 u32 u64 i16 i32 i64 std::process::ExitCode }
+
+impl std::process::Termination for ExitCode {
fn report(self) -> std::process::ExitCode {
- std::process::ExitCode::from(self.0 as u8)
+ self.into()
}
}
diff --git a/glib/src/lib.rs b/glib/src/lib.rs
index a4ed600ef0f1..827c49b3fd59 100644
--- a/glib/src/lib.rs
+++ b/glib/src/lib.rs
@@ -117,7 +117,7 @@ pub mod object;
mod boxed_any_object;
pub use boxed_any_object::BoxedAnyObject;
mod exit_code;
-pub use exit_code::ExitCode;
+pub use exit_code::{ExitCode, InvalidExitCode};
pub mod collections;
pub use collections::{List, PtrSlice, SList, Slice, StrV};
diff --git a/graphene/README.md b/graphene/README.md
index c6b75fe51f41..f310ab1c1d15 100644
--- a/graphene/README.md
+++ b/graphene/README.md
@@ -6,7 +6,7 @@ Graphene __1.10__ is the lowest supported version for the underlying library.
## Minimum supported Rust version
-Currently, the minimum supported Rust version is `1.80.0`.
+Currently, the minimum supported Rust version is `1.83.0`.
## Documentation
diff --git a/pango/README.md b/pango/README.md
index bbcec65d65c7..20cca3a6d30d 100644
--- a/pango/README.md
+++ b/pango/README.md
@@ -6,7 +6,7 @@ Pango __1.40__ is the lowest supported version for the underlying library.
## Minimum supported Rust version
-Currently, the minimum supported Rust version is `1.80.0`.
+Currently, the minimum supported Rust version is `1.83.0`.
## Documentation
diff --git a/pangocairo/README.md b/pangocairo/README.md
index 7c2d66a17d70..3f6124cae4ac 100644
--- a/pangocairo/README.md
+++ b/pangocairo/README.md
@@ -7,7 +7,7 @@ PangoCairo __1.40__ is the lowest supported version for the underlying library.
## Minimum supported Rust version
-Currently, the minimum supported Rust version is `1.80.0`.
+Currently, the minimum supported Rust version is `1.83.0`.
## Documentation
diff --git a/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml b/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml
index d3030c357c77..524c25c4abf0 100644
--- a/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml
+++ b/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml
@@ -6,7 +6,7 @@ description = "crate that depends on a glib-rs dependent crate for validation of
keywords = ["gtk-rs-core", "integration"]
license = "MIT/Apache-2.0"
edition = "2021"
-rust-version = "1.80"
+rust-version = "1.83"
[dependencies]
# Use `gstreamer` as a simulation of an identified crate re-exporting `glib`.
diff --git a/tests/two-levels-glib-dependent/gstreamer/Cargo.toml b/tests/two-levels-glib-dependent/gstreamer/Cargo.toml
index 338349a8bec5..86ae3c55526a 100644
--- a/tests/two-levels-glib-dependent/gstreamer/Cargo.toml
+++ b/tests/two-levels-glib-dependent/gstreamer/Cargo.toml
@@ -7,7 +7,7 @@ description = "gstreamer simulator as a glib dependent crate for validation of g
keywords = ["gtk-rs-core", "integration"]
license = "MIT/Apache-2.0"
edition = "2021"
-rust-version = "1.80"
+rust-version = "1.83"
[dependencies]
glib = { path = "../../../glib" }
diff --git a/tests/two-levels-glib-dependent/gtk/Cargo.toml b/tests/two-levels-glib-dependent/gtk/Cargo.toml
index ed0cf601795e..d57b6469c936 100644
--- a/tests/two-levels-glib-dependent/gtk/Cargo.toml
+++ b/tests/two-levels-glib-dependent/gtk/Cargo.toml
@@ -7,7 +7,7 @@ description = "gtk simulator as a glib dependent crate for validation of glib re
keywords = ["gtk-rs-core", "integration"]
license = "MIT/Apache-2.0"
edition = "2021"
-rust-version = "1.80"
+rust-version = "1.83"
[dependencies]
glib = { path = "../../../glib" }
From 218ed478de31614205b8af0790461d43ce4c122b Mon Sep 17 00:00:00 2001
From: Philipp Jungkamp
Date: Tue, 8 Apr 2025 12:42:10 +0200
Subject: [PATCH 2/2] Replace `map_or` with `is_none_or` to satisfy clippy
---
gio/src/gio_future.rs | 2 +-
glib/src/source_futures.rs | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gio/src/gio_future.rs b/gio/src/gio_future.rs
index 7560e3a5b20a..114c7dd3e94d 100644
--- a/gio/src/gio_future.rs
+++ b/gio/src/gio_future.rs
@@ -115,7 +115,7 @@ where
&& self
.receiver
.as_ref()
- .map_or(true, |receiver| receiver.is_terminated())
+ .is_none_or(|receiver| receiver.is_terminated())
}
}
diff --git a/glib/src/source_futures.rs b/glib/src/source_futures.rs
index c3140fd28a1d..dd719d84be6e 100644
--- a/glib/src/source_futures.rs
+++ b/glib/src/source_futures.rs
@@ -101,7 +101,7 @@ where
&& self
.source
.as_ref()
- .map_or(true, |(_, receiver)| receiver.is_terminated())
+ .is_none_or(|(_, receiver)| receiver.is_terminated())
}
}
@@ -313,7 +313,7 @@ where
&& self
.source
.as_ref()
- .map_or(true, |(_, receiver)| receiver.is_terminated())
+ .is_none_or(|(_, receiver)| receiver.is_terminated())
}
}