Skip to content

Commit 95533de

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 01d15f9 commit 95533de

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
@@ -131,6 +131,7 @@
131131
//! ```
132132
133133
use libc::{c_char, size_t};
134+
use std::borrow::Cow;
134135
use std::char;
135136
use std::cmp::{Eq, Ordering, PartialEq};
136137
use std::collections::HashMap;
@@ -501,72 +502,81 @@ impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
501502
}
502503

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

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

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

521538
impl<'a> ToGlibPtr<'a, *mut c_char> for str {
522-
type Storage = CString;
539+
type Storage = Cow<'static, [u8]>;
523540

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

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

537553
impl<'a> ToGlibPtr<'a, *const c_char> for String {
538-
type Storage = CString;
554+
type Storage = Cow<'static, [u8]>;
539555

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

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

555568
impl<'a> ToGlibPtr<'a, *mut c_char> for String {
556-
type Storage = CString;
569+
type Storage = Cow<'static, [u8]>;
557570

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

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

0 commit comments

Comments
 (0)