Skip to content

Commit 4ab2235

Browse files
committed
libcore: add borrow module
Following [the collections reform RFC](rust-lang/rfcs#235), this commit adds a new `borrow` module to libcore. The module contains traits for borrowing data (`BorrowFrom` and `BorrowFromMut`), generalized cloning (`ToOwned`), and a clone-on-write smartpointer (`Cow`).
1 parent f092793 commit 4ab2235

File tree

5 files changed

+145
-1
lines changed

5 files changed

+145
-1
lines changed

src/libcollections/slice.rs

+11
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989

9090
use self::Direction::*;
9191
use alloc::boxed::Box;
92+
use core::borrow::{BorrowFrom, BorrowFromMut};
9293
use core::cmp;
9394
use core::kinds::Sized;
9495
use core::mem::size_of;
@@ -647,6 +648,16 @@ impl<T> SliceAllocPrelude<T> for [T] {
647648
}
648649
}
649650

651+
#[unstable = "trait is unstable"]
652+
impl<T> BorrowFrom<Vec<T>> for [T] {
653+
fn borrow_from(owned: &Vec<T>) -> &[T] { owned[] }
654+
}
655+
656+
#[unstable = "trait is unstable"]
657+
impl<T> BorrowFromMut<Vec<T>> for [T] {
658+
fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { owned[mut] }
659+
}
660+
650661
/// Unsafe operations
651662
pub mod raw {
652663
pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};

src/libcollections/str.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
pub use self::MaybeOwned::*;
5555
use self::RecompositionState::*;
5656
use self::DecompositionType::*;
57-
57+
use core::borrow::BorrowFrom;
5858
use core::default::Default;
5959
use core::fmt;
6060
use core::cmp;
@@ -604,6 +604,11 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
604604
}
605605
}
606606

607+
#[unstable = "trait is unstable"]
608+
impl BorrowFrom<String> for str {
609+
fn borrow_from(owned: &String) -> &str { owned[] }
610+
}
611+
607612
/// Unsafe string operations.
608613
pub mod raw {
609614
pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};

src/libcore/borrow.rs

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! A module for working with borrowed data.
12+
//!
13+
//! # The `BorrowFrom` traits
14+
//!
15+
//! In general, there may be several ways to "borrow" a piece of data. The
16+
//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
17+
//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
18+
//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
19+
//!
20+
//! When writing generic code, it is often desirable to abstract over all ways
21+
//! of borrowing data from a given type. That is the role of the `BorrowFrom`
22+
//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`. A given
23+
//! type can be borrowed as multiple different types. In particular, `Vec<T>:
24+
//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
25+
//!
26+
//! # The `ToOwned` trait
27+
//!
28+
//! Some types make it possible to go from borrowed to owned, usually by
29+
//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
30+
//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
31+
//! from any borrow of a given type.
32+
//!
33+
//! # The `Cow` (clone-on-write) type
34+
//!
35+
//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
36+
//! can enclose and provide immutable access to borrowed data, and clone the
37+
//! data lazily when mutation or ownership is required. The type is designed to
38+
//! work with general borrowed data via the `BorrowFrom` trait.
39+
//!
40+
//! `Cow` implements both `Deref` and `DerefMut`, which means that you can call
41+
//! methods directly on the data it encloses. The first time a mutable reference
42+
//! is required, the data will be cloned (via `to_owned`) if it is not
43+
//! already owned.
44+
45+
#![unstable = "recently added as part of collections reform"]
46+
47+
use clone::Clone;
48+
use kinds::Sized;
49+
use ops::Deref;
50+
51+
/// A trait for borrowing data.
52+
pub trait BorrowFrom<Sized? Owned> for Sized? {
53+
/// Immutably borrow from an owned value.
54+
fn borrow_from(owned: &Owned) -> &Self;
55+
}
56+
57+
/// A trait for mutably borrowing data.
58+
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
59+
/// Mutably borrow from an owned value.
60+
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
61+
}
62+
63+
impl<Sized? T> BorrowFrom<T> for T {
64+
fn borrow_from(owned: &T) -> &T { owned }
65+
}
66+
67+
impl<Sized? T> BorrowFromMut<T> for T {
68+
fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
69+
}
70+
71+
impl BorrowFrom<&'static str> for str {
72+
fn borrow_from<'a>(owned: &'a &'static str) -> &'a str { &**owned }
73+
}
74+
75+
/// A generalization of Clone to borrowed data.
76+
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
77+
/// Create owned data from borrowed data, usually by copying.
78+
fn to_owned(&self) -> Owned;
79+
}
80+
81+
impl<T> ToOwned<T> for T where T: Clone {
82+
fn to_owned(&self) -> T { self.clone() }
83+
}
84+
85+
/// A clone-on-write smart pointer.
86+
pub enum Cow<'a, T, B: 'a> where B: ToOwned<T> {
87+
/// Borrowed data.
88+
Borrowed(&'a B),
89+
90+
/// Owned data.
91+
Owned(T)
92+
}
93+
94+
impl<'a, T, B> Cow<'a, T, B> where B: ToOwned<T> {
95+
/// Acquire a mutable reference to the owned form of the data.
96+
///
97+
/// Copies the data if it is not already owned.
98+
pub fn to_mut(&mut self) -> &mut T {
99+
match *self {
100+
Borrowed(borrowed) => {
101+
*self = Owned(borrowed.to_owned());
102+
self.to_mut()
103+
}
104+
Owned(ref mut owned) => owned
105+
}
106+
}
107+
108+
/// Extract the owned data.
109+
///
110+
/// Copies the data if it is not already owned.
111+
pub fn into_owned(self) -> T {
112+
match self {
113+
Borrowed(borrowed) => borrowed.to_owned(),
114+
Owned(owned) => owned
115+
}
116+
}
117+
}
118+
119+
impl<'a, T, B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> {
120+
fn deref(&self) -> &B {
121+
match *self {
122+
Borrowed(borrowed) => borrowed,
123+
Owned(ref owned) => BorrowFrom::borrow_from(owned)
124+
}
125+
}
126+
}

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub mod default;
108108
pub mod any;
109109
pub mod atomic;
110110
pub mod bool;
111+
pub mod borrow;
111112
pub mod cell;
112113
pub mod char;
113114
pub mod panicking;

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ extern crate rustrt;
141141

142142
pub use core::any;
143143
pub use core::bool;
144+
pub use core::borrow;
144145
pub use core::cell;
145146
pub use core::clone;
146147
#[cfg(not(test))] pub use core::cmp;

0 commit comments

Comments
 (0)