Hello,
I'm playing with code, which simplified looks like this:
use std::io::Cursor;
use seek_test::*;
fn main() {
let w1: Vec<u8> = Vec::new();
let w2 = Cursor::new(Vec::<u8>::new());
let mut writer1 = Writer::new_unseekable(w1);
let mut writer2 = Writer::new(w2);
assert!(!writer1.check_can_seek());
assert!(writer2.check_can_seek());
writer1.write(b"abc").unwrap();
writer2.write(b"cde").unwrap();
assert_eq!(3, writer1.position().unwrap());
assert_eq!(3, writer2.position().unwrap());
// this cannot be achieved with trait object,
// because there is no way to own back type
// turned to trait object ?
let returned_w1 = writer1.unwrap();
let returned_w2 = writer2.unwrap().into_inner();
assert_eq!(b"abc", &returned_w1[..]);
assert_eq!(b"cde", &returned_w2[..]);
}
So basically I have type Writer
, which can contain other type than implements Write
. Now inner type may or may not implemented Seek
trait. I want to work with both, and for those that did not have Seek
capability to provide some workaround to get current position in stream (just by calculating written bytes). Also internally Writer
should behave slightly differently if inner can seek or not .
So I tried to implement - create a trait that abstracts common behaviour of inner stream, then Wrapper type for seekable and nonseekable types, which I put around true inner type and have impl to distinguish, which wrapper to use.
The code is here Polymorphism Rust · GitHub
My problem with this implementation is:
a) It's a lot of gluing code to make it work, so it rather intensive comparing to quite simple purpose
b) All supporting traits and structs must be public, because they leak into main type, which kind of breaks encapsulation
So I wonder if this approach is optional, if there could be easier, more elegant solution, or at least some partial improvements. Or maybe completely different approach.
I of course tried trait objects - see this code Polymorphism Rust · GitHub
It nicely hides implementation details, cause all machinery now can be private to module, but has couple of issues:
a) At the end I'd need to retain back full ownership of inner stream, with trait objects it does not seem to be available, as once turned to trait object I cannot get back ownership of original object (only reference via downcasting). Or am I missing something?
b) I would kind of prefer static dispatch in this case
So any ideas, comments, I'd like to see anything, thanks.