我使用Brotly-sys,但它似乎没有维护。所以我用Brotli。我做了一个压缩和解压缩的接口(我也使用lzma和zstd):
use std::io::{self, Write};
pub use brotli::writer::DecompressorWriter;
pub use brotli::enc::writer::CompressorWriter;
use super::Coder;
impl<W: Write> Coder<W> for DecompressorWriter<W> {
fn get_mut(&mut self) -> &mut W {
DecompressorWriter::get_mut(self)
}
fn finish(self) -> std::io::Result<W> {
DecompressorWriter::flush(&mut self).map_err(|_| {
io::Error::new(io::ErrorKind::Other, "brotli decoder failed to finalize stream")
});
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> Coder<W> for CompressorWriter<W> {
fn get_mut(&mut self) -> &mut W {
CompressorWriter::get_mut(self)
}
fn finish(self) -> std::io::Result<W> {
self.flush()?;
CompressorWriter::flush(&mut self).map_err(|_| {
io::Error::new(io::ErrorKind::Other, "brotli encoder failed to finalize stream")
})
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
但得到
error[E0308]: mismatched types
--> lib/src/codecs/brotli.rs:13:24
|
13 | fn finish(self) -> std::io::Result<W> {
| ------ ^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
= note: expected enum `std::result::Result<W, std::io::Error>`
found unit type `()`
error[E0308]: mismatched types
--> lib/src/codecs/brotli.rs:31:9
|
24 | impl<W: Write> Coder<W> for CompressorWriter<W> {
| - this type parameter
...
29 | fn finish(self) -> std::io::Result<W> {
| ------------------ expected `std::result::Result<W, std::io::Error>` because of return type
30 | self.flush()?;
31 | / CompressorWriter::flush(&mut self).map_err(|_| {
32 | | io::Error::new(io::ErrorKind::Other, "brotli encoder failed to finalize stream")
33 | | })
| |__________^ expected type parameter `W`, found `()`
|
= note: expected enum `std::result::Result<W, _>`
found enum `std::result::Result<(), _>`
但flush
函数不实现Write
特性。
Coder
接口在这里:https://github.com/Ludea/speedupdate-rs/blob/master/lib/src/codecs/mod.rs#L21
那么我该如何解决我的问题?(我可以提供GH repo这个问题)我在MacOS/Win64/Linux x86_64上得到这个问题。由于
您的Coder
特性与CompressorWriter
结构不兼容。您可能必须修改Coder
特征。
我假设Coder
的流程为:
- 创建实现
Coder
的压缩算法 - 通过调用
get_mut()
获取可变Write
对象。 - 写入对象
- 调用
finish()
,从其返回值中检索压缩数据。
你的trait强制get_mut()
的返回值与finish()
的返回值相同,这不是CompressorWriter
的情况。
你不需要为这个引入一个新的泛型;您可以简单地从get_mut()
函数返回&mut dyn Write
。这可能需要对Coder
的其他实现进行一些小调整,但应该可以工作。
次要旁注:我将get_mut()
重命名为get_input_writer()
,因为它与CompressorWriter::get_mut()
冲突,使处理它更加烦人。
use std::io::{self, Write};
pub use brotli::enc::writer::CompressorWriter;
pub use brotli::writer::DecompressorWriter;
trait Coder<W> {
fn get_input_writer(&mut self) -> &mut dyn Write;
fn finish(self) -> io::Result<W>;
fn finish_boxed(self: Box<Self>) -> io::Result<W>;
}
impl<W: Write> Coder<W> for CompressorWriter<W> {
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli encoder failed to finalize stream",
)
})?;
Ok(self.into_inner())
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> Coder<W> for DecompressorWriter<W> {
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})?;
self.into_inner().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
fn main() {
// Encode
let mut coder: Box<dyn Coder<_>> = Box::new(CompressorWriter::with_params(
Vec::new(),
1024,
&Default::default(),
));
coder.get_input_writer().write_all(b"Hello world!").unwrap();
let output = coder.finish_boxed().unwrap();
println!("{:?}", output);
// Decode
let mut decoder: Box<dyn Coder<_>> = Box::new(DecompressorWriter::new(Vec::new(), 1024));
decoder.get_input_writer().write_all(&output).unwrap();
let output = decoder.finish_boxed().unwrap();
println!("{:?}", String::from_utf8_lossy(&output));
}
[139, 5, 128, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 3]
"Hello world!"
当你在上面的时候,我也会改变一些其他的东西,为了方便:
- 将trait的泛型设置为关联类型。如果用户不能配置泛型,那么最好避免使用它们。
- 为方便添加
into_boxed_coder
功能
use std::io::{self, Write};
pub use brotli::enc::writer::CompressorWriter;
pub use brotli::writer::DecompressorWriter;
trait Coder {
type Out;
fn into_boxed_coder(self) -> Box<dyn Coder<Out = Self::Out>>
where
Self: Sized + 'static,
{
Box::new(self)
}
fn get_input_writer(&mut self) -> &mut dyn Write;
fn finish(self) -> io::Result<Self::Out>;
fn finish_boxed(self: Box<Self>) -> io::Result<Self::Out>;
}
impl<W: Write> Coder for CompressorWriter<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli encoder failed to finalize stream",
)
})?;
Ok(self.into_inner())
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> Coder for DecompressorWriter<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})?;
self.into_inner().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
fn main() {
// Encode
let mut coder =
CompressorWriter::with_params(Vec::new(), 1024, &Default::default()).into_boxed_coder();
coder.get_input_writer().write_all(b"Hello world!").unwrap();
let output = coder.finish_boxed().unwrap();
println!("{:?}", output);
// Decode
let mut decoder = DecompressorWriter::new(Vec::new(), 1024).into_boxed_coder();
decoder.get_input_writer().write_all(&output).unwrap();
let output = decoder.finish_boxed().unwrap();
println!("{:?}", String::from_utf8_lossy(&output));
}
[139, 5, 128, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 3]
"Hello world!"
下面是brotli
,zstd
和lzma
实现的更完整的示例:
use std::{
io::{self, Write},
ops::Deref,
};
trait Coder {
type Out;
fn into_boxed_coder(self) -> Box<dyn Coder<Out = Self::Out>>
where
Self: Sized + 'static,
{
Box::new(self)
}
fn get_input_writer(&mut self) -> &mut dyn Write;
fn finish(self) -> io::Result<Self::Out>;
fn finish_boxed(self: Box<Self>) -> io::Result<Self::Out>;
}
mod zstd {
use std::io::{self, Write};
use zstd::stream::{write::Decoder, write::Encoder};
impl<W: Write> super::Coder for Encoder<'static, W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(self) -> io::Result<W> {
self.finish()
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> super::Coder for Decoder<'static, W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush()?;
Ok(self.into_inner())
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
}
mod brotli {
use std::io::{self, Write};
pub use brotli::enc::writer::CompressorWriter;
pub use brotli::writer::DecompressorWriter;
impl<W: Write> super::Coder for CompressorWriter<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli encoder failed to finalize stream",
)
})?;
Ok(self.into_inner())
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> super::Coder for DecompressorWriter<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
self.flush().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})?;
self.into_inner().map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
"brotli decoder failed to finalize stream",
)
})
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
}
mod lzma {
use std::io::{self, Write};
pub use xz2::write::{XzDecoder, XzEncoder};
impl<W: Write> super::Coder for XzEncoder<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(self) -> io::Result<W> {
XzEncoder::finish(self)
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
impl<W: Write> super::Coder for XzDecoder<W> {
type Out = W;
fn get_input_writer(&mut self) -> &mut dyn Write {
self
}
fn finish(mut self) -> io::Result<W> {
XzDecoder::finish(&mut self)
}
fn finish_boxed(self: Box<Self>) -> io::Result<W> {
self.finish()
}
}
}
fn run_example<OutEncode, OutDecode>(
mut encoder: Box<dyn Coder<Out = OutEncode>>,
mut decoder: Box<dyn Coder<Out = OutDecode>>,
) where
OutEncode: Write + std::fmt::Debug + Deref<Target = [u8]>,
OutDecode: Write + Deref<Target = [u8]>,
{
// Encode
encoder
.get_input_writer()
.write_all(b"Hello world!")
.unwrap();
let output = encoder.finish_boxed().unwrap();
println!("{:?}", output);
// Decode
decoder.get_input_writer().write_all(&output).unwrap();
let output = decoder.finish_boxed().unwrap();
println!("{:?}", String::from_utf8_lossy(&output));
}
fn main() {
println!("zstd:");
run_example(
::zstd::stream::write::Encoder::new(Vec::new(), 0)
.unwrap()
.into_boxed_coder(),
::zstd::stream::write::Decoder::new(Vec::new())
.unwrap()
.into_boxed_coder(),
);
println!();
println!("brotli:");
run_example(
::brotli::enc::writer::CompressorWriter::with_params(Vec::new(), 1024, &Default::default())
.into_boxed_coder(),
::brotli::writer::DecompressorWriter::new(Vec::new(), 1024).into_boxed_coder(),
);
println!();
println!("lzma:");
run_example(
::xz2::write::XzEncoder::new(Vec::new(), 5).into_boxed_coder(),
::xz2::write::XzDecoder::new(Vec::new()).into_boxed_coder(),
);
println!();
}
zstd:
[40, 181, 47, 253, 0, 88, 97, 0, 0, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]
"Hello world!"
brotli:
[139, 5, 128, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 3]
"Hello world!"
lzma:
[253, 55, 122, 88, 90, 0, 0, 4, 230, 214, 180, 70, 2, 0, 33, 1, 22, 0, 0, 0, 116, 47, 229, 163, 1, 0, 11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 0, 10, 99, 214, 243, 246, 128, 91, 211, 0, 1, 36, 12, 166, 24, 216, 216, 31, 182, 243, 125, 1, 0, 0, 0, 0, 4, 89, 90]
"Hello world!"