use crate::{finality, header};
use alloc::vec::Vec;
#[derive(Debug)]
pub struct GrandpaWarpSyncResponse<'a> {
pub fragments: Vec<GrandpaWarpSyncResponseFragment<'a>>,
pub is_finished: bool,
}
#[derive(Debug)]
pub struct GrandpaWarpSyncResponseFragment<'a> {
pub scale_encoded_header: &'a [u8],
pub scale_encoded_justification: &'a [u8],
}
#[derive(Debug, derive_more::Display, derive_more::Error)]
#[display("Failed to decode response")]
pub struct DecodeGrandpaWarpSyncResponseError;
pub fn decode_grandpa_warp_sync_response(
encoded: &'_ [u8],
block_number_bytes: usize,
) -> Result<GrandpaWarpSyncResponse<'_>, DecodeGrandpaWarpSyncResponseError> {
nom::Parser::parse(
&mut nom::combinator::all_consuming::<_, (&[u8], nom::error::ErrorKind), _>(
nom::combinator::map(
(
decode_fragments(block_number_bytes),
nom::number::streaming::le_u8,
),
|(fragments, is_finished)| GrandpaWarpSyncResponse {
fragments,
is_finished: is_finished != 0,
},
),
),
encoded,
)
.map(|(_, parse_result)| parse_result)
.map_err(|_| DecodeGrandpaWarpSyncResponseError)
}
fn decode_fragments<'a, E: nom::error::ParseError<&'a [u8]>>(
block_number_bytes: usize,
) -> impl nom::Parser<&'a [u8], Output = Vec<GrandpaWarpSyncResponseFragment<'a>>, Error = E> {
nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
nom::multi::many_m_n(num_elems, num_elems, decode_fragment(block_number_bytes))
})
}
fn decode_fragment<'a, E: nom::error::ParseError<&'a [u8]>>(
block_number_bytes: usize,
) -> impl nom::Parser<&'a [u8], Output = GrandpaWarpSyncResponseFragment<'a>, Error = E> {
nom::combinator::map(
(
nom::combinator::recognize(move |s| {
header::decode_partial(s, block_number_bytes)
.map(|(a, b)| (b, a))
.map_err(|_| {
nom::Err::Failure(nom::error::make_error(s, nom::error::ErrorKind::Verify))
})
}),
nom::combinator::recognize(move |s| {
finality::decode::decode_partial_grandpa_justification(s, block_number_bytes)
.map(|(a, b)| (b, a))
.map_err(|_| {
nom::Err::Failure(nom::error::make_error(s, nom::error::ErrorKind::Verify))
})
}),
),
move |(scale_encoded_header, scale_encoded_justification)| {
GrandpaWarpSyncResponseFragment {
scale_encoded_header,
scale_encoded_justification,
}
},
)
}