use crate::commands::{
responses::{Response, TypedResponseError},
Command,
};
use crate::raw::{Frame, RawCommandList};
use crate::sealed;
pub trait CommandList: sealed::Sealed {
type Response;
#[doc(hidden)]
fn to_raw_command_list(self) -> Option<RawCommandList>;
#[doc(hidden)]
fn parse_responses(frames: Vec<Frame>) -> Result<Self::Response, TypedResponseError>;
}
impl<C: Command> sealed::Sealed for Vec<C> {}
impl<C> CommandList for Vec<C>
where
C: Command,
{
type Response = Vec<C::Response>;
fn to_raw_command_list(self) -> Option<RawCommandList> {
let mut commands = self.into_iter().map(|c| c.to_command());
let mut raw_commands = RawCommandList::new(commands.next()?);
raw_commands.extend(commands);
Some(raw_commands)
}
fn parse_responses(frames: Vec<Frame>) -> Result<Self::Response, TypedResponseError> {
let frames = frames.into_iter();
let (lower, _) = frames.size_hint();
let mut out = Vec::with_capacity(lower);
for frame in frames {
out.push(<C::Response>::from_frame(frame)?);
}
Ok(out)
}
}
macro_rules! impl_command_list_tuple {
($first_type:ident, $($further_type:ident => $further_idx:tt),*) => {
impl<$first_type, $($further_type),*> sealed::Sealed for ($first_type, $($further_type),*)
where
$first_type: Command,
$(
$further_type: Command
),*
{}
impl<$first_type, $($further_type),*> CommandList for ($first_type, $($further_type),*)
where
$first_type: Command,
$(
$further_type: Command
),*
{
type Response = ($first_type::Response, $($further_type::Response),*);
fn to_raw_command_list(self) -> Option<RawCommandList> {
#[allow(unused_mut)]
let mut commands = RawCommandList::new(self.0.to_command());
$(
commands.add(self.$further_idx.to_command());
)*
Some(commands)
}
fn parse_responses(frames: Vec<Frame>) -> Result<Self::Response, TypedResponseError> {
let mut frames = frames.into_iter();
Ok((
<$first_type::Response>::from_frame(frames.next().unwrap())?,
$(
<$further_type::Response>::from_frame(frames.next().unwrap())?,
)*
))
}
}
};
}
impl_command_list_tuple!(A,);
impl_command_list_tuple!(A, B => 1);
impl_command_list_tuple!(A, B => 1, C => 2);
impl_command_list_tuple!(A, B => 1, C => 2, D => 3, E => 4);
impl_command_list_tuple!(A, B => 1, C => 2, D => 3, E => 4, F => 5);
impl_command_list_tuple!(A, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6);
impl_command_list_tuple!(A, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7);