Skip to content

Commit

Permalink
Implement Rc/Arc conversions for string-like types
Browse files Browse the repository at this point in the history
Provides the following conversion implementations:

* `From<`{`CString`,`&CStr`}`>` for {`Arc`,`Rc`}`<CStr>`
* `From<`{`OsString`,`&OsStr`}`>` for {`Arc`,`Rc`}`<OsStr>`
* `From<`{`PathBuf`,`&Path`}`>` for {`Arc`,`Rc`}`<Path>`
  • Loading branch information
murarth committed Nov 26, 2017
1 parent 693bb0d commit 1bbc776
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ use memchr;
use ops;
use os::raw::c_char;
use ptr;
use rc::Rc;
use slice;
use str::{self, Utf8Error};
use sync::Arc;
use sys;

/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
Expand Down Expand Up @@ -704,6 +706,42 @@ impl From<CString> for Box<CStr> {
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<CString> for Arc<CStr> {
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a CStr> for Arc<CStr> {
#[inline]
fn from(s: &CStr) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<CString> for Rc<CStr> {
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a CStr> for Rc<CStr> {
#[inline]
fn from(s: &CStr) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
}
}

#[stable(feature = "default_box_extra", since = "1.17.0")]
impl Default for Box<CStr> {
fn default() -> Box<CStr> {
Expand Down Expand Up @@ -1201,6 +1239,8 @@ mod tests {
use borrow::Cow::{Borrowed, Owned};
use hash::{Hash, Hasher};
use collections::hash_map::DefaultHasher;
use rc::Rc;
use sync::Arc;

#[test]
fn c_to_rust() {
Expand Down Expand Up @@ -1337,4 +1377,21 @@ mod tests {
let boxed = <Box<CStr>>::default();
assert_eq!(boxed.to_bytes_with_nul(), &[0]);
}

#[test]
fn into_rc() {
let orig: &[u8] = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(orig).unwrap();
let rc: Rc<CStr> = Rc::from(cstr);
let arc: Arc<CStr> = Arc::from(cstr);

assert_eq!(&*rc, cstr);
assert_eq!(&*arc, cstr);

let rc2: Rc<CStr> = Rc::from(cstr.to_owned());
let arc2: Arc<CStr> = Arc::from(cstr.to_owned());

assert_eq!(&*rc2, cstr);
assert_eq!(&*arc2, cstr);
}
}
58 changes: 58 additions & 0 deletions src/libstd/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use fmt;
use ops;
use cmp;
use hash::{Hash, Hasher};
use rc::Rc;
use sync::Arc;

use sys::os_str::{Buf, Slice};
use sys_common::{AsInner, IntoInner, FromInner};
Expand Down Expand Up @@ -592,6 +594,42 @@ impl From<OsString> for Box<OsStr> {
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<OsString> for Arc<OsStr> {
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a OsStr> for Arc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Arc<OsStr> {
let arc = s.inner.into_arc();
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<OsString> for Rc<OsStr> {
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a OsStr> for Rc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Rc<OsStr> {
let rc = s.inner.into_rc();
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
}
}

#[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box<OsStr> {
fn default() -> Box<OsStr> {
Expand Down Expand Up @@ -793,6 +831,9 @@ mod tests {
use super::*;
use sys_common::{AsInner, IntoInner};

use rc::Rc;
use sync::Arc;

#[test]
fn test_os_string_with_capacity() {
let os_string = OsString::with_capacity(0);
Expand Down Expand Up @@ -935,4 +976,21 @@ mod tests {
assert_eq!(os_str, os_string);
assert!(os_string.capacity() >= 123);
}

#[test]
fn into_rc() {
let orig = "Hello, world!";
let os_str = OsStr::new(orig);
let rc: Rc<OsStr> = Rc::from(os_str);
let arc: Arc<OsStr> = Arc::from(os_str);

assert_eq!(&*rc, os_str);
assert_eq!(&*arc, os_str);

let rc2: Rc<OsStr> = Rc::from(os_str.to_owned());
let arc2: Arc<OsStr> = Arc::from(os_str.to_owned());

assert_eq!(&*rc2, os_str);
assert_eq!(&*arc2, os_str);
}
}
58 changes: 58 additions & 0 deletions src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ use hash::{Hash, Hasher};
use io;
use iter::{self, FusedIterator};
use ops::{self, Deref};
use rc::Rc;
use sync::Arc;

use ffi::{OsStr, OsString};

Expand Down Expand Up @@ -1452,6 +1454,42 @@ impl<'a> From<PathBuf> for Cow<'a, Path> {
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<PathBuf> for Arc<Path> {
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a Path> for Arc<Path> {
#[inline]
fn from(s: &Path) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.as_os_str());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl From<PathBuf> for Rc<Path> {
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
}
}

#[stable(feature = "shared_from_slice2", since = "1.23.0")]
impl<'a> From<&'a Path> for Rc<Path> {
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for Path {
type Owned = PathBuf;
Expand Down Expand Up @@ -2568,6 +2606,9 @@ impl Error for StripPrefixError {
mod tests {
use super::*;

use rc::Rc;
use sync::Arc;

macro_rules! t(
($path:expr, iter: $iter:expr) => (
{
Expand Down Expand Up @@ -3970,4 +4011,21 @@ mod tests {
assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b");
assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b");
}

#[test]
fn into_rc() {
let orig = "hello/world";
let path = Path::new(orig);
let rc: Rc<Path> = Rc::from(path);
let arc: Arc<Path> = Arc::from(path);

assert_eq!(&*rc, path);
assert_eq!(&*arc, path);

let rc2: Rc<Path> = Rc::from(path.to_owned());
let arc2: Arc<Path> = Arc::from(path.to_owned());

assert_eq!(&*rc2, path);
assert_eq!(&*arc2, path);
}
}
24 changes: 24 additions & 0 deletions src/libstd/sys/redox/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use borrow::Cow;
use fmt;
use str;
use mem;
use rc::Rc;
use sync::Arc;
use sys_common::{AsInner, IntoInner};
use std_unicode::lossy::Utf8Lossy;

Expand Down Expand Up @@ -123,6 +125,16 @@ impl Buf {
let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
Buf { inner: inner.into_vec() }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
self.as_slice().into_arc()
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
self.as_slice().into_rc()
}
}

impl Slice {
Expand Down Expand Up @@ -156,4 +168,16 @@ impl Slice {
let boxed: Box<[u8]> = Default::default();
unsafe { mem::transmute(boxed) }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
let arc: Arc<[u8]> = Arc::from(&self.inner);
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
let rc: Rc<[u8]> = Rc::from(&self.inner);
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
}
}
24 changes: 24 additions & 0 deletions src/libstd/sys/unix/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use borrow::Cow;
use fmt;
use str;
use mem;
use rc::Rc;
use sync::Arc;
use sys_common::{AsInner, IntoInner};
use std_unicode::lossy::Utf8Lossy;

Expand Down Expand Up @@ -123,6 +125,16 @@ impl Buf {
let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
Buf { inner: inner.into_vec() }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
self.as_slice().into_arc()
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
self.as_slice().into_rc()
}
}

impl Slice {
Expand Down Expand Up @@ -156,4 +168,16 @@ impl Slice {
let boxed: Box<[u8]> = Default::default();
unsafe { mem::transmute(boxed) }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
let arc: Arc<[u8]> = Arc::from(&self.inner);
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
let rc: Rc<[u8]> = Rc::from(&self.inner);
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
}
}
24 changes: 24 additions & 0 deletions src/libstd/sys/wasm/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use borrow::Cow;
use fmt;
use str;
use mem;
use rc::Rc;
use sync::Arc;
use sys_common::{AsInner, IntoInner};
use std_unicode::lossy::Utf8Lossy;

Expand Down Expand Up @@ -123,6 +125,16 @@ impl Buf {
let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
Buf { inner: inner.into_vec() }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
self.as_slice().into_arc()
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
self.as_slice().into_rc()
}
}

impl Slice {
Expand Down Expand Up @@ -156,4 +168,16 @@ impl Slice {
let boxed: Box<[u8]> = Default::default();
unsafe { mem::transmute(boxed) }
}

#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
let arc: Arc<[u8]> = Arc::from(&self.inner);
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
}

#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
let rc: Rc<[u8]> = Rc::from(&self.inner);
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
}
}
Loading

0 comments on commit 1bbc776

Please sign in to comment.