<commit_before># rust AsRef and AsMut

## trait definition

在Rust中实现上述两个trait， 则表明能够将一个类型转换为另一个类型的引用。
``` rust
trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}
trait AsMut<T: ?Sized> {
    fn as_mut(&mut self) -> &mut T;
}
```
copy from [Rust笔记 - AsRef and AsMut trait](Rust笔记 - AsRef and AsMut trait)


std::convert 下面，还有另外两个 Trait，AsRef/AsMut，它们功能是配合泛型，在执行引用操作的时候，进行自动类型转换。

## AsRef
AsRef 提供了一个方法 .as_ref()。

对于一个类型为 T 的对象 foo，如果 T 实现了 AsRef<U>，那么，foo 可执行 .as_ref() 操作，即 foo.as_ref()。操作的结果，我们得到了一个类型为 &U 的新引用。

注：

与 Into<T> 不同的是，AsRef<T> 只是类型转换，foo 对象本身没有被消耗；
T: AsRef<U> 中的 T，可以接受 资源拥有者（owned）类型，共享引用（shared referrence）类型 ，可变引用（mutable referrence）类型。


## AsMut
AsMut<T> 提供了一个方法 .as_mut()。它是 AsRef<T> 的可变（mutable）引用版本。

对于一个类型为 T 的对象 foo，如果 T 实现了 AsMut<U>，那么，foo 可执行 .as_mut() 操作，即 foo.as_mut()。操作的结果，我们得到了一个类型为 &mut U 的可变（mutable）引用。

注：在转换的过程中，foo 会被可变（mutable）借用。

copy from [AsRef 和 AsMut](https://wiki.jikexueyuan.com/project/rust-primer/intoborrow/asref.html)<commit_msg>add as_ref example<commit_after># rust AsRef and AsMut

## trait definition

在Rust中实现上述两个trait， 则表明能够将一个类型转换为另一个类型的引用。
``` rust
trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}
trait AsMut<T: ?Sized> {
    fn as_mut(&mut self) -> &mut T;
}
```
copy from [Rust笔记 - AsRef and AsMut trait](Rust笔记 - AsRef and AsMut trait)


std::convert 下面，还有另外两个 Trait，AsRef/AsMut，它们功能是配合泛型，在执行引用操作的时候，进行自动类型转换。

## AsRef
AsRef 提供了一个方法 .as_ref()。

对于一个类型为 T 的对象 foo，如果 T 实现了 AsRef<U>，那么，foo 可执行 .as_ref() 操作，即 foo.as_ref()。操作的结果，我们得到了一个类型为 &U 的新引用。

注：

与 Into<T> 不同的是，AsRef<T> 只是类型转换，foo 对象本身没有被消耗；
T: AsRef<U> 中的 T，可以接受 资源拥有者（owned）类型，共享引用（shared referrence）类型 ，可变引用（mutable referrence）类型。


## AsMut
AsMut<T> 提供了一个方法 .as_mut()。它是 AsRef<T> 的可变（mutable）引用版本。

对于一个类型为 T 的对象 foo，如果 T 实现了 AsMut<U>，那么，foo 可执行 .as_mut() 操作，即 foo.as_mut()。操作的结果，我们得到了一个类型为 &mut U 的可变（mutable）引用。

注：在转换的过程中，foo 会被可变（mutable）借用。

copy from [AsRef 和 AsMut](https://wiki.jikexueyuan.com/project/rust-primer/intoborrow/asref.html)

## explaining as_ref

``` rust
fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.as_ref().map(|x| &**x).unwrap_or("default string");
}
```
First, as_ref() implicitly takes a reference on opt, giving an &Option<String> (because as_ref() takes &self, i.e. it receives a reference), and turns it into an Option<&String>. Then we use map to convert it to an Option<&str>. Here's what &**x does: the rightmost * (which is evaluated first) simply dereferences the &String, giving a String lvalue. Then, the leftmost * actually invokes the Deref trait, because String implements Deref<Target=str>, giving us a str lvalue. Finally, the & takes the address of the str lvalue, giving us a &str.

You can simplify this a bit further by using map_or to combine map and unwrap_or in a single operation:

``` rust
fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.as_ref().map_or("default string", |x| &**x);
}
```
If &**x looks too magical to you, you can write String::as_str instead:

``` rust
fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.as_ref().map_or("default string", String::as_str);
}
```
or String::as_ref (from the AsRef trait, which is in the prelude):

``` rust
fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.as_ref().map_or("default string", String::as_ref);
}
```
or String::deref (though you need to import the Deref trait too):

``` rust
use std::ops::Deref;

fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.as_ref().map_or("default string", String::deref);
}
```
For either of these to work, you need to keep an owner for the Option<String> as long as the Option<&str> or unwrapped &str needs to remain available. If that's too complicated, you could use Cow.

``` rust
use std::borrow::Cow::{Borrowed, Owned};

fn main() {
    let opt: Option<String> = Some("some value".to_owned());
    let value = opt.map_or(Borrowed("default string"), |x| Owned(x));
}
```
copy from [Converting from Option<String> to Option<&str>](https://stackoverflow.com/questions/31233938/converting-from-optionstring-to-optionstr)
{'fraction_non_alphanumeric': 0.14976303317535544, 'fraction_numerical': 0.0018957345971563982, 'mean_word_length': 4.995738636363637, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 39, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5190824', 'n_tokens_mistral': 1910, 'n_tokens_neox': 1953, 'n_words': 459}