Rust 使用带缓冲区的Snappy压缩

Rust 使用带缓冲区的Snappy压缩,rust,snappy,Rust,Snappy,我正试图找出最好的方法来使用缓冲和防锈。之前,我正在使用写入文件。但是现在我想添加压缩。上述snappy板条箱的compress功能需要一个和[u8]作为参数,但BufWriter不会让我访问其缓冲区以传递给snappy。我已经研究了两种方法来解决这个问题 在第一种方法中,我使用一个向量(具有_容量)而不是BufWriter作为缓冲区,并创建了一个写函数,该函数将确保写入向量不会导致它重新分配。如果需要,我会压缩缓冲区中当前的内容,然后将其写入文件并释放向量(drain函数)。我是根据BufWr

我正试图找出最好的方法来使用缓冲和防锈。之前,我正在使用写入文件。但是现在我想添加压缩。上述snappy板条箱的
compress
功能需要一个
和[u8]
作为参数,但
BufWriter
不会让我访问其缓冲区以传递给snappy。我已经研究了两种方法来解决这个问题

在第一种方法中,我使用一个向量(具有_容量)而不是
BufWriter
作为缓冲区,并创建了一个写函数,该函数将确保写入向量不会导致它重新分配。如果需要,我会压缩缓冲区中当前的内容,然后将其写入文件并释放向量(drain函数)。我是根据BufWriter所做的工作写这篇文章的。缺点是,由于它是一个向量,如果缓冲区超出范围,它不会自动将缓冲区刷新到文件中。我必须在编写文件的范围内手动执行此操作,这是我不喜欢的

另一方面,我或多或少地复制了
BufWriter
源代码,并在将其输出到文件之前更改了
flush
函数以压缩其缓冲区(向量)。这种方式似乎是最好的,但我只是不喜欢复制代码的想法

处理这两个选项或其他选项的最佳方式是什么


如果相关,我写入缓冲区的对象总是相同的大小,并且我的缓冲区大小是对象大小的倍数。

因为snappy看起来需要一次压缩所有对象,所以您只需要将所有对象缓冲到最后。然后,可以在末尾刷新和压缩:

use std::io::{self, Write, Cursor};

fn compress(_data: &[u8]) -> Vec<u8> {
    // The best compression ever
    b"compressed".as_ref().into()
}

struct SnappyCompressor<W> {
    inner: W,
    buffer: Vec<u8>,
}

impl<W> SnappyCompressor<W>
    where W: Write
{
    fn new(inner: W) -> Self {
        SnappyCompressor {
            inner: inner,
            buffer: vec![],
        }
    }
}

impl<W> Write for SnappyCompressor<W>
    where W: Write
{
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.buffer.extend(data);
        Ok(data.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        let compressed = compress(&self.buffer);
        self.inner.write_all(&compressed)
    }
}

fn main() {
    let mut output = Cursor::new(vec![]);
    {
        let mut compressor = SnappyCompressor::new(output.by_ref());
        assert_eq!(5, compressor.write(b"hello").unwrap());
        assert_eq!(5, compressor.write(b"world").unwrap());
        compressor.flush().unwrap();
    }
    let bytes = output.into_inner();
    assert_eq!(&b"compressed"[..], &bytes[..]);
}
为了防止尝试刷新两次,您需要添加一个标记来跟踪:

fn write(&mut self, data: &[u8]) -> io::Result<usize> {
    if self.is_flushed {
        return Err(Error::new(ErrorKind::Other, "Buffer has already been compressed, cannot add more data"));
    }

    self.buffer.extend(data);
    Ok(data.len())
}

