2015-10-14 25 views
1

我正在编写Google Brotli解压缩算法的Rust实现,该算法在流末尾使用固定数量的“隐式零”来启用某些优化。访问由Take或Chain包装的读取组件

Google C的实现使用了各种计数器的意大利面代码,但我想在Rust std :: io库中使用适配器。类似:

pub struct StreamBitReader<R> { 
    reader: Chain<R,Take<Repeat>>, 
    ... 
} 

其中“R”是底层Read该比特读取器结构被包裹。但是,在很多情况下,解压缩算法会检查是否有“溢出”流,并通过检查读取的隐式零字节数来完成此操作。这似乎是不可能的安全锈,因为没有办法获得Chain组件的参考,除非我失去了一些东西。

当构建Chain时,它将获取(移动)底层Read结构的所有权,然后隐藏在私有成员中。

有什么办法来构建Take<Repeat>部分,这样我可以甚至在Chain适配器取得所有权访问limit()新生力量Take

回答

1

我知道一种方式,但我认为它不适合你的目标。

use std::io::{self, Read}; 

fn main() { 
    let file = io::empty(); 
    let zeroes = io::repeat(0); 
    let mut ten_zeroes = zeroes.take(10); 
    { 
     let mut with_zeroes = file.chain(ten_zeroes.by_ref()); 
     let mut buf = [0; 5]; 
     with_zeroes.read(&mut buf); 
    } 
    println!("{}", ten_zeroes.limit()); 
} 

关键是Read::by_ref,它返回一个可变引用。 Read是针对实现Read的类型的任何可变引用而实现的,因此您可以将参考的所有权更改为Chain

诀窍是你必须销毁Chain,然后才能再次使用内部对象。将这个存储在结构体中也是非常痛苦/不可能的。

你最好的选择可能是写自己的ZeroPadded适配器,结合ChainRepeatTake并提供limit方法。

如果没有其他人给出更好的答案,我还可以看到为适配器上的方法添加功能请求。使用into_inner方法消耗一个适配器并返回包装物件的情况并不少见,但您也可以有一个返回对包装物体的引用的as_inner