How do i do 'or' traits, or diffrent implementations of trait which vary because of a where cause of inner trait specification, i dont like only specifying S to be HandleWithDelims when I want it to also have an implementation which works with another trait HandleWithLength.
To fully explain.
My goal is to make a set of traits and trait implementations where someone can implement HandleWithDelims or HandleWithLength (I did not make this yet as I cant get the abstraction/separation working), and with these traits, someone can implement one, or the other one with a struct, preferably one as im fine if both implementations conflict, also specific implementations of a trait (StreamSender) get to pick what type of Handling it wants and all of the Frames will use that specific handling for encoding, RemoteFileSystem CAN NEVER have an idea to the two different traits/framing, as it would feel like a bad api. I attached the full (messy) code below.
Also I tried to enable the nightly feature of specializations, unfortunately it only lets you to chain something which does not implement a method from the trait and one more thing, so i cant have two traits to implement and pick via implementations for StreamSender.
pub trait HandleWithLength {
fn to_bytes(&self) -> Result<Vec<u8>, FileFrameStatus>;
}
pub trait HandleWithDelims {
// type FrameOutput;
fn to_bytes(
&self,
escape_byte: Option<u8>,
starting_delimiter: Option<Vec<u8>>,
ending_delimiter: Option<Vec<u8>>,
) -> Result<Vec<u8>, FileFrameStatus>;
// fn create_frame_handler() -> Self::FrameOutput;
}
impl HandleWithDelims for FileFrame {
// type FrameOutput = FrameEncoder;
fn to_bytes(
&self,
escape_byte: Option<u8>,
starting_delimiter: Option<Vec<u8>>,
ending_delimiter: Option<Vec<u8>>,
) -> Result<Vec<u8>, FileFrameStatus> {
let mut bytes_frame = Vec::new();
if let Some(ref direction) = self.direction {
bytes_frame.push(direction.clone() as u8);
} else {
return Err(FileFrameStatus::NotValidFrame);
}
if let Some(ref operation) = self.operation {
bytes_frame.push(operation.clone() as u8);
} else {
return Err(FileFrameStatus::NotValidFrame);
}
if let Some(ref codec) = self.codec {
bytes_frame.push(codec.clone() as u8);
} else {
return Err(FileFrameStatus::NotValidFrame);
}
if let Some(ref chunking_status) = self.chunking_status {
bytes_frame.push(chunking_status.clone() as u8);
} else {
return Err(FileFrameStatus::NotValidFrame);
}
let encoder = FrameEncoder::new(starting_delimiter, ending_delimiter, escape_byte);
bytes_frame = encoder.encode_bytes(bytes_frame, self.file_chunks.clone());
Ok(bytes_frame)
}
}
pub trait StreamSender {
async fn encode_frame<S>(&self, frame: S) -> Result<Vec<u8>, FileFrameStatus>
where
S: HandleWithDelims;
async fn send(&mut self, bytes: Vec<u8>);
}
impl StreamSender for TcpFsSender {
async fn encode_frame<S>(&self, frame: S) -> Result<Vec<u8>, FileFrameStatus>
where
S: HandleWithDelims,
{
frame.to_bytes(
self.escape_byte,
self.start_delimiter.clone(),
self.end_delimiter.clone(),
)
}
async fn send(&mut self, bytes: Vec<u8>) {
let res = self.tx.send_async(bytes).await;
println!("{:#?}", res);
}
}
impl <S: StreamSender + Default>RemoteFileSystem<S>
// where S: StreamSender
{
...
Full code: