Skip to content

Commit 133a343

Browse files
committed
glib: add more From implementations for GString
1 parent 342d86d commit 133a343

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()
@@ -1232,6 +1239,42 @@ impl From<GString> for Box<str> {
12321239
}
12331240
}
12341241

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

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

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

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

@@ -1699,7 +1803,7 @@ mod tests {
16991803
#[test]
17001804
fn test_gstring_from_cstring() {
17011805
let cstr = CString::new("foo").unwrap();
1702-
let gstring = GString::from(cstr);
1806+
let gstring = GString::try_from(cstr).unwrap();
17031807
assert_eq!(gstring.as_str(), "foo");
17041808
let foo: Box<str> = gstring.into();
17051809
assert_eq!(foo.as_ref(), "foo");
@@ -1708,7 +1812,7 @@ mod tests {
17081812
#[test]
17091813
fn test_string_from_gstring_from_cstring() {
17101814
let cstr = CString::new("foo").unwrap();
1711-
let gstring = GString::from(cstr);
1815+
let gstring = GString::try_from(cstr).unwrap();
17121816
assert_eq!(gstring.as_str(), "foo");
17131817
let s = String::from(gstring);
17141818
assert_eq!(s, "foo");

0 commit comments

Comments
 (0)