Skip to content

Commit 5a367f0

Browse files
committed
glib: have ToGlibPtr check interior string nuls in debug mode
Also use Cow<[u8]> as storage to optimize out empty string allocations.
1 parent 9299356 commit 5a367f0

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

glib/src/translate.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
#[cfg(not(windows))]
134134
use std::os::unix::prelude::*;
135135
use std::{
136+
borrow::Cow,
136137
char,
137138
cmp::{Eq, Ordering, PartialEq},
138139
collections::HashMap,
@@ -502,72 +503,81 @@ impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
502503
}
503504

504505
impl<'a> ToGlibPtr<'a, *const c_char> for str {
505-
type Storage = CString;
506+
type Storage = Cow<'static, [u8]>;
506507

507-
#[inline]
508508
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
509-
let tmp =
510-
CString::new(self).expect("str::ToGlibPtr<*const c_char>: unexpected '\0' character");
511-
Stash(tmp.as_ptr(), tmp)
509+
static EMPTY_STRING: &[u8] = &[0];
510+
511+
let bytes = if self.is_empty() {
512+
Cow::Borrowed(EMPTY_STRING)
513+
} else {
514+
if cfg!(debug_assertions) {
515+
crate::GStr::check_interior_nuls(self).unwrap();
516+
}
517+
let mut bytes = Vec::with_capacity(self.len() + 1);
518+
unsafe {
519+
ptr::copy_nonoverlapping(self.as_ptr(), bytes.as_mut_ptr(), self.len());
520+
bytes.as_mut_ptr().add(self.len()).write(0);
521+
bytes.set_len(self.len() + 1);
522+
}
523+
Cow::Owned(bytes)
524+
};
525+
Stash(bytes.as_ptr() as *const c_char, bytes)
512526
}
513527

514528
#[inline]
515529
fn to_glib_full(&self) -> *const c_char {
530+
if cfg!(debug_assertions) {
531+
crate::GStr::check_interior_nuls(self).unwrap();
532+
}
516533
unsafe {
517534
ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *const c_char
518535
}
519536
}
520537
}
521538

522539
impl<'a> ToGlibPtr<'a, *mut c_char> for str {
523-
type Storage = CString;
540+
type Storage = Cow<'static, [u8]>;
524541

525542
#[inline]
526543
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
527-
let tmp =
528-
CString::new(self).expect("str::ToGlibPtr<*mut c_char>: unexpected '\0' character");
529-
Stash(tmp.as_ptr() as *mut c_char, tmp)
544+
let s = ToGlibPtr::<*const c_char>::to_glib_none(self);
545+
Stash(s.0 as *mut _, s.1)
530546
}
531547

532548
#[inline]
533549
fn to_glib_full(&self) -> *mut c_char {
534-
unsafe { ffi::g_strndup(self.as_ptr() as *mut c_char, self.len() as size_t) }
550+
ToGlibPtr::<*const c_char>::to_glib_full(self) as *mut _
535551
}
536552
}
537553

538554
impl<'a> ToGlibPtr<'a, *const c_char> for String {
539-
type Storage = CString;
555+
type Storage = Cow<'static, [u8]>;
540556

541557
#[inline]
542558
fn to_glib_none(&self) -> Stash<'a, *const c_char, String> {
543-
let tmp = CString::new(&self[..])
544-
.expect("String::ToGlibPtr<*const c_char>: unexpected '\0' character");
545-
Stash(tmp.as_ptr(), tmp)
559+
let s = ToGlibPtr::to_glib_none(self.as_str());
560+
Stash(s.0, s.1)
546561
}
547562

548563
#[inline]
549564
fn to_glib_full(&self) -> *const c_char {
550-
unsafe {
551-
ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *const c_char
552-
}
565+
ToGlibPtr::to_glib_full(self.as_str())
553566
}
554567
}
555568

556569
impl<'a> ToGlibPtr<'a, *mut c_char> for String {
557-
type Storage = CString;
570+
type Storage = Cow<'static, [u8]>;
558571

559572
#[inline]
560573
fn to_glib_none(&self) -> Stash<'a, *mut c_char, String> {
561-
let tmp = CString::new(&self[..])
562-
.expect("String::ToGlibPtr<*mut c_char>: unexpected '\0' character");
563-
Stash(tmp.as_ptr() as *mut c_char, tmp)
574+
let s = ToGlibPtr::to_glib_none(self.as_str());
575+
Stash(s.0, s.1)
564576
}
565577

566578
#[inline]
567579
fn to_glib_full(&self) -> *mut c_char {
568-
unsafe {
569-
ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *mut c_char
570-
}
580+
ToGlibPtr::to_glib_full(self.as_str())
571581
}
572582
}
573583

0 commit comments

Comments
 (0)