Skip to content

Commit 475f44e

Browse files
committed
glib: add more From implementations for GString
1 parent 95533de commit 475f44e

File tree

1 file changed

+120
-16
lines changed

1 file changed

+120
-16
lines changed

glib/src/gstring.rs

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ use crate::translate::*;
44
use crate::types::{StaticType, Type};
55
use crate::value::{FromValue, ToValue};
66
use crate::Value;
7-
use std::borrow::Borrow;
7+
use std::borrow::{Borrow, Cow};
88
use std::cmp::Ordering;
9-
use std::ffi::{CStr, CString, OsStr};
9+
use std::ffi::{CStr, CString, OsStr, OsString};
1010
use std::fmt;
1111
use std::hash;
1212
use std::mem;
1313
use std::ops::Deref;
1414
use std::os::raw::{c_char, c_void};
15-
use std::path::Path;
15+
use std::path::{Path, PathBuf};
1616
use std::ptr;
1717
use std::slice;
1818
use std::string::String;
@@ -327,6 +327,13 @@ impl<'a> TryFrom<&'a CStr> for &'a GStr {
327327
}
328328
}
329329

330+
impl<'a> From<&'a GStr> for Cow<'a, GStr> {
331+
#[inline]
332+
fn from(s: &'a GStr) -> Self {
333+
Cow::Borrowed(s)
334+
}
335+
}
336+
330337
impl PartialEq<GStr> for String {
331338
fn eq(&self, other: &GStr) -> bool {
332339
self.as_str() == other.as_str()
@@ -1231,6 +1238,42 @@ impl From<GString> for Box<str> {
12311238
}
12321239
}
12331240

1241+
impl From<GString> for Vec<u8> {
1242+
#[inline]
1243+
fn from(value: GString) -> Vec<u8> {
1244+
value.into_bytes_with_nul()
1245+
}
1246+
}
1247+
1248+
impl TryFrom<GString> for CString {
1249+
type Error = GStringInteriorNulError<GString>;
1250+
#[inline]
1251+
fn try_from(value: GString) -> Result<Self, Self::Error> {
1252+
if let Some(nul_pos) = memchr::memchr(0, value.as_bytes()) {
1253+
return Err(GStringInteriorNulError(
1254+
value,
1255+
GStrInteriorNulError(nul_pos),
1256+
));
1257+
}
1258+
let v = value.into_bytes_with_nul();
1259+
Ok(unsafe { CString::from_vec_with_nul_unchecked(v) })
1260+
}
1261+
}
1262+
1263+
impl From<GString> for OsString {
1264+
#[inline]
1265+
fn from(s: GString) -> Self {
1266+
OsString::from(String::from(s))
1267+
}
1268+
}
1269+
1270+
impl From<GString> for PathBuf {
1271+
#[inline]
1272+
fn from(s: GString) -> Self {
1273+
PathBuf::from(OsString::from(s))
1274+
}
1275+
}
1276+
12341277
impl From<String> for GString {
12351278
#[inline]
12361279
fn from(mut s: String) -> Self {
@@ -1257,6 +1300,16 @@ impl From<Box<str>> for GString {
12571300
}
12581301
}
12591302

1303+
impl<'a> From<Cow<'a, str>> for GString {
1304+
#[inline]
1305+
fn from(s: Cow<'a, str>) -> Self {
1306+
match s {
1307+
Cow::Borrowed(s) => Self::from(s),
1308+
Cow::Owned(s) => Self::from(s),
1309+
}
1310+
}
1311+
}
1312+
12601313
impl From<&GStr> for GString {
12611314
#[inline]
12621315
fn from(s: &GStr) -> GString {
@@ -1285,22 +1338,73 @@ impl From<&str> for GString {
12851338
}
12861339
}
12871340

1288-
impl From<CString> for GString {
1341+
impl TryFrom<CString> for GString {
1342+
type Error = GStringUtf8Error<CString>;
12891343
#[inline]
1290-
fn from(s: CString) -> Self {
1291-
// Moves the content of the CString
1292-
// Also check if it's valid UTF-8
1293-
let s = String::from_utf8(s.into_bytes_with_nul()).unwrap();
1294-
Self(Inner::Native(Some(s.into_boxed_str())))
1344+
fn try_from(value: CString) -> Result<Self, Self::Error> {
1345+
if value.as_bytes().is_empty() {
1346+
Ok(Self(Inner::Native(None)))
1347+
} else {
1348+
// Moves the content of the CString
1349+
// Also check if it's valid UTF-8
1350+
let s = String::from_utf8(value.into_bytes_with_nul()).map_err(|e| {
1351+
let err = e.utf8_error();
1352+
GStringUtf8Error(
1353+
unsafe { CString::from_vec_with_nul_unchecked(e.into_bytes()) },
1354+
err,
1355+
)
1356+
})?;
1357+
Ok(Self(Inner::Native(Some(s.into()))))
1358+
}
12951359
}
12961360
}
12971361

1298-
impl From<&CStr> for GString {
1362+
impl TryFrom<OsString> for GString {
1363+
type Error = GStringFromError<OsString>;
12991364
#[inline]
1300-
fn from(c: &CStr) -> Self {
1301-
// Creates a copy with the GLib allocator
1302-
// Also check if it's valid UTF-8
1303-
c.to_str().unwrap().into()
1365+
fn try_from(value: OsString) -> Result<Self, Self::Error> {
1366+
Self::from_string_checked(value.into_string().map_err(GStringFromError::Unspecified)?)
1367+
.map_err(|e| GStringFromError::from(e).convert(OsString::from))
1368+
}
1369+
}
1370+
1371+
impl TryFrom<PathBuf> for GString {
1372+
type Error = GStringFromError<PathBuf>;
1373+
#[inline]
1374+
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
1375+
GString::try_from(value.into_os_string()).map_err(|e| e.convert(PathBuf::from))
1376+
}
1377+
}
1378+
1379+
impl TryFrom<&CStr> for GString {
1380+
type Error = std::str::Utf8Error;
1381+
#[inline]
1382+
fn try_from(value: &CStr) -> Result<Self, Self::Error> {
1383+
// Check if it's valid UTF-8
1384+
value.to_str()?;
1385+
let gstr = unsafe { GStr::from_utf8_with_nul_unchecked(value.to_bytes_with_nul()) };
1386+
Ok(gstr.to_owned())
1387+
}
1388+
}
1389+
1390+
impl<'a> From<Cow<'a, GStr>> for GString {
1391+
#[inline]
1392+
fn from(s: Cow<'a, GStr>) -> Self {
1393+
s.into_owned()
1394+
}
1395+
}
1396+
1397+
impl<'a> From<GString> for Cow<'a, GStr> {
1398+
#[inline]
1399+
fn from(s: GString) -> Self {
1400+
Cow::Owned(s)
1401+
}
1402+
}
1403+
1404+
impl<'a> From<&'a GString> for Cow<'a, GStr> {
1405+
#[inline]
1406+
fn from(s: &'a GString) -> Self {
1407+
Cow::Borrowed(s.as_gstr())
13041408
}
13051409
}
13061410

@@ -1698,7 +1802,7 @@ mod tests {
16981802
#[test]
16991803
fn test_gstring_from_cstring() {
17001804
let cstr = CString::new("foo").unwrap();
1701-
let gstring = GString::from(cstr);
1805+
let gstring = GString::try_from(cstr).unwrap();
17021806
assert_eq!(gstring.as_str(), "foo");
17031807
let foo: Box<str> = gstring.into();
17041808
assert_eq!(foo.as_ref(), "foo");
@@ -1707,7 +1811,7 @@ mod tests {
17071811
#[test]
17081812
fn test_string_from_gstring_from_cstring() {
17091813
let cstr = CString::new("foo").unwrap();
1710-
let gstring = GString::from(cstr);
1814+
let gstring = GString::try_from(cstr).unwrap();
17111815
assert_eq!(gstring.as_str(), "foo");
17121816
let s = String::from(gstring);
17131817
assert_eq!(s, "foo");

0 commit comments

Comments
 (0)