Function understand_lifetime_hrtb

Source
pub fn understand_lifetime_hrtb()
Expand description

示例: 理解 trait对象中的生命周期参数

trait Foo<'a> {}
struct FooImpl<'a> {
    s: &'a [u32],
}
impl<'a> Foo<'a> for FooImpl<'a> {
}
// 为 trait对象 增加 'a ,因为 Box 默认是 static 的,而FooImpl 中的 s 则是引用
// 表明该trait对象(结构体实例)与其结构体中的引用的生命周期是一样长的(<=)
fn foo<'a>(s: &'a [u32]) -> Box<dyn Foo<'a> + 'a> {
    Box::new(FooImpl { s: s })
}
fn main(){}

§理解 HRTB (higher ranked trait bounds)

示例一:

use std::fmt::Debug;
trait DoSomething<T> {
    fn do_sth(&self, value: T);
}
impl<'a, T: Debug> DoSomething<T> for &'a usize {
    fn do_sth(&self, value: T) {
        println!("{:?}", value);
    }
}
fn foo<'a>(b: Box<DoSomething<&'a usize>>) {
    let s: usize = 10;
    b.do_sth(&s) // error[E0597]: `s` does not live long enough
}
fn main(){
    let x  = Box::new(&2usize);
    foo(x);
}

修正:使用 for<'f> 改为 late bound


use std::fmt::Debug;
trait DoSomething<T> {
    fn do_sth(&self, value: T);
}
impl<'a, T: Debug> DoSomething<T> for &'a usize {
    fn do_sth(&self, value: T) {
        println!("{:?}", value);
    }
}
fn bar(b: Box<for<'f> DoSomething<&'f usize>>) {
    let s: usize = 10;
    b.do_sth(&s);
}
fn main(){
    let x  = Box::new(&2usize);
    bar(x);
}

示例 2:

use rand;
use std::io::Read;

trait Checksum<R: Read> {
    fn calc(&mut self, r: R) -> Vec<u8>;
}

struct Xor;

impl<R: Read> Checksum<R> for Xor {
    fn calc(&mut self, mut r: R) -> Vec<u8> {
        let mut res: u8 = 0;
        let mut buf = [0u8; 8];
        loop {
            let read = r.read(&mut buf).unwrap();
            if read == 0 {
                break;
            }
            for b in &buf[..read] {
                res ^= b;
            }
        }

        vec![res]
    }
}

struct Add;

impl<R: Read> Checksum<R> for Add {
    fn calc(&mut self, mut r: R) -> Vec<u8> {
        let mut res: u8 = 0;
        let mut buf = [0u8; 8];
        loop {
            let read = r.read(&mut buf).unwrap();
            if read == 0 {
                break;
            }
            for b in &buf[..read] {
                let tmp = res as u16 + *b as u16;
                res = tmp as u8;
            }
        }

        vec![res]
    }
}

fn main() {
    let mut buf = [0u8; 8];
    // error[E0308]: `if` and `else` have incompatible types
    // 修正:
    // step 1: Box<dyn Checksum<&[u8]>> 转为 trait 对象
    // step 2: Box<dyn for<'a> Checksum<&'a [u8]>> 使用 for<'a> 转为 late bound
    let mut checker = if rand::random() {
        println!("Initializing Xor Checksum");
        Box::new(Xor)
    } else {
        println!("Initializing Add Checksum");
        Box::new(Add)
    };

    let mut data = "Sedm lumpu slohlo pumpu za uplnku".as_bytes();
    let mut i = 0;

    loop {
        let chunk_size = data.read(&mut buf).unwrap();
        if chunk_size == 0 {
            break;
        }
        let cs = checker.calc(&buf[..chunk_size]);
        println!("Checksum {} is {:?}", i, cs);
        i += 1;
    }
}