Skip to content

Commit 5368f27

Browse files
jf2048sdroege
authored andcommitted
glib: add more From implementations for GString
1 parent 37c7b18 commit 5368f27

File tree

1 file changed

+105
-15
lines changed

1 file changed

+105
-15
lines changed

glib/src/gstring.rs

Lines changed: 105 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
use std::{
44
borrow::{Borrow, Cow},
55
cmp::Ordering,
6-
ffi::{CStr, CString, OsStr},
6+
ffi::{CStr, CString, OsStr, OsString},
77
fmt, hash,
88
marker::PhantomData,
99
mem,
1010
ops::Deref,
1111
os::raw::{c_char, c_void},
12-
path::Path,
12+
path::{Path, PathBuf},
1313
ptr, slice,
1414
};
1515

@@ -1282,6 +1282,42 @@ impl From<GString> for Box<str> {
12821282
}
12831283
}
12841284

1285+
impl From<GString> for Vec<u8> {
1286+
#[inline]
1287+
fn from(value: GString) -> Vec<u8> {
1288+
value.into_bytes_with_nul()
1289+
}
1290+
}
1291+
1292+
impl TryFrom<GString> for CString {
1293+
type Error = GStringInteriorNulError<GString>;
1294+
#[inline]
1295+
fn try_from(value: GString) -> Result<Self, Self::Error> {
1296+
if let Some(nul_pos) = memchr::memchr(0, value.as_bytes()) {
1297+
return Err(GStringInteriorNulError(
1298+
value,
1299+
GStrInteriorNulError(nul_pos),
1300+
));
1301+
}
1302+
let v = value.into_bytes_with_nul();
1303+
Ok(unsafe { CString::from_vec_with_nul_unchecked(v) })
1304+
}
1305+
}
1306+
1307+
impl From<GString> for OsString {
1308+
#[inline]
1309+
fn from(s: GString) -> Self {
1310+
OsString::from(String::from(s))
1311+
}
1312+
}
1313+
1314+
impl From<GString> for PathBuf {
1315+
#[inline]
1316+
fn from(s: GString) -> Self {
1317+
PathBuf::from(OsString::from(s))
1318+
}
1319+
}
1320+
12851321
impl From<String> for GString {
12861322
#[inline]
12871323
fn from(mut s: String) -> Self {
@@ -1308,6 +1344,16 @@ impl From<Box<str>> for GString {
13081344
}
13091345
}
13101346

1347+
impl<'a> From<Cow<'a, str>> for GString {
1348+
#[inline]
1349+
fn from(s: Cow<'a, str>) -> Self {
1350+
match s {
1351+
Cow::Borrowed(s) => Self::from(s),
1352+
Cow::Owned(s) => Self::from(s),
1353+
}
1354+
}
1355+
}
1356+
13111357
impl From<&GStr> for GString {
13121358
#[inline]
13131359
fn from(s: &GStr) -> GString {
@@ -1336,22 +1382,66 @@ impl From<&str> for GString {
13361382
}
13371383
}
13381384

1339-
impl From<CString> for GString {
1385+
impl TryFrom<CString> for GString {
1386+
type Error = GStringUtf8Error<CString>;
13401387
#[inline]
1341-
fn from(s: CString) -> Self {
1342-
// Moves the content of the CString
1343-
// Also check if it's valid UTF-8
1344-
let s = String::from_utf8(s.into_bytes_with_nul()).unwrap();
1345-
Self(Inner::Native(Some(s.into_boxed_str())))
1388+
fn try_from(value: CString) -> Result<Self, Self::Error> {
1389+
if value.as_bytes().is_empty() {
1390+
Ok(Self(Inner::Native(None)))
1391+
} else {
1392+
// Moves the content of the CString
1393+
// Also check if it's valid UTF-8
1394+
let s = String::from_utf8(value.into_bytes_with_nul()).map_err(|e| {
1395+
let err = e.utf8_error();
1396+
GStringUtf8Error(
1397+
unsafe { CString::from_vec_with_nul_unchecked(e.into_bytes()) },
1398+
err,
1399+
)
1400+
})?;
1401+
Ok(Self(Inner::Native(Some(s.into()))))
1402+
}
13461403
}
13471404
}
13481405

1349-
impl From<&CStr> for GString {
1406+
impl TryFrom<OsString> for GString {
1407+
type Error = GStringFromError<OsString>;
13501408
#[inline]
1351-
fn from(c: &CStr) -> Self {
1352-
// Creates a copy with the GLib allocator
1353-
// Also check if it's valid UTF-8
1354-
c.to_str().unwrap().into()
1409+
fn try_from(value: OsString) -> Result<Self, Self::Error> {
1410+
Self::from_string_checked(value.into_string().map_err(GStringFromError::Unspecified)?)
1411+
.map_err(|e| GStringFromError::from(e).convert(OsString::from))
1412+
}
1413+
}
1414+
1415+
impl TryFrom<PathBuf> for GString {
1416+
type Error = GStringFromError<PathBuf>;
1417+
#[inline]
1418+
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
1419+
GString::try_from(value.into_os_string()).map_err(|e| e.convert(PathBuf::from))
1420+
}
1421+
}
1422+
1423+
impl TryFrom<&CStr> for GString {
1424+
type Error = std::str::Utf8Error;
1425+
#[inline]
1426+
fn try_from(value: &CStr) -> Result<Self, Self::Error> {
1427+
// Check if it's valid UTF-8
1428+
value.to_str()?;
1429+
let gstr = unsafe { GStr::from_utf8_with_nul_unchecked(value.to_bytes_with_nul()) };
1430+
Ok(gstr.to_owned())
1431+
}
1432+
}
1433+
1434+
impl<'a> From<Cow<'a, GStr>> for GString {
1435+
#[inline]
1436+
fn from(s: Cow<'a, GStr>) -> Self {
1437+
s.into_owned()
1438+
}
1439+
}
1440+
1441+
impl<'a> From<&'a GString> for Cow<'a, GStr> {
1442+
#[inline]
1443+
fn from(s: &'a GString) -> Self {
1444+
Cow::Borrowed(s.as_gstr())
13551445
}
13561446
}
13571447

@@ -1793,7 +1883,7 @@ mod tests {
17931883
#[test]
17941884
fn test_gstring_from_cstring() {
17951885
let cstr = CString::new("foo").unwrap();
1796-
let gstring = GString::from(cstr);
1886+
let gstring = GString::try_from(cstr).unwrap();
17971887
assert_eq!(gstring.as_str(), "foo");
17981888
let foo: Box<str> = gstring.into();
17991889
assert_eq!(foo.as_ref(), "foo");
@@ -1802,7 +1892,7 @@ mod tests {
18021892
#[test]
18031893
fn test_string_from_gstring_from_cstring() {
18041894
let cstr = CString::new("foo").unwrap();
1805-
let gstring = GString::from(cstr);
1895+
let gstring = GString::try_from(cstr).unwrap();
18061896
assert_eq!(gstring.as_str(), "foo");
18071897
let s = String::from(gstring);
18081898
assert_eq!(s, "foo");

0 commit comments

Comments
 (0)