深入RUST標準庫內(nèi)核(三 基礎(chǔ)Trait)— Ops Trait

本書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ù)式編程的有力手段并簡化代碼浦旱,提升代碼的理解度。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末九杂,一起剝皮案震驚了整個濱河市颁湖,隨后出現(xiàn)的幾起案子宣蠕,更是在濱河造成了極大的恐慌,老刑警劉巖甥捺,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抢蚀,死亡現(xiàn)場離奇詭異,居然都是意外死亡镰禾,警方通過查閱死者的電腦和手機皿曲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吴侦,“玉大人屋休,你說我怎么就攤上這事”溉停” “怎么了劫樟?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長织堂。 經(jīng)常有香客問我叠艳,道長,這世上最難降的妖魔是什么捧挺? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任虑绵,我火速辦了婚禮,結(jié)果婚禮上闽烙,老公的妹妹穿的比我還像新娘翅睛。我一直安慰自己,他們只是感情好黑竞,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布捕发。 她就那樣靜靜地躺著,像睡著了一般很魂。 火紅的嫁衣襯著肌膚如雪扎酷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天遏匆,我揣著相機與錄音法挨,去河邊找鬼。 笑死幅聘,一個胖子當著我的面吹牛凡纳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帝蒿,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼荐糜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起暴氏,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤延塑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后答渔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體关带,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年研儒,在試婚紗的時候發(fā)現(xiàn)自己被綠了豫缨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡端朵,死狀恐怖好芭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冲呢,我是刑警寧澤舍败,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站敬拓,受9級特大地震影響邻薯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乘凸,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一厕诡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧营勤,春花似錦灵嫌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赂蠢,卻和暖如春绪穆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虱岂。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工玖院, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人第岖。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓司恳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绍傲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容