1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//! 用于处理借用数据的模块。

#![stable(feature = "rust1", since = "1.0.0")]

/// 借用数据的 trait。
///
/// 在 Rust 中,通常为不同的用例提供类型的不同表示形式。
/// 例如,可以通过指针类型 (例如 [`Box<T>`] 或 [`Rc<T>`]) 为特定用途适当地选择值的存储位置和管理。
/// 除了这些可以与任何类型一起使用的泛型包装之外,某些类型还提供了可选的构面,从而提供了可能昂贵的功能。
/// 这种类型的一个示例是 [`String`],它增加了将字符串扩展到基本 [`str`] 的功能。
/// 这要求保持简单的不可变字符串不需要的其他信息。
///
/// 这些类型通过引用该数据的类型来提供对底层数据的访问。据说它们是借来的那种类型的。
/// 例如,可以将 [`Box<T>`] 作为 `T` 借用,而可以将 [`String`] 作为 `str` 借用。
///
/// 类型表示可以通过实现 `Borrow<T>` 来借用它们作为某种类型的 `T`,并在 trait 的 [`borrow`] 方法中对 `T` 进行引用。一个类型可以自由借用为几种不同的类型。
/// 如果希望将类型可变为借用 - 允许修改底层数据,则可以另外实现 [`BorrowMut<T>`]。
///
/// 此外,在为其他 traits 提供实现时,需要考虑由于充当该底层类型的表示而导致它们的行为是否与底层类型的行为相同。
/// 当泛型代码依赖于这些其他 trait 实现的相同行为时,通常会使用 `Borrow<T>`。
/// 这些 traits 可能会显示为其他 trait bounds。
///
/// 特别是对于借用和拥有的值,`Eq`,`Ord` 和 `Hash` 必须等效: `x.borrow() == y.borrow()` 的结果应与 `x == y` 相同。
///
/// 如果泛型代码只需要为可以为相关类型 `T` 提供引用的所有类型工作,则通常最好使用 [`AsRef<T>`],因为更多类型可以安全地实现它。
///
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
/// [`String`]: ../../std/string/struct.String.html
/// [`borrow`]: Borrow::borrow
///
/// # Examples
///
/// 作为数据集合,[`HashMap<K, V>`] 同时拥有键和值。如果键的实际数据包装在某种管理类型中,则仍然应该可以使用对键数据的引用来搜索值。
/// 例如,如果键是一个字符串,则它很可能与哈希 map 一起存储为 [`String`],而应该可以使用 [`&str`][`str`] 进行搜索。
/// 因此,`insert` 需要在 `String` 上运行,而 `get` 需要能够使用 `&str`。
///
/// 略有简化,`HashMap<K, V>` 的相关部分如下所示:
///
/// ```
/// use std::borrow::Borrow;
/// use std::hash::Hash;
///
/// pub struct HashMap<K, V> {
///     # marker: ::std::marker::PhantomData<(K, V)>,
///     // 字段省略
/// }
///
/// impl<K, V> HashMap<K, V> {
///     pub fn insert(&self, key: K, value: V) -> Option<V>
///     where K: Hash + Eq
///     {
///         # unimplemented!()
///         // ...
///     }
///
///     pub fn get<Q>(&self, k: &Q) -> Option<&V>
///     where
///         K: Borrow<Q>,
///         Q: Hash + Eq + ?Sized
///     {
///         # unimplemented!()
///         // ...
///     }
/// }
/// ```
///
/// 整个哈希 map 在键类型 `K` 上是泛型的。由于这些键存储在哈希 map 中,因此该类型必须拥有键的数据。
/// 插入键值对时,会给 map 这样的 `K`,并且需要找到正确的哈希值存储区,并根据该 `K` 检查键是否已存在。因此,它需要 `K: Hash + Eq`。
///
/// 但是,在 map 中搜索值时,必须提供 `K` 的引用作为搜索键,这要求始终创建此类拥有的值。
/// 对于字符串键,这意味着仅在搜索仅 `str` 可用的情况下,才需要创建 `String` 值。
///
/// 相反,`get` 方法是底层键数据类型的泛型,在上面的方法签名中称为 `Q`。它通过要求 `K: Borrow<Q>` 来声明 `K` 借用为 `Q`。
/// 通过额外要求 `Q: Hash + Eq`,它表示要求 `K` 和 `Q` 具有 `Hash` 和 `Eq` traits 的实现,它们会产生相同的结果。
///
/// `get` 的实现尤其依赖于 `Hash` 的相同实现,即通过基于 `Q` 值计算出的哈希值插入键,通过在 `Q` 值上调用 `Hash::hash` 来确定键的哈希存储桶。
///
///
/// 结果,如果包装了 `Q` 值的 `K` 产生与 `Q` 不同的哈希,则哈希 map 会中断。例如,假设您有一个包裹字符串但比较 ASCII 字母而忽略大小写的类型:
///
/// ```
/// pub struct CaseInsensitiveString(String);
///
/// impl PartialEq for CaseInsensitiveString {
///     fn eq(&self, other: &Self) -> bool {
///         self.0.eq_ignore_ascii_case(&other.0)
///     }
/// }
///
/// impl Eq for CaseInsensitiveString { }
/// ```
///
/// 因为两个相等的值需要产生相同的哈希值,所以 `Hash` 的实现也需要忽略 ASCII 大小写:
///
/// ```
/// # use std::hash::{Hash, Hasher};
/// # pub struct CaseInsensitiveString(String);
/// impl Hash for CaseInsensitiveString {
///     fn hash<H: Hasher>(&self, state: &mut H) {
///         for c in self.0.as_bytes() {
///             c.to_ascii_lowercase().hash(state)
///         }
///     }
/// }
/// ```
///
/// `CaseInsensitiveString` 可以实现 `Borrow<str>` 吗? 它当然可以通过其包含的拥有的字符串为字符串切片提供引用。
/// 但是由于 `Hash` 的实现方式不同,所以它的行为与 `str` 不同,因此,实际上,一定不能实现 `Borrow<str>`。
/// 如果它希望允许其他人访问底层 `str`,则可以通过 `AsRef<str>` 来实现,而 `AsRef<str>` 则没有任何额外的要求。
///
/// [`Hash`]: crate::hash::Hash
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
/// [`String`]: ../../std/string/struct.String.html
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Borrow"]
pub trait Borrow<Borrowed: ?Sized> {
    /// 从拥有的值中一成不变地借用。
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// 用于可变借用数据的 trait。
///
/// 作为 [`Borrow<T>`] 的同伴,这个 trait 允许一个类型通过提供一个可变引用作为底层类型借用。
/// 请参见 [`Borrow<T>`],以了解更多有关借用另一种类型的信息。
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
    /// 从拥有的值中借用。
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    #[rustc_diagnostic_item = "noop_method_borrow"]
    fn borrow(&self) -> &T {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for &T {
    fn borrow(&self) -> &T {
        &**self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for &mut T {
    fn borrow(&self) -> &T {
        &**self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for &mut T {
    fn borrow_mut(&mut self) -> &mut T {
        &mut **self
    }
}