Skip to content

Commit 5cbef4c

Browse files
committed
glib: Use TryFrom for GString conversions
1 parent 16a07a4 commit 5cbef4c

File tree

4 files changed

+66
-62
lines changed

4 files changed

+66
-62
lines changed

gio/src/file.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl<O: IsA<File>> FileExtManual for O {
237237
+ 'static,
238238
>,
239239
> {
240-
let etag = etag.map(glib::GString::from);
240+
let etag = etag.map(|e| glib::GString::try_from(e).unwrap());
241241
Box::pin(crate::GioFuture::new(
242242
self,
243243
move |obj, cancellable, send| {

glib/src/gstring.rs

Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl GString {
8282

8383
impl Clone for GString {
8484
fn clone(&self) -> GString {
85-
self.as_str().into()
85+
self.as_str().try_into().unwrap()
8686
}
8787
}
8888

@@ -247,70 +247,68 @@ impl From<GString> for Box<str> {
247247
}
248248
}
249249

250-
impl From<String> for GString {
250+
impl TryFrom<String> for GString {
251+
type Error = std::ffi::NulError;
251252
#[inline]
252-
fn from(s: String) -> Self {
253+
fn try_from(s: String) -> Result<Self, Self::Error> {
253254
// Moves the content of the String
254-
unsafe {
255-
// No check for valid UTF-8 here
256-
let cstr = CString::from_vec_unchecked(s.into_bytes());
257-
GString(Inner::Native(Some(cstr)))
258-
}
255+
// Check for interior nul bytes
256+
let cstr = CString::new(s.into_bytes())?;
257+
Ok(GString(Inner::Native(Some(cstr))))
259258
}
260259
}
261260

262-
impl From<Box<str>> for GString {
261+
impl TryFrom<Box<str>> for GString {
262+
type Error = std::ffi::NulError;
263263
#[inline]
264-
fn from(s: Box<str>) -> Self {
264+
fn try_from(s: Box<str>) -> Result<Self, Self::Error> {
265265
// Moves the content of the String
266-
s.into_string().into()
266+
s.into_string().try_into()
267267
}
268268
}
269269

270-
impl<'a> From<&'a str> for GString {
270+
impl TryFrom<&str> for GString {
271+
type Error = std::ffi::NulError;
271272
#[inline]
272-
fn from(s: &'a str) -> Self {
273-
// Allocates with the GLib allocator
274-
unsafe {
275-
// No check for valid UTF-8 here
276-
let copy = ffi::g_malloc(s.len() + 1) as *mut c_char;
277-
ptr::copy_nonoverlapping(s.as_ptr() as *const c_char, copy, s.len() + 1);
278-
ptr::write(copy.add(s.len()), 0);
279-
280-
GString(Inner::Foreign {
281-
ptr: ptr::NonNull::new_unchecked(copy),
282-
len: s.len(),
283-
})
284-
}
273+
fn try_from(s: &str) -> Result<Self, Self::Error> {
274+
s.to_owned().try_into()
285275
}
286276
}
287277

288-
impl From<Vec<u8>> for GString {
278+
#[derive(thiserror::Error, Debug)]
279+
pub enum GStringError {
280+
#[error("invalid UTF-8")]
281+
Utf8(#[from] std::str::Utf8Error),
282+
#[error("interior nul bytes")]
283+
Nul(#[from] std::ffi::NulError),
284+
}
285+
286+
impl TryFrom<Vec<u8>> for GString {
287+
type Error = GStringError;
289288
#[inline]
290-
fn from(s: Vec<u8>) -> Self {
289+
fn try_from(s: Vec<u8>) -> Result<Self, Self::Error> {
291290
// Moves the content of the Vec
292291
// Also check if it's valid UTF-8
293-
let cstring = CString::new(s).expect("CString::new failed");
294-
cstring.into()
292+
let cstring = CString::new(s)?;
293+
Ok(cstring.try_into()?)
295294
}
296295
}
297296

298-
impl From<CString> for GString {
299-
#[inline]
300-
fn from(s: CString) -> Self {
297+
impl TryFrom<CString> for GString {
298+
type Error = std::str::Utf8Error;
299+
fn try_from(s: CString) -> Result<Self, Self::Error> {
301300
// Moves the content of the CString
302301
// Also check if it's valid UTF-8
303-
assert!(s.to_str().is_ok());
304-
Self(Inner::Native(Some(s)))
302+
s.to_str()?;
303+
Ok(Self(Inner::Native(Some(s))))
305304
}
306305
}
307306

308-
impl<'a> From<&'a CStr> for GString {
307+
impl TryFrom<&CStr> for GString {
308+
type Error = std::str::Utf8Error;
309309
#[inline]
310-
fn from(c: &'a CStr) -> Self {
311-
// Creates a copy with the GLib allocator
312-
// Also check if it's valid UTF-8
313-
c.to_str().unwrap().into()
310+
fn try_from(c: &CStr) -> Result<Self, Self::Error> {
311+
c.to_owned().try_into()
314312
}
315313
}
316314

@@ -361,7 +359,7 @@ impl FromGlibPtrNone<*const u8> for GString {
361359
assert!(!ptr.is_null());
362360
let cstr = CStr::from_ptr(ptr as *const _);
363361
// Also check if it's valid UTF-8
364-
cstr.to_str().unwrap().into()
362+
cstr.try_into().unwrap()
365363
}
366364
}
367365

@@ -493,16 +491,16 @@ impl<'a> ToGlibPtr<'a, *mut i8> for GString {
493491
impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
494492
unsafe fn from_glib_none_num(ptr: *const i8, num: usize) -> Self {
495493
if num == 0 || ptr.is_null() {
496-
return Self::from("");
494+
return Self::try_from("").unwrap();
497495
}
498496
let slice = slice::from_raw_parts(ptr as *const u8, num);
499497
// Also check if it's valid UTF-8
500-
std::str::from_utf8(slice).unwrap().into()
498+
std::str::from_utf8(slice).unwrap().try_into().unwrap()
501499
}
502500

503501
unsafe fn from_glib_container_num(ptr: *const i8, num: usize) -> Self {
504502
if num == 0 || ptr.is_null() {
505-
return Self::from("");
503+
return Self::try_from("").unwrap();
506504
}
507505

508506
// Check if it's valid UTF-8
@@ -517,7 +515,7 @@ impl<'a> FromGlibContainer<*const c_char, *const i8> for GString {
517515

518516
unsafe fn from_glib_full_num(ptr: *const i8, num: usize) -> Self {
519517
if num == 0 || ptr.is_null() {
520-
return Self::from("");
518+
return Self::try_from("").unwrap();
521519
}
522520

523521
// Check if it's valid UTF-8
@@ -596,7 +594,7 @@ unsafe impl<'a> crate::value::FromValue<'a> for GString {
596594
type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
597595

598596
unsafe fn from_value(value: &'a crate::Value) -> Self {
599-
Self::from(<&str>::from_value(value))
597+
Self::try_from(<&str>::from_value(value)).unwrap()
600598
}
601599
}
602600

@@ -686,15 +684,15 @@ mod tests {
686684

687685
#[test]
688686
fn test_gstring_from_str() {
689-
let gstring: GString = "foo".into();
687+
let gstring: GString = "foo".try_into().unwrap();
690688
assert_eq!(gstring.as_str(), "foo");
691689
let foo: Box<str> = gstring.into();
692690
assert_eq!(foo.as_ref(), "foo");
693691
}
694692

695693
#[test]
696694
fn test_string_from_gstring() {
697-
let gstring = GString::from("foo");
695+
let gstring = GString::try_from("foo").unwrap();
698696
assert_eq!(gstring.as_str(), "foo");
699697
let s = String::from(gstring);
700698
assert_eq!(s, "foo");
@@ -703,7 +701,7 @@ mod tests {
703701
#[test]
704702
fn test_gstring_from_cstring() {
705703
let cstr = CString::new("foo").unwrap();
706-
let gstring = GString::from(cstr);
704+
let gstring = GString::try_from(cstr).unwrap();
707705
assert_eq!(gstring.as_str(), "foo");
708706
let foo: Box<str> = gstring.into();
709707
assert_eq!(foo.as_ref(), "foo");
@@ -712,7 +710,7 @@ mod tests {
712710
#[test]
713711
fn test_string_from_gstring_from_cstring() {
714712
let cstr = CString::new("foo").unwrap();
715-
let gstring = GString::from(cstr);
713+
let gstring = GString::try_from(cstr).unwrap();
716714
assert_eq!(gstring.as_str(), "foo");
717715
let s = String::from(gstring);
718716
assert_eq!(s, "foo");
@@ -721,7 +719,7 @@ mod tests {
721719
#[test]
722720
fn test_vec_u8_to_gstring() {
723721
let v: &[u8] = b"foo";
724-
let s: GString = Vec::from(v).into();
722+
let s: GString = Vec::from(v).try_into().unwrap();
725723
assert_eq!(s.as_str(), "foo");
726724
}
727725

@@ -754,11 +752,11 @@ mod tests {
754752
fn test_hashmap() {
755753
use std::collections::HashMap;
756754

757-
let gstring = GString::from("foo");
755+
let gstring = GString::try_from("foo").unwrap();
758756
assert_eq!(gstring.as_str(), "foo");
759757
let mut h: HashMap<GString, i32> = HashMap::new();
760758
h.insert(gstring, 42);
761-
let gstring: GString = "foo".into();
759+
let gstring: GString = "foo".try_into().unwrap();
762760
assert!(h.contains_key(&gstring));
763761
}
764762
}

glib/src/utils.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,18 @@ mod tests {
336336
fn test_filename_from_uri() {
337337
use crate::GString;
338338
use std::path::PathBuf;
339-
let uri: GString = "file:///foo/bar.txt".into();
339+
let uri: GString = "file:///foo/bar.txt".try_into().unwrap();
340340
if let Ok((filename, hostname)) = crate::filename_from_uri(&uri) {
341341
assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
342342
assert_eq!(hostname, None);
343343
} else {
344344
unreachable!();
345345
}
346346

347-
let uri: GString = "file://host/foo/bar.txt".into();
347+
let uri: GString = "file://host/foo/bar.txt".try_into().unwrap();
348348
if let Ok((filename, hostname)) = crate::filename_from_uri(&uri) {
349349
assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
350-
assert_eq!(hostname, Some(GString::from("host")));
350+
assert_eq!(hostname, Some(GString::try_from("host").unwrap()));
351351
} else {
352352
unreachable!();
353353
}
@@ -358,19 +358,19 @@ mod tests {
358358
use crate::GString;
359359
assert_eq!(
360360
crate::uri_parse_scheme("foo://bar"),
361-
Some(GString::from("foo"))
361+
Some(GString::try_from("foo").unwrap())
362362
);
363363
assert_eq!(crate::uri_parse_scheme("foo"), None);
364364

365365
let escaped = crate::uri_escape_string("&foo", None, true);
366-
assert_eq!(escaped, GString::from("%26foo"));
366+
assert_eq!(escaped, GString::try_from("%26foo").unwrap());
367367

368368
let unescaped = crate::uri_unescape_string(escaped.as_str(), None);
369-
assert_eq!(unescaped, Some(GString::from("&foo")));
369+
assert_eq!(unescaped, Some(GString::try_from("&foo").unwrap()));
370370

371371
assert_eq!(
372372
crate::uri_unescape_segment(Some("/foo"), None, None),
373-
Some(GString::from("/foo"))
373+
Some(GString::try_from("/foo").unwrap())
374374
);
375375
assert_eq!(crate::uri_unescape_segment(Some("/foo%"), None, None), None);
376376
}

glib/src/value.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,13 +1152,19 @@ mod tests {
11521152
let v = vec!["123", "456"].to_value();
11531153
assert_eq!(
11541154
v.get::<Vec<GString>>(),
1155-
Ok(vec![GString::from("123"), GString::from("456")])
1155+
Ok(vec![
1156+
GString::try_from("123").unwrap(),
1157+
GString::try_from("456").unwrap()
1158+
])
11561159
);
11571160

11581161
let v = vec![String::from("123"), String::from("456")].to_value();
11591162
assert_eq!(
11601163
v.get::<Vec<GString>>(),
1161-
Ok(vec![GString::from("123"), GString::from("456")])
1164+
Ok(vec![
1165+
GString::try_from("123").unwrap(),
1166+
GString::try_from("456").unwrap()
1167+
])
11621168
);
11631169
}
11641170

0 commit comments

Comments
 (0)