]> git.lizzy.rs Git - rust.git/commitdiff
Implement `Rc`/`Arc` conversions for string-like types
authorMurarth <murarth@gmail.com>
Tue, 14 Nov 2017 19:31:07 +0000 (12:31 -0700)
committerMurarth <murarth@gmail.com>
Sun, 26 Nov 2017 05:13:11 +0000 (22:13 -0700)
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>`

src/libstd/ffi/c_str.rs
src/libstd/ffi/os_str.rs
src/libstd/path.rs
src/libstd/sys/redox/os_str.rs
src/libstd/sys/unix/os_str.rs
src/libstd/sys/wasm/os_str.rs
src/libstd/sys/windows/os_str.rs
src/libstd/sys_common/wtf8.rs

index 1aa47f066b69fc7f7177f929eaee2dc93933b3c5..a2022a2eeb23c3d8fc086d4e44419bb5e8aafc80 100644 (file)
 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
@@ -704,6 +706,42 @@ fn from(s: CString) -> 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> {
@@ -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() {
@@ -1337,4 +1377,21 @@ fn boxed_default() {
         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);
+    }
 }
index 8c34660f821b71b45c20406adf5a4f7a47c1994d..cb902461f39fd1b148c1b3e7ad4a08f51998ff4d 100644 (file)
@@ -13,6 +13,8 @@
 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};
@@ -592,6 +594,42 @@ fn from(s: OsString) -> 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> {
@@ -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);
@@ -935,4 +976,21 @@ fn test_os_str_clone_into() {
         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);
+    }
 }
index 4e35cf840de96434d6e1ec3512258836627e31b2..eb125a4737a1ca0dd614b677a5a5a49a7a075fc4 100644 (file)
@@ -86,6 +86,8 @@
 use io;
 use iter::{self, FusedIterator};
 use ops::{self, Deref};
+use rc::Rc;
+use sync::Arc;
 
 use ffi::{OsStr, OsString};
 
@@ -1452,6 +1454,42 @@ fn from(s: PathBuf) -> 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;
@@ -2568,6 +2606,9 @@ fn description(&self) -> &str { "prefix not found" }
 mod tests {
     use super::*;
 
+    use rc::Rc;
+    use sync::Arc;
+
     macro_rules! t(
         ($path:expr, iter: $iter:expr) => (
             {
@@ -3970,4 +4011,21 @@ fn display_format_flags() {
         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);
+    }
 }
index c54286353a92f9c9b60ac3656993e5b1e8455f7b..5c40d42fa0a44d282a57ac5e2906281d64193e80 100644 (file)
@@ -15,6 +15,8 @@
 use fmt;
 use str;
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use std_unicode::lossy::Utf8Lossy;
 
@@ -123,6 +125,16 @@ pub fn from_box(boxed: Box<Slice>) -> 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 {
@@ -156,4 +168,16 @@ pub fn empty_box() -> Box<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) }
+    }
 }
index 777db17e3e164d322ef4cfe649093f07ca2a287c..a27e76a0e3bccbef2a5e24e931a96326e330ea3b 100644 (file)
@@ -15,6 +15,8 @@
 use fmt;
 use str;
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use std_unicode::lossy::Utf8Lossy;
 
@@ -123,6 +125,16 @@ pub fn from_box(boxed: Box<Slice>) -> 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 {
@@ -156,4 +168,16 @@ pub fn empty_box() -> Box<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) }
+    }
 }
index c5908a7a8dc227a3ad2227311cb010e10f24865d..0e64b5bc6b8fb862682e25da862456b3ba02b271 100644 (file)
@@ -15,6 +15,8 @@
 use fmt;
 use str;
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use std_unicode::lossy::Utf8Lossy;
 
@@ -123,6 +125,16 @@ pub fn from_box(boxed: Box<Slice>) -> 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 {
@@ -156,4 +168,16 @@ pub fn empty_box() -> Box<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) }
+    }
 }
index 3eb4582718b517d9b83eda92eca5e1160b21bf41..b8d2f7bc53ce721b657bc9b2da4c574fba7e088b 100644 (file)
@@ -15,6 +15,8 @@
 use fmt;
 use sys_common::wtf8::{Wtf8, Wtf8Buf};
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 
 #[derive(Clone, Hash)]
@@ -115,6 +117,16 @@ pub fn from_box(boxed: Box<Slice>) -> Buf {
         let inner: Box<Wtf8> = unsafe { mem::transmute(boxed) };
         Buf { inner: Wtf8Buf::from_box(inner) }
     }
+
+    #[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 {
@@ -144,4 +156,16 @@ pub fn into_box(&self) -> Box<Slice> {
     pub fn empty_box() -> Box<Slice> {
         unsafe { mem::transmute(Wtf8::empty_box()) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        let arc = self.inner.into_arc();
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        let rc = self.inner.into_rc();
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+    }
 }
index b89a73cd28a090ea8aa684c4d3a51569ff6efe27..e212b5006f2d1af4a1a4aea76063bcc77cd69a81 100644 (file)
 use iter::FromIterator;
 use mem;
 use ops;
+use rc::Rc;
 use slice;
 use str;
+use sync::Arc;
 use sys_common::AsInner;
 
 const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}";
@@ -641,6 +643,18 @@ pub fn empty_box() -> Box<Wtf8> {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Wtf8> {
+        let arc: Arc<[u8]> = Arc::from(&self.bytes);
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Wtf8> {
+        let rc: Rc<[u8]> = Rc::from(&self.bytes);
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
+    }
 }