Skip to content

Commit

Permalink
glib: Implement IntoOptionalGStr for plain string types
Browse files Browse the repository at this point in the history
This way strings can be passed to such functions without explicit
`Option` wrapping, see gtk-rs#805.
  • Loading branch information
sdroege committed Jan 13, 2023
1 parent f0b9630 commit 825e701
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 16 deletions.
4 changes: 2 additions & 2 deletions glib/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ pub fn convert_with_fallback(
str_: &[u8],
to_codeset: impl IntoGStr,
from_codeset: impl IntoGStr,
fallback: Option<impl IntoGStr>,
fallback: impl IntoOptionalGStr,
) -> Result<(Slice<u8>, usize), CvtError> {
assert!(str_.len() <= isize::MAX as usize);
let mut bytes_read = 0;
let mut bytes_written = 0;
let mut error = ptr::null_mut();
let result = to_codeset.run_with_gstr(|to_codeset| {
from_codeset.run_with_gstr(|from_codeset| {
fallback.run_with_gstr(|fallback| unsafe {
fallback.run_with_optional_gstr(|fallback| unsafe {
ffi::g_convert_with_fallback(
str_.as_ptr(),
str_.len() as isize,
Expand Down
11 changes: 9 additions & 2 deletions glib/src/gstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1993,19 +1993,26 @@ pub const NONE_STR: Option<&'static str> = None;
/// A trait to accept both <code>[Option]&lt;&[str]></code> or <code>[Option]&lt;&[GStr]></code> as
/// an argument.
pub trait IntoOptionalGStr {
fn run_with_gstr<T, F: FnOnce(Option<&GStr>) -> T>(self, f: F) -> T;
fn run_with_optional_gstr<T, F: FnOnce(Option<&GStr>) -> T>(self, f: F) -> T;
}

impl<S: IntoGStr> IntoOptionalGStr for Option<S> {
#[inline]
fn run_with_gstr<T, F: FnOnce(Option<&GStr>) -> T>(self, f: F) -> T {
fn run_with_optional_gstr<T, F: FnOnce(Option<&GStr>) -> T>(self, f: F) -> T {
match self {
Some(t) => t.run_with_gstr(|s| f(Some(s))),
None => f(None),
}
}
}

impl<S: IntoGStr> IntoOptionalGStr for S {
#[inline]
fn run_with_optional_gstr<T, F: FnOnce(Option<&GStr>) -> T>(self, f: F) -> T {
self.run_with_gstr(|s| f(Some(s)))
}
}

#[cfg(test)]
#[allow(clippy::disallowed_names)]
mod tests {
Expand Down
24 changes: 12 additions & 12 deletions glib/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ pub fn set_program_name(name: Option<impl IntoGStr>) {

#[doc(alias = "g_set_prgname")]
#[inline]
pub fn set_prgname(name: Option<impl IntoGStr>) {
name.run_with_gstr(|name| unsafe { ffi::g_set_prgname(name.to_glib_none().0) })
pub fn set_prgname(name: impl IntoOptionalGStr) {
name.run_with_optional_gstr(|name| unsafe { ffi::g_set_prgname(name.to_glib_none().0) })
}

#[doc(alias = "g_environ_getenv")]
Expand Down Expand Up @@ -135,11 +135,11 @@ pub fn is_canonical_pspec_name(name: &str) -> bool {
#[doc(alias = "g_uri_escape_string")]
pub fn uri_escape_string(
unescaped: impl IntoGStr,
reserved_chars_allowed: Option<impl IntoGStr>,
reserved_chars_allowed: impl IntoOptionalGStr,
allow_utf8: bool,
) -> crate::GString {
unescaped.run_with_gstr(|unescaped| {
reserved_chars_allowed.run_with_gstr(|reserved_chars_allowed| unsafe {
reserved_chars_allowed.run_with_optional_gstr(|reserved_chars_allowed| unsafe {
from_glib_full(ffi::g_uri_escape_string(
unescaped.to_glib_none().0,
reserved_chars_allowed.to_glib_none().0,
Expand All @@ -152,10 +152,10 @@ pub fn uri_escape_string(
#[doc(alias = "g_uri_unescape_string")]
pub fn uri_unescape_string(
escaped_string: impl IntoGStr,
illegal_characters: Option<impl IntoGStr>,
illegal_characters: impl IntoOptionalGStr,
) -> Option<crate::GString> {
escaped_string.run_with_gstr(|escaped_string| {
illegal_characters.run_with_gstr(|illegal_characters| unsafe {
illegal_characters.run_with_optional_gstr(|illegal_characters| unsafe {
from_glib_full(ffi::g_uri_unescape_string(
escaped_string.to_glib_none().0,
illegal_characters.to_glib_none().0,
Expand All @@ -173,13 +173,13 @@ pub fn uri_parse_scheme(uri: impl IntoGStr) -> Option<crate::GString> {

#[doc(alias = "g_uri_unescape_segment")]
pub fn uri_unescape_segment(
escaped_string: Option<impl IntoGStr>,
escaped_string_end: Option<impl IntoGStr>,
illegal_characters: Option<impl IntoGStr>,
escaped_string: impl IntoOptionalGStr,
escaped_string_end: impl IntoOptionalGStr,
illegal_characters: impl IntoOptionalGStr,
) -> Option<crate::GString> {
escaped_string.run_with_gstr(|escaped_string| {
escaped_string_end.run_with_gstr(|escaped_string_end| {
illegal_characters.run_with_gstr(|illegal_characters| unsafe {
escaped_string.run_with_optional_gstr(|escaped_string| {
escaped_string_end.run_with_optional_gstr(|escaped_string_end| {
illegal_characters.run_with_optional_gstr(|illegal_characters| unsafe {
from_glib_full(ffi::g_uri_unescape_segment(
escaped_string.to_glib_none().0,
escaped_string_end.to_glib_none().0,
Expand Down

0 comments on commit 825e701

Please sign in to comment.