rust/src/libcollections/borrow.rs

332 lines
9.1 KiB
Rust
Raw Normal View History

// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A module for working with borrowed data.
#![stable(feature = "rust1", since = "1.0.0")]
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{Add, AddAssign, Deref};
use fmt;
use self::Cow::*;
2015-11-16 10:54:28 -06:00
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
where B: ToOwned,
<B as ToOwned>::Owned: 'a
{
fn borrow(&self) -> &B {
&**self
}
}
2015-04-09 11:51:19 -05:00
/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
#[stable(feature = "rust1", since = "1.0.0")]
type Owned: Borrow<Self>;
2015-04-09 11:51:19 -05:00
/// Creates owned data from borrowed data, usually by cloning.
2016-04-05 07:11:08 -05:00
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let s = "a"; // &str
/// let ss = s.to_owned(); // String
///
/// let v = &[1, 2]; // slice
/// let vv = v.to_owned(); // Vec
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn to_owned(&self) -> Self::Owned;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
type Owned = T;
2015-11-23 16:23:48 -06:00
fn to_owned(&self) -> T {
self.clone()
}
}
/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
2015-04-09 11:51:19 -05:00
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
2015-04-09 11:51:19 -05:00
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
2015-02-21 18:43:11 -06:00
/// fn abs_all(input: &mut Cow<[i32]>) {
/// for i in 0..input.len() {
/// let v = input[i];
/// if v < 0 {
/// // Clones into a vector if not already owned.
/// input.to_mut()[i] = -v;
/// }
/// }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
pub enum Cow<'a, B: ?Sized + 'a>
where B: ToOwned
{
/// Borrowed data.
#[stable(feature = "rust1", since = "1.0.0")]
2016-02-19 18:08:36 -06:00
Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
/// Owned data.
#[stable(feature = "rust1", since = "1.0.0")]
Owned(
2016-02-19 18:08:36 -06:00
#[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
),
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
fn clone(&self) -> Cow<'a, B> {
match *self {
Borrowed(b) => Borrowed(b),
Owned(ref o) => {
let b: &B = o.borrow();
Owned(b.to_owned())
2015-11-23 16:23:48 -06:00
}
}
}
}
impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
2015-04-09 11:51:19 -05:00
/// Acquires a mutable reference to the owned form of the data.
///
/// Clones the data if it is not already owned.
2015-03-24 15:48:57 -05:00
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
///
/// let hello = cow.to_mut();
///
/// assert_eq!(hello, &[1, 2, 3]);
2015-03-24 15:48:57 -05:00
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
match *self {
Borrowed(borrowed) => {
*self = Owned(borrowed.to_owned());
self.to_mut()
}
2015-11-23 16:23:48 -06:00
Owned(ref mut owned) => owned,
}
}
2015-04-09 11:51:19 -05:00
/// Extracts the owned data.
///
/// Clones the data if it is not already owned.
2015-03-24 15:48:57 -05:00
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
///
/// let hello = cow.into_owned();
///
/// assert_eq!(vec![1, 2, 3], hello);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_owned(self) -> <B as ToOwned>::Owned {
match self {
Borrowed(borrowed) => borrowed.to_owned(),
2015-11-23 16:23:48 -06:00
Owned(owned) => owned,
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
type Target = B;
fn deref(&self) -> &B {
match *self {
Borrowed(borrowed) => borrowed,
2015-11-23 16:23:48 -06:00
Owned(ref owned) => owned.borrow(),
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
#[inline]
fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
where B: PartialEq<C> + ToOwned,
C: ToOwned
{
#[inline]
fn eq(&self, other: &Cow<'b, C>) -> bool {
PartialEq::eq(&**self, &**other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned {
#[inline]
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
where B: fmt::Debug + ToOwned,
<B as ToOwned>::Owned: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Borrowed(ref b) => fmt::Debug::fmt(b, f),
Owned(ref o) => fmt::Debug::fmt(o, f),
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
where B: fmt::Display + ToOwned,
<B as ToOwned>::Owned: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Borrowed(ref b) => fmt::Display::fmt(b, f),
Owned(ref o) => fmt::Display::fmt(o, f),
}
}
}
2016-06-16 08:44:56 -05:00
#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
where B: ToOwned,
<B as ToOwned>::Owned: Default
{
/// Creates an owned Cow<'a, B> with the default value for the contained owned value.
2016-06-16 08:44:56 -05:00
fn default() -> Cow<'a, B> {
Owned(<B as ToOwned>::Owned::default())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
2015-11-23 16:23:48 -06:00
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
std: Stabilize APIs for the 1.7 release This commit stabilizes and deprecates the FCP (final comment period) APIs for the upcoming 1.7 beta release. The specific APIs which changed were: Stabilized * `Path::strip_prefix` (renamed from `relative_from`) * `path::StripPrefixError` (new error type returned from `strip_prefix`) * `Ipv4Addr::is_loopback` * `Ipv4Addr::is_private` * `Ipv4Addr::is_link_local` * `Ipv4Addr::is_multicast` * `Ipv4Addr::is_broadcast` * `Ipv4Addr::is_documentation` * `Ipv6Addr::is_unspecified` * `Ipv6Addr::is_loopback` * `Ipv6Addr::is_unique_local` * `Ipv6Addr::is_multicast` * `Vec::as_slice` * `Vec::as_mut_slice` * `String::as_str` * `String::as_mut_str` * `<[T]>::clone_from_slice` - the `usize` return value is removed * `<[T]>::sort_by_key` * `i32::checked_rem` (and other signed types) * `i32::checked_neg` (and other signed types) * `i32::checked_shl` (and other signed types) * `i32::checked_shr` (and other signed types) * `i32::saturating_mul` (and other signed types) * `i32::overflowing_add` (and other signed types) * `i32::overflowing_sub` (and other signed types) * `i32::overflowing_mul` (and other signed types) * `i32::overflowing_div` (and other signed types) * `i32::overflowing_rem` (and other signed types) * `i32::overflowing_neg` (and other signed types) * `i32::overflowing_shl` (and other signed types) * `i32::overflowing_shr` (and other signed types) * `u32::checked_rem` (and other unsigned types) * `u32::checked_neg` (and other unsigned types) * `u32::checked_shl` (and other unsigned types) * `u32::saturating_mul` (and other unsigned types) * `u32::overflowing_add` (and other unsigned types) * `u32::overflowing_sub` (and other unsigned types) * `u32::overflowing_mul` (and other unsigned types) * `u32::overflowing_div` (and other unsigned types) * `u32::overflowing_rem` (and other unsigned types) * `u32::overflowing_neg` (and other unsigned types) * `u32::overflowing_shl` (and other unsigned types) * `u32::overflowing_shr` (and other unsigned types) * `ffi::IntoStringError` * `CString::into_string` * `CString::into_bytes` * `CString::into_bytes_with_nul` * `From<CString> for Vec<u8>` * `From<CString> for Vec<u8>` * `IntoStringError::into_cstring` * `IntoStringError::utf8_error` * `Error for IntoStringError` Deprecated * `Path::relative_from` - renamed to `strip_prefix` * `Path::prefix` - use `components().next()` instead * `os::unix::fs` constants - moved to the `libc` crate * `fmt::{radix, Radix, RadixFmt}` - not used enough to stabilize * `IntoCow` - conflicts with `Into` and may come back later * `i32::{BITS, BYTES}` (and other integers) - not pulling their weight * `DebugTuple::formatter` - will be removed * `sync::Semaphore` - not used enough and confused with system semaphores Closes #23284 cc #27709 (still lots more methods though) Closes #27712 Closes #27722 Closes #27728 Closes #27735 Closes #27729 Closes #27755 Closes #27782 Closes #27798
2016-01-15 12:07:52 -06:00
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
fn as_ref(&self) -> &T {
self
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
type Output = Cow<'a, str>;
fn add(self, rhs: &'a str) -> Self {
if self == "" {
Cow::Borrowed(rhs)
} else if rhs == "" {
self
} else {
Cow::Owned(self.into_owned() + rhs)
}
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
type Output = Cow<'a, str>;
fn add(self, rhs: Cow<'a, str>) -> Self {
if self == "" {
rhs
} else if rhs == "" {
self
} else {
Cow::Owned(self.into_owned() + rhs.borrow())
}
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
fn add_assign(&mut self, rhs: &'a str) {
if rhs == "" { return; }
self.to_mut().push_str(rhs);
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
fn add_assign(&mut self, rhs: Cow<'a, str>) {
if rhs == "" { return; }
self.to_mut().push_str(rhs.borrow());
}
}