|
131 | 131 | //! ```
|
132 | 132 |
|
133 | 133 | use libc::{c_char, size_t};
|
| 134 | +use std::borrow::Cow; |
134 | 135 | use std::char;
|
135 | 136 | use std::cmp::{Eq, Ordering, PartialEq};
|
136 | 137 | use std::collections::HashMap;
|
@@ -501,72 +502,81 @@ impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
|
501 | 502 | }
|
502 | 503 |
|
503 | 504 | impl<'a> ToGlibPtr<'a, *const c_char> for str {
|
504 |
| - type Storage = CString; |
| 505 | + type Storage = Cow<'static, [u8]>; |
505 | 506 |
|
506 |
| - #[inline] |
507 | 507 | 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) |
511 | 525 | }
|
512 | 526 |
|
513 | 527 | #[inline]
|
514 | 528 | fn to_glib_full(&self) -> *const c_char {
|
| 529 | + if cfg!(debug_assertions) { |
| 530 | + crate::GStr::check_interior_nuls(self).unwrap(); |
| 531 | + } |
515 | 532 | unsafe {
|
516 | 533 | ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *const c_char
|
517 | 534 | }
|
518 | 535 | }
|
519 | 536 | }
|
520 | 537 |
|
521 | 538 | impl<'a> ToGlibPtr<'a, *mut c_char> for str {
|
522 |
| - type Storage = CString; |
| 539 | + type Storage = Cow<'static, [u8]>; |
523 | 540 |
|
524 | 541 | #[inline]
|
525 | 542 | 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) |
529 | 545 | }
|
530 | 546 |
|
531 | 547 | #[inline]
|
532 | 548 | 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 _ |
534 | 550 | }
|
535 | 551 | }
|
536 | 552 |
|
537 | 553 | impl<'a> ToGlibPtr<'a, *const c_char> for String {
|
538 |
| - type Storage = CString; |
| 554 | + type Storage = Cow<'static, [u8]>; |
539 | 555 |
|
540 | 556 | #[inline]
|
541 | 557 | 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) |
545 | 560 | }
|
546 | 561 |
|
547 | 562 | #[inline]
|
548 | 563 | 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()) |
552 | 565 | }
|
553 | 566 | }
|
554 | 567 |
|
555 | 568 | impl<'a> ToGlibPtr<'a, *mut c_char> for String {
|
556 |
| - type Storage = CString; |
| 569 | + type Storage = Cow<'static, [u8]>; |
557 | 570 |
|
558 | 571 | #[inline]
|
559 | 572 | 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) |
563 | 575 | }
|
564 | 576 |
|
565 | 577 | #[inline]
|
566 | 578 | 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()) |
570 | 580 | }
|
571 | 581 | }
|
572 | 582 |
|
|
0 commit comments