fn flush(&mut self) -> io::Result<()> {
    if self.is_flushed {
        return Ok(())
    }

    self.is_flushed = true;
    let compressed = compress(&self.buffer);
    self.inner.write_all(&compressed)
}
fn写入(&mut self,数据:&[u8])->io::结果{
如果self.u被刷新{
返回Err(Error::new(ErrorKind::Other,“缓冲区已被压缩,无法添加更多数据”);
}
self.buffer.extend(数据);
Ok(data.len())
}
fn刷新(&mut self)->io::结果{
如果self.u被刷新{
返回Ok(())
}
self.is_=true;
let compressed=压缩(&self.buffer);
self.internal.write_all(&压缩)
}
总而言之,最终版本如下所示:

use std::io::{self, Write, Cursor, Error, ErrorKind};

fn compress(_data: &[u8]) -> Vec<u8> {
    // The best compression ever
    b"compressed".as_ref().into()
}

struct SnappyCompressor<W>
    where W: Write
{
    inner: W,
    buffer: Vec<u8>,
    is_flushed: bool,
}

impl<W> SnappyCompressor<W>
    where W: Write
{
    fn new(inner: W) -> Self {
        SnappyCompressor {
            inner: inner,
            buffer: vec![],
            is_flushed: false,
        }
    }

    // fn into_inner
}

impl<W> Write for SnappyCompressor<W>
    where W: Write
{
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        if self.is_flushed {
            return Err(Error::new(ErrorKind::Other, "Buffer has already been compressed, cannot add more data"));
        }

        self.buffer.extend(data);
        Ok(data.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        if self.is_flushed {
            return Ok(())
        }

        self.is_flushed = true;
        let compressed = compress(&self.buffer);
        self.inner.write_all(&compressed)
    }
}

impl<W> Drop for SnappyCompressor<W>
    where W: Write
{
    fn drop(&mut self) {
        self.flush().unwrap();
    }
}

fn main() {
    let mut output = Cursor::new(vec![]);
    {
        let mut compressor = SnappyCompressor::new(output.by_ref());
        assert_eq!(5, compressor.write(b"hello").unwrap());
        assert_eq!(5, compressor.write(b"world").unwrap());
        compressor.flush().unwrap();
    }
    let bytes = output.into_inner();
    assert_eq!(&b"compressed"[..], &bytes[..]);
}
使用std::io:{self,Write,Cursor,Error,ErrorKind};
fn压缩(_数据:&[u8])->Vec{
//有史以来最好的压缩
b“compressed”。as_ref()
}
结构SnappyCompressor
W:写在哪里
{
内部:W,
缓冲区:Vec,
你脸红了吗,
}
impl Snappy压缩机
W:写在哪里
{
fn新(内部:W)->自{
快速压缩机{
内:内,
缓冲区:vec![],
是:错,
}
}
//fn进入_内部
}
SnappyCompressor的impl写入
W:写在哪里
{
fn写入(&mut self,数据:&[u8])->io::结果{
如果self.u被刷新{
返回Err(Error::new(ErrorKind::Other,“缓冲区已被压缩,无法添加更多数据”);
}
self.buffer.extend(数据);
Ok(data.len())
}
fn刷新(&mut self)->io::结果{
如果self.u被刷新{
返回Ok(())
}
self.is_=true;
let compressed=压缩(&self.buffer);
self.internal.write_all(&压缩)
}
}
Snappy压缩机的impl下降
W:写在哪里
{
fn下降(&mut自我){
self.flush().unwrap();
}
}
fn main(){
让mut output=Cursor::new(vec![]);
{
让mut compressor=SnappyCompressor::new(output.by_ref());
assert_eq!(5,compressor.write(b“hello”).unwrap());
断言(5,compressor.write(b“world”).unwrap());
压缩机。冲洗()。展开();
}
让bytes=output.into_inner();
assert_eq!(&b“compressed”[…],&bytes[…]);
}

snappy与压缩多个缓冲区然后将它们打包在一起兼容吗?函数签名似乎表明它希望一次压缩和解压缩所有内容。如果是这样的话,您需要将所有内容缓冲(放入
Vec
),然后在最后压缩所有内容。您是对的。我最初认为,因为我知道未压缩的大小是恒定的,所以我也能够分离缓冲区并逐个解压缩它们。但是知道未压缩的大小对我没有帮助,因为压缩的大小不是恒定的。我将尝试使用
Vec,u8>
,看看这对性能有何影响。谢谢另外,我应该如何处理这个问题?我应该删除它,还是有没有一种方法可以在不选择答案的情况下将其标记为已解决?我认为你提问的方式有答案,因此我将在接下来的一两个小时内发布我的答案。答案并不完全符合你的要求:-)这看起来很好,或多或少回答了我的问题。我会试试这个,还有别的,看看他们的表现如何。再次感谢!
use std::io::{self, Write, Cursor, Error, ErrorKind};

fn compress(_data: &[u8]) -> Vec<u8> {
    // The best compression ever
    b"compressed".as_ref().into()
}

struct SnappyCompressor<W>
    where W: Write
{
    inner: W,
    buffer: Vec<u8>,
    is_flushed: bool,
}

impl<W> SnappyCompressor<W>
    where W: Write
{
    fn new(inner: W) -> Self {
        SnappyCompressor {
            inner: inner,
            buffer: vec![],
            is_flushed: false,
        }
    }

    // fn into_inner
}

impl<W> Write for SnappyCompressor<W>
    where W: Write
{
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        if self.is_flushed {
            return Err(Error::new(ErrorKind::Other, "Buffer has already been compressed, cannot add more data"));
        }

        self.buffer.extend(data);
        Ok(data.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        if self.is_flushed {
            return Ok(())
        }

        self.is_flushed = true;
        let compressed = compress(&self.buffer);
        self.inner.write_all(&compressed)
    }
}

impl<W> Drop for SnappyCompressor<W>
    where W: Write
{
    fn drop(&mut self) {
        self.flush().unwrap();
    }
}

fn main() {
    let mut output = Cursor::new(vec![]);
    {
        let mut compressor = SnappyCompressor::new(output.by_ref());
        assert_eq!(5, compressor.write(b"hello").unwrap());
        assert_eq!(5, compressor.write(b"world").unwrap());
        compressor.flush().unwrap();
    }
    let bytes = output.into_inner();
    assert_eq!(&b"compressed"[..], &bytes[..]);
}