Skip to content

Commit 1cbddef

Browse files
committed
glib: add more From implementations for GString
1 parent 5a367f0 commit 1cbddef

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,11 +3,11 @@
33
use std::{
44
borrow::{Borrow, Cow},
55
cmp::Ordering,
6-
ffi::{CStr, CString, OsStr},
6+
ffi::{CStr, CString, OsStr, OsString},
77
fmt, hash, mem,
88
ops::Deref,
99
os::raw::{c_char, c_void},
10-
path::Path,
10+
path::{Path, PathBuf},
1111
ptr, slice,
1212
};
1313

@@ -1274,6 +1274,42 @@ impl From<GString> for Box<str> {
12741274
}
12751275
}
12761276

1277+
impl From<GString> for Vec<u8> {
1278+
#[inline]
1279+
fn from(value: GString) -> Vec<u8> {
1280+
value.into_bytes_with_nul()
1281+
}
1282+
}
1283+
1284+
impl TryFrom<GString> for CString {
1285+
type Error = GStringInteriorNulError<GString>;
1286+
#[inline]
1287+
fn try_from(value: GString) -> Result<Self, Self::Error> {
1288+
if let Some(nul_pos) = memchr::memchr(0, value.as_bytes()) {
1289+
return Err(GStringInteriorNulError(
1290+
value,
1291+
GStrInteriorNulError(nul_pos),
1292+
));
1293+
}
1294+
let v = value.into_bytes_with_nul();
1295+
Ok(unsafe { CString::from_vec_with_nul_unchecked(v) })
1296+
}
1297+
}
1298+
1299+
impl From<GString> for OsString {
1300+
#[inline]
1301+
fn from(s: GString) -> Self {
1302+
OsString::from(String::from(s))
1303+
}
1304+
}
1305+
1306+
impl From<GString> for PathBuf {
1307+
#[inline]
1308+
fn from(s: GString) -> Self {
1309+
PathBuf::from(OsString::from(s))
1310+
}
1311+
}
1312+
12771313
impl From<String> for GString {
12781314
#[inline]
12791315
fn from(mut s: String) -> Self {
@@ -1300,6 +1336,16 @@ impl From<Box<str>> for GString {
13001336
}
13011337
}
13021338

1339+
impl<'a> From<Cow<'a, str>> for GString {
1340+
#[inline]
1341+
fn from(s: Cow<'a, str>) -> Self {
1342+
match s {
1343+
Cow::Borrowed(s) => Self::from(s),
1344+
Cow::Owned(s) => Self::from(s),
1345+
}
1346+
}
1347+
}
1348+
13031349
impl From<&GStr> for GString {
13041350
#[inline]
13051351
fn from(s: &GStr) -> GString {
@@ -1328,22 +1374,66 @@ impl From<&str> for GString {
13281374
}
13291375
}
13301376

1331-
impl From<CString> for GString {
1377+
impl TryFrom<CString> for GString {
1378+
type Error = GStringUtf8Error<CString>;
13321379
#[inline]
1333-
fn from(s: CString) -> Self {
1334-
// Moves the content of the CString
1335-
// Also check if it's valid UTF-8
1336-
let s = String::from_utf8(s.into_bytes_with_nul()).unwrap();
1337-
Self(Inner::Native(Some(s.into_boxed_str())))
1380+
fn try_from(value: CString) -> Result<Self, Self::Error> {
1381+
if value.as_bytes().is_empty() {
1382+
Ok(Self(Inner::Native(None)))
1383+
} else {
1384+
// Moves the content of the CString
1385+
// Also check if it's valid UTF-8
1386+
let s = String::from_utf8(value.into_bytes_with_nul()).map_err(|e| {
1387+
let err = e.utf8_error();
1388+
GStringUtf8Error(
1389+
unsafe { CString::from_vec_with_nul_unchecked(e.into_bytes()) },
1390+
err,
1391+
)
1392+
})?;
1393+
Ok(Self(Inner::Native(Some(s.into()))))
1394+
}
13381395
}
13391396
}
13401397

1341-
impl From<&CStr> for GString {
1398+
impl TryFrom<OsString> for GString {
1399+
type Error = GStringFromError<OsString>;
13421400
#[inline]
1343-
fn from(c: &CStr) -> Self {
1344-
// Creates a copy with the GLib allocator
1345-
// Also check if it's valid UTF-8
1346-
c.to_str().unwrap().into()
1401+
fn try_from(value: OsString) -> Result<Self, Self::Error> {
1402+
Self::from_string_checked(value.into_string().map_err(GStringFromError::Unspecified)?)
1403+
.map_err(|e| GStringFromError::from(e).convert(OsString::from))
1404+
}
1405+
}
1406+
1407+
impl TryFrom<PathBuf> for GString {
1408+
type Error = GStringFromError<PathBuf>;
1409+
#[inline]
1410+
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
1411+
GString::try_from(value.into_os_string()).map_err(|e| e.convert(PathBuf::from))
1412+
}
1413+
}
1414+
1415+
impl TryFrom<&CStr> for GString {
1416+
type Error = std::str::Utf8Error;
1417+
#[inline]
1418+
fn try_from(value: &CStr) -> Result<Self, Self::Error> {
1419+
// Check if it's valid UTF-8
1420+
value.to_str()?;
1421+
let gstr = unsafe { GStr::from_utf8_with_nul_unchecked(value.to_bytes_with_nul()) };
1422+
Ok(gstr.to_owned())
1423+
}
1424+
}
1425+
1426+
impl<'a> From<Cow<'a, GStr>> for GString {
1427+
#[inline]
1428+
fn from(s: Cow<'a, GStr>) -> Self {
1429+
s.into_owned()
1430+
}
1431+
}
1432+
1433+
impl<'a> From<&'a GString> for Cow<'a, GStr> {
1434+
#[inline]
1435+
fn from(s: &'a GString) -> Self {
1436+
Cow::Borrowed(s.as_gstr())
13471437
}
13481438
}
13491439

@@ -1785,7 +1875,7 @@ mod tests {
17851875
#[test]
17861876
fn test_gstring_from_cstring() {
17871877
let cstr = CString::new("foo").unwrap();
1788-
let gstring = GString::from(cstr);
1878+
let gstring = GString::try_from(cstr).unwrap();
17891879
assert_eq!(gstring.as_str(), "foo");
17901880
let foo: Box<str> = gstring.into();
17911881
assert_eq!(foo.as_ref(), "foo");
@@ -1794,7 +1884,7 @@ mod tests {
17941884
#[test]
17951885
fn test_string_from_gstring_from_cstring() {
17961886
let cstr = CString::new("foo").unwrap();
1797-
let gstring = GString::from(cstr);
1887+
let gstring = GString::try_from(cstr).unwrap();
17981888
assert_eq!(gstring.as_str(), "foo");
17991889
let s = String::from(gstring);
18001890
assert_eq!(s, "foo");

0 commit comments

Comments
 (0)