rust/src/libcollections/borrow.rs

362 lines
9.6 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 string::String;
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:
///
/// ```
2017-02-14 22:07:51 -06:00
/// let s: &str = "a";
/// let ss: String = s.to_owned();
2016-04-05 07:11:08 -05:00
///
2017-02-14 22:07:51 -06:00
/// let v: &[i32] = &[1, 2];
/// let vv: Vec<i32> = v.to_owned();
2016-04-05 07:11:08 -05:00
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn to_owned(&self) -> Self::Owned;
}
#[stable(feature = "rust1", since = "1.0.0")]
2016-12-19 22:24:00 -06:00
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-12-19 22:24:00 -06:00
Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
&'a B),
/// Owned data.
#[stable(feature = "rust1", since = "1.0.0")]
2016-12-19 22:24:00 -06:00
Owned(#[stable(feature = "rust1", since = "1.0.0")]
<B as ToOwned>::Owned),
}
#[stable(feature = "rust1", since = "1.0.0")]
2016-12-19 22:24:00 -06:00
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
}
}
}
}
2016-12-19 22:24:00 -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());
match *self {
Borrowed(..) => unreachable!(),
Owned(ref mut owned) => owned,
}
}
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")]
2016-12-19 22:24:00 -06:00
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")]
2016-12-19 22:24:00 -06:00
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")]
2016-12-19 22:24:00 -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")]
2016-12-19 22:24:00 -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.14.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
type Output = Cow<'a, str>;
#[inline]
fn add(mut self, rhs: &'a str) -> Self::Output {
self += rhs;
self
}
}
#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
type Output = Cow<'a, str>;
#[inline]
fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
self += rhs;
self
}
}
#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
fn add_assign(&mut self, rhs: &'a str) {
if self.is_empty() {
*self = Cow::Borrowed(rhs)
} else if rhs.is_empty() {
return;
} else {
if let Cow::Borrowed(lhs) = *self {
let mut s = String::with_capacity(lhs.len() + rhs.len());
s.push_str(lhs);
*self = Cow::Owned(s);
}
self.to_mut().push_str(rhs);
}
}
}
#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
fn add_assign(&mut self, rhs: Cow<'a, str>) {
if self.is_empty() {
*self = rhs
} else if rhs.is_empty() {
return;
} else {
if let Cow::Borrowed(lhs) = *self {
let mut s = String::with_capacity(lhs.len() + rhs.len());
s.push_str(lhs);
*self = Cow::Owned(s);
}
self.to_mut().push_str(&rhs);
}
}
}