You cannot use the HStream
type directly; it doesn't represent anything. It's only used to construct derived pointer types, such as &HStream
and Box<HStream>
.
The simplest solution would be to have a LinkedList
of Stream<Box<HStream>>
.
fn main() {
let mut list = Arc::new(Mutex::new(LinkedList::<Stream<Box<HStream>>>::new()));
}
Then, we just have to implement HStream
for Box<HStream>
.
impl<'a> HRecv for Box<HStream + 'a> {}
impl<'a> HSend for Box<HStream + 'a> {}
impl<'a> AsRawFd for Box<HStream + 'a> {
fn as_raw_fd(&self) -> RawFd { (&**self).as_raw_fd() }
}
impl<'a> HStream for Box<HStream + 'a> {}
Note that this is missing a trait... Clone
.
Clone
is not object-safe, which means that it's not possible to create trait object types for that trait, such as &Clone
or Box<Clone>
. Clone
is not object-safe because its clone
method returns Self
, which represents the concrete type of the implementor. If you used this method through a trait object, the compiler wouldn't be able to know in advance the type of the result (it could be any of Clone
's implementors!).
Since HStream
is a subtrait of Clone
, HStream
is not object-safe either. The consequence is that we can't implement Clone
at all, and types like Box<HStream>
are not legal to use.
However, we can work around this by making our own, object-safe trait. We can even automatically implement it on types that implement the standard Clone
trait.
pub trait BoxedHStreamClone {
fn boxed_clone(&self) -> Box<HStream>;
}
// Implementation for all types that implement HStream and Clone and don't hold any borrows
impl<T: HStream + Clone + 'static> BoxedHStreamClone for T {
fn boxed_clone(&self) -> Box<HStream> {
Box::new(self.clone()) as Box<HStream>
}
}
// Implementation for Box<HStream + 'a>, which cannot implement Clone
impl<'a> BoxedHStreamClone for Box<HStream + 'a> {
fn boxed_clone(&self) -> Box<HStream> {
Box::new((&**self).boxed_clone()) as Box<HStream>
}
}
Replace the Clone
trait bound on HStream
with BoxedHStreamClone
and you're good to go!
pub trait HStream: HRecv + HSend + AsRawFd + BoxedHStreamClone {}
Here's the final code:
use std::sync::{Arc, Mutex};
use std::collections::LinkedList;
use std::os::unix::io::{RawFd, AsRawFd};
pub trait BoxedHStreamClone {
fn boxed_clone(&self) -> Box<HStream>;
}
impl<T: HStream + Clone + 'static> BoxedHStreamClone for T {
fn boxed_clone(&self) -> Box<HStream> {
Box::new(self.clone()) as Box<HStream>
}
}
pub trait HRecv {}
pub trait HSend {}
pub trait HStream: HRecv + HSend + AsRawFd + BoxedHStreamClone {}
pub struct Stream<T: HStream> {
pub inner: T
}
pub type StreamList = Arc<Mutex<LinkedList<Stream<Box<HStream>>>>>;
impl<'a> HRecv for Box<HStream + 'a> {}
impl<'a> HSend for Box<HStream + 'a> {}
impl<'a> AsRawFd for Box<HStream + 'a> {
fn as_raw_fd(&self) -> RawFd { (&**self).as_raw_fd() }
}
impl<'a> BoxedHStreamClone for Box<HStream + 'a> {
fn boxed_clone(&self) -> Box<HStream> {
Box::new((&**self).boxed_clone()) as Box<HStream>
}
}
impl<'a> HStream for Box<HStream + 'a> {}
fn main() {
let mut list = Arc::new(Mutex::new(LinkedList::<Stream<Box<HStream>>>::new()));
}