I've implemented a WriteAt
trait, that requires you to always give a position for the write.To work with the ecosystem I've created a CursorAt
wrapper that implements Write
:
pub struct CursorAt<T> {
inner: T,
position: u64,
}
impl<T> CursorAt<T> {
pub fn new(inner: T, position: u64) -> Self {
Self { inner, position }
}
}
impl<T: WriteAt> Write for CursorAt<T> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.inner.write_slice_at(&mut self.position, buf).unwrap();
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
When trying to use the CursorAt
type with the flate2
crate:
fn compressed_to_file(writer: &mut (impl WriteAt + ?Sized), position: &mut u64) {
let cursor = CursorAt::new(writer, *position);
let mut encoder = ZlibEncoder::new(cursor, Compression::best());
encoder.write_all(&file).unwrap();
let cursor = encoder.finish().unwrap();
}
However the compiler tells me that WriteAt
is not implemented for &mut impl WriteAt + ?Sized
, which seems weird:
error[E0277]: the trait bound `&mut impl WriteAt + ?Sized: WriteAt` is not satisfied
--> ubiart_toolkit/src/ipk/writer.rs:191:56
|
191 | let mut encoder = ZlibEncoder::new(cursor, Compression::best());
| ---------------- ^^^^^^ the trait `WriteAt` is not implemented for `&mut impl WriteAt + ?Sized`, which is required by `CursorAt<&mut impl WriteAt + ?Sized>: std::io::Write`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `WriteAt`:
File
std::vec::Vec<u8>
= note: required for `CursorAt<&mut impl WriteAt + ?Sized>` to implement `std::io::Write`
note: required by a bound in `flate2::write::ZlibEncoder::<W>::new`
--> flate2-1.0.28/src/zlib/write.rs:35:9
|
35 | impl<W: Write> ZlibEncoder<W> {
| ^^^^^ required by this bound in `ZlibEncoder::<W>::new`
...
41 | pub fn new(w: W, level: crate::Compression) -> ZlibEncoder<W> {
| --- required by a bound in this associated function
What can I do to fix this?
I've tried to implement WriteAt
for &mut WriteAt
but that loops forever and I can't figure out how to tell the compiler to use the write_slice_at
from the &mut T
:
impl<T: WriteAt + ?Sized> WriteAt for &mut T {
fn write_slice_at(&mut self, position: &mut u64, buf: &[u8]) -> Result<(), WriteError> {
self.write_slice_at(position, buf)
}
}
P.S. This code is extracted from a much larger codebase, which is why it's a bit convoluted. The CursorAt
type is also used to wrap my ReadAt
implementation for Read
, which is why the new
function doesn't have trait bounds. I've also replaced some of the error handling with unwraps
to make the code more compact.