本書github鏈接:inside-rust-std-library
前面章節(jié)參見:
深入RUST標準庫內(nèi)核(序言) - 簡書 (jianshu.com)
深入RUST標準庫內(nèi)核(一 概述) - 簡書 (jianshu.com)
深入RUST標準庫內(nèi)核(二 內(nèi)存)—Layout/原生指針 - 簡書 (jianshu.com)
深入RUST標準庫內(nèi)核(二 內(nèi)存)—NonNull<T>/申請及釋放 - 簡書 (jianshu.com)
深入RUST標準庫內(nèi)核(二 內(nèi)存)—mem模塊/MaybeUninit<T> - 簡書 (jianshu.com)
深入RUST標準庫內(nèi)核 (三 基礎(chǔ)Trait) 編譯器內(nèi)置Trait - 簡書 (jianshu.com)
Borrow Trait 代碼分析
Borrow Trait代碼定義如下:
//實現(xiàn)Borrow Trait的類型一般是封裝結(jié)構(gòu)丧没,如智能指針Box<T>,Rc<T>, String佑力,Cell, RefCell等,通過borrow將內(nèi)部變量的引用提供給
//外部。通常的情況下,這些也都實現(xiàn)了Deref恨旱,AsRef等Trait把內(nèi)部變量暴露出來往堡,所以這些Trait之間有些重復。但Borrow Trait 更主要的
//場景是在RefCell等結(jié)構(gòu)中提供內(nèi)部可變性翠拣,這是Deref, AsRef等Trait無能為力的區(qū)域版仔。后繼分析相關(guān)類型時再給出進一步分析。
pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
fn borrow_mut(&mut self) -> &mut Borrowed;
}
//每一個類型都實現(xiàn)了針對自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for T {
#[rustc_diagnostic_item = "noop_method_borrow"]
fn borrow(&self) -> &T {
self
}
}
//每一個類型都實現(xiàn)了針對自身的BorrowMut Trait
impl<T: ?Sized> BorrowMut<T> for T {
fn borrow_mut(&mut self) -> &mut T {
self
}
}
//每一個類型的引用都實現(xiàn)了對自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for &T {
fn borrow(&self) -> &T {
&**self
}
}
//每一個類型的可變引用都實現(xiàn)了針對自身的Borrow Trait
impl<T: ?Sized> Borrow<T> for &mut T {
fn borrow(&self) -> &T {
&**self
}
}
//每一個類型的可變引用都實現(xiàn)了針對自身的BorrowMut
impl<T: ?Sized> BorrowMut<T> for &mut T {
fn borrow_mut(&mut self) -> &mut T {
&mut **self
}
}
ops 運算符 Trait 代碼分析
RUST中误墓,所有的運算符號都可以重載蛮粮。
一個小規(guī)則
在重載函數(shù)中,如果重載的符號出現(xiàn)谜慌,編譯器用規(guī)定的默認操作來實現(xiàn)然想。例如:
impl const BitAnd for u8 {
type Output = u8;
//下面函數(shù)內(nèi)部的 & 符號不再引發(fā)重載,是編譯器的默認按位與操作欣范。
fn bitand(self, rhs: u8) -> u8 { self & u8 }
}
數(shù)學運算符 Trait
易理解变泄,略
位運算符 Trait
易理解,略
關(guān)系運算符Trait
代碼及分析如下
//"==" "!="的實現(xiàn)Trait恼琼,實現(xiàn)該Trait的類型可以只部分相等
pub trait PartialEq<Rhs: ?Sized = Self> {
/// “==” 重載方法
fn eq(&self, other: &Rhs) -> bool;
///`!=` 重載方法
fn ne(&self, other: &Rhs) -> bool {
!self.eq(other)
}
}
/// 實現(xiàn)Derive屬性的過程宏
pub macro PartialEq($item:item) {
/* compiler built-in */
}
//實現(xiàn)該Trait的類型必須完全相等
pub trait Eq: PartialEq<Self> {
fn assert_receiver_is_total_eq(&self) {}
}
/// 實現(xiàn)Derive屬性的過程宏
pub macro Eq($item:item) {
/* compiler built-in */
}
//用于表示關(guān)系結(jié)果的結(jié)構(gòu)體
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
#[repr(i8)]
pub enum Ordering {
/// 小于.
Less = -1,
/// 等于.
Equal = 0,
/// 大于.
Greater = 1,
}
impl Ordering {
pub const fn is_eq(self) -> bool {
matches!(self, Equal)
}
//以下函數(shù)體實現(xiàn)略
pub const fn is_ne(self) -> bool
pub const fn is_lt(self) -> bool
pub const fn is_gt(self) -> bool
pub const fn is_le(self) -> bool
pub const fn is_ge(self) -> bool
//做反轉(zhuǎn)操作
pub const fn reverse(self) -> Ordering {
match self {
Less => Greater,
Equal => Equal,
Greater => Less,
}
}
//用來簡化代碼及更好的支持函數(shù)式編程
//舉例:
// let x: (i64, i64, i64) = (1, 2, 7);
// let y: (i64, i64, i64) = (1, 5, 3);
// let result = x.0.cmp(&y.0).then(x.1.cmp(&y.1)).then(x.2.cmp(&y.2));
pub const fn then(self, other: Ordering) -> Ordering {
match self {
Equal => other,
_ => self,
}
}
//用來簡化代碼實及支持函數(shù)式編程
pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
match self {
Equal => f(),
_ => self,
}
}
}
// "<" ">" ">=" "<=" 運算符重載結(jié)構(gòu)
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
// "<" 運算符重載
fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less))
}
//"<="運算符重載
fn le(&self, other: &Rhs) -> bool {
// Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`.
!matches!(self.partial_cmp(other), None | Some(Greater))
}
//">"運算符重載
fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater))
}
//">="運算符重載
fn ge(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater | Equal))
}
}
//實現(xiàn)Derive的過程宏
pub macro PartialOrd($item:item) {
/* compiler built-in */
}
//用輸入的閉包比較函數(shù)獲取兩個值中大的一個
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
}
}
//用輸入的閉包比較函數(shù)獲取兩個值中小的一個
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
}
}
//以下代碼易理解妨蛹,略
pub trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
fn max(self, other: Self) -> Self
where
Self: Sized,
{
max_by(self, other, Ord::cmp)
}
fn min(self, other: Self) -> Self
where
Self: Sized,
{
min_by(self, other, Ord::cmp)
}
fn clamp(self, min: Self, max: Self) -> Self
where
Self: Sized,
{
assert!(min <= max);
if self < min {
min
} else if self > max {
max
} else {
self
}
}
}
//實現(xiàn)Drive 屬性過程宏
pub macro Ord($item:item) {
/* compiler built-in */
}
pub fn min<T: Ord>(v1: T, v2: T) -> T {
v1.min(v2)
}
pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
pub fn max<T: Ord>(v1: T, v2: T) -> T {
v1.max(v2)
}
pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
//對于實現(xiàn)了PartialOrd的類型實現(xiàn)一個Ord的反轉(zhuǎn),這是一個
//adapter的設計模式例子
pub struct Reverse<T>(pub T);
impl<T: PartialOrd> PartialOrd for Reverse<T> {
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
fn lt(&self, other: &Self) -> bool {
other.0 < self.0
}
...
...
}
impl<T: Ord> Ord for Reverse<T> {
fn cmp(&self, other: &Reverse<T>) -> Ordering {
other.0.cmp(&self.0)
}
...
}
impl<T: Clone> Clone for Reverse<T> {
fn clone(&self) -> Reverse<T> {
Reverse(self.0.clone())
}
fn clone_from(&mut self, other: &Self) {
self.0.clone_from(&other.0)
}
}
// 具體的實現(xiàn)宏
mod impls {
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::hint::unreachable_unchecked;
//PartialEq在原生類型上的實現(xiàn)
macro_rules! partial_eq_impl {
($($t:ty)*) => ($(
impl PartialEq for $t {
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
}
)*)
}
impl PartialEq for () {
fn eq(&self, _other: &()) -> bool {
true
}
fn ne(&self, _other: &()) -> bool {
false
}
}
partial_eq_impl! {
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
}
// Eq晴竞,PartialOrd, Ord在原生類型上的實現(xiàn)蛙卤,略
...
...
impl PartialEq for ! {
fn eq(&self, _: &!) -> bool {
*self
}
}
impl Eq for ! {}
impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
}
}
impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering {
*self
}
}
//A實現(xiàn)了PartialEq<B>, PartialOrd<B>后,對&A實現(xiàn)PartialEq<&B>颓鲜, PartialOrd<&B>
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&B) -> bool {
//注意這個調(diào)用方式表窘,此時不能用self.eq調(diào)用典予。
//eq方法參數(shù)為引用
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
where
A: PartialOrd<B>,
{
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
fn lt(&self, other: &&B) -> bool {
PartialOrd::lt(*self, *other)
}
...
...
}
//如果A實現(xiàn)了Ord Trait, 對&A實現(xiàn)Ord Trait
impl<A: ?Sized> Ord for &A
where
A: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
}
impl<A: ?Sized> Eq for &A where A: Eq {}
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
where
A: PartialOrd<B>,
{
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
fn lt(&self, other: &&mut B) -> bool {
PartialOrd::lt(*self, *other)
}
...
...
}
impl<A: ?Sized> Ord for &mut A
where
A: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
}
impl<A: ?Sized> Eq for &mut A where A: Eq {}
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
}
關(guān)系運算的運算符重載相對于數(shù)學運算符重載和位運算符重載復雜一些,但其邏輯依然是比較簡單的乐严。
瘤袖?運算符 Trait代碼分析
?操作是RUST支持函數(shù)式編程的一個基礎(chǔ)。不過即使不用于函數(shù)式編程昂验,也可大幅簡化代碼捂敌。
當一個類型實現(xiàn)了Try Trait時〖惹伲可對這個類型做占婉?操作簡化代碼。
Try Trait也是try..catch在RUST中的一種實現(xiàn)方式甫恩,但從代碼的表現(xiàn)形式上更加簡化逆济。另外,因為能夠返回具體類型磺箕,這種實現(xiàn)方式就不僅局限于處理異常奖慌,可以擴展到其他類似的場景。
可以定義返回類型的方法松靡,支持鏈式函數(shù)調(diào)用简僧。
Try Trait定義如下:
pub trait Try: FromResidual {
/// ?操作符正常結(jié)束的返回值類型
type Output;
/// ?操作符提前返回的值類型,后繼會用實例來說明
type Residual;
/// 從Self::Output返回值類型中獲得原類型的值
/// 函數(shù)必須符合下面代碼的原則雕欺,
/// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`.
/// 例子:
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::Try;
///
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
/// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
/// assert_eq!(
/// <std::ops::ControlFlow<String, _> as Try>::from_output(5),
/// std::ops::ControlFlow::Continue(5),
/// );
fn from_output(output: Self::Output) -> Self;
/// branch函數(shù)會返回ControlFlow岛马,據(jù)此決定流程繼續(xù)還是提前返回
/// 例子:
/// ```p
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, Try};
///
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
///
/// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
///
/// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(
/// ControlFlow::<_, String>::Break(3).branch(),
/// ControlFlow::Break(ControlFlow::Break(3)),
/// );
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
pub trait FromResidual<R = <Self as Try>::Residual> {
/// 該函數(shù)從提前返回的值中獲取原始值
///
/// 此函數(shù)必須符合下面代碼的原則
/// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
/// 例子:
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, FromResidual};
///
/// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
/// assert_eq!(Option::<String>::from_residual(None), None);
/// assert_eq!(
/// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
/// ControlFlow::Break(5),
/// );
/// ```
fn from_residual(residual: R) -> Self;
}
Try Trait對? 操作支持的舉例如下:
//不用? 操作的代碼
pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
iter: impl Iterator<Item = T>,
mut accum: A,
mut f: impl FnMut(A, T) -> R,
) -> R {
for x in iter {
let cf = f(accum, x).branch();
match cf {
ControlFlow::Continue(a) => accum = a,
ControlFlow::Break(r) => return R::from_residual(r),
}
}
R::from_output(accum)
}
// 使用? 操作的代碼:
fn simple_try_fold<A, T, R: Try<Output = A>>(
iter: impl Iterator<Item = T>,
mut accum: A,
mut f: impl FnMut(A, T) -> R,
) -> R {
for x in iter {
accum = f(accum, x)?;
}
R::from_output(accum)
}
由上,可推斷出T?表示如下代碼
match((T as Try).branch()) {
ControlFlow::Continue(a) => a,
ControlFlow::Break(r) => return (T as Try)::from_residual(r),
}
ControlFlow類型代碼如下, 主要用于指示代碼控制流程指示屠列, 邏輯上可類比于continue, break 關(guān)鍵字 代碼如下:
pub enum ControlFlow<B, C = ()> {
/// Move on to the next phase of the operation as normal.
Continue(C),
/// Exit the operation without running subsequent phases.
Break(B),
// Yes, the order of the variants doesn't match the type parameters.
// They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
// is a no-op conversion in the `Try` implementation.
}
impl<B, C> ops::Try for ControlFlow<B, C> {
type Output = C;
// convert::Infallible表示類型不會被使用啦逆,可認為是忽略類型,
//對于Residual只會用ControlFlow::Break(B), 所以用Infallible明確說明不會用到此類型
type Residual = ControlFlow<B, convert::Infallible>;
fn from_output(output: Self::Output) -> Self {
ControlFlow::Continue(output)
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
ControlFlow::Continue(c) => ControlFlow::Continue(c),
ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
}
}
impl<B, C> ops::FromResidual for ControlFlow<B, C> {
// Infallible表示類型不會被用到
fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
match residual {
ControlFlow::Break(b) => ControlFlow::Break(b),
}
}
}
Option的Try Trait實現(xiàn):
impl<T> ops::Try for Option<T> {
type Output = T;
// Infallible是一種錯誤類型,但該錯誤永遠也不會發(fā)生笛洛,這里需要返回None蹦浦,
// 所以需要用Option類型,但因為只用None撞蜂。所以Some使用Infallible來表示不會被使用,這也表現(xiàn)了RUST的安全理念侥袜,一定在類型定義的時候保證代碼安全蝌诡。
type Residual = Option<convert::Infallible>;
fn from_output(output: Self::Output) -> Self {
Some(output)
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
Some(v) => ControlFlow::Continue(v),
None => ControlFlow::Break(None),
}
}
}
impl<T> const ops::FromResidual for Option<T> {
#[inline]
fn from_residual(residual: Option<convert::Infallible>) -> Self {
match residual {
None => None,
}
}
}
一個Iterator::try_fold()的實現(xiàn):
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
//try 關(guān)鍵字將accum轉(zhuǎn)化為R類型變量
try { accum }
}
小結(jié)
利用Try Trait,程序員可以實現(xiàn)自定義類型的?枫吧,提供函數(shù)式編程的有力手段并簡化代碼浦旱,提升代碼的理解度。