use super::Error;
use crate::util;
use alloc::vec::Vec;
use core::{cmp, fmt, iter, slice};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AuraConsensusLogRef<'a> {
AuthoritiesChange(AuraAuthoritiesIter<'a>),
OnDisabled(u32),
}
impl<'a> AuraConsensusLogRef<'a> {
pub fn from_slice(slice: &'a [u8]) -> Result<Self, Error> {
Ok(match slice.first() {
Some(1) => {
AuraConsensusLogRef::AuthoritiesChange(AuraAuthoritiesIter::decode(&slice[1..])?)
}
Some(2) => {
let n = u32::from_le_bytes(
<[u8; 4]>::try_from(&slice[1..]).map_err(|_| Error::DigestItemDecodeError)?,
);
AuraConsensusLogRef::OnDisabled(n)
}
Some(_) => return Err(Error::BadAuraConsensusRefType),
None => return Err(Error::TooShort),
})
}
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
let index = iter::once(match self {
AuraConsensusLogRef::AuthoritiesChange(_) => [1],
AuraConsensusLogRef::OnDisabled(_) => [2],
});
let body = match self {
AuraConsensusLogRef::AuthoritiesChange(list) => {
let len = util::encode_scale_compact_usize(list.len());
either::Left(
iter::once(len)
.map(either::Left)
.chain(
list.clone()
.flat_map(|l| l.scale_encoding().map(either::Right)),
)
.map(either::Left),
)
}
AuraConsensusLogRef::OnDisabled(digest) => {
either::Right(iter::once(digest.to_le_bytes()).map(either::Right))
}
};
index.map(either::Left).chain(body.map(either::Right))
}
}
impl<'a> From<&'a AuraConsensusLog> for AuraConsensusLogRef<'a> {
fn from(a: &'a AuraConsensusLog) -> Self {
match a {
AuraConsensusLog::AuthoritiesChange(v) => AuraConsensusLogRef::AuthoritiesChange(
AuraAuthoritiesIter(AuraAuthoritiesIterInner::List(v.iter())),
),
AuraConsensusLog::OnDisabled(v) => AuraConsensusLogRef::OnDisabled(*v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AuraConsensusLog {
AuthoritiesChange(Vec<AuraAuthority>),
OnDisabled(u32),
}
impl<'a> From<AuraConsensusLogRef<'a>> for AuraConsensusLog {
fn from(a: AuraConsensusLogRef<'a>) -> Self {
match a {
AuraConsensusLogRef::AuthoritiesChange(v) => {
AuraConsensusLog::AuthoritiesChange(v.map(|a| a.into()).collect())
}
AuraConsensusLogRef::OnDisabled(v) => AuraConsensusLog::OnDisabled(v),
}
}
}
#[derive(Clone)]
pub struct AuraAuthoritiesIter<'a>(AuraAuthoritiesIterInner<'a>);
#[derive(Clone)]
enum AuraAuthoritiesIterInner<'a> {
List(slice::Iter<'a, AuraAuthority>),
Raw(slice::Chunks<'a, u8>),
}
impl<'a> AuraAuthoritiesIter<'a> {
pub fn decode(data: &'a [u8]) -> Result<Self, Error> {
let (data, num_items) = util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(data)
.map_err(|_| Error::TooShort)?;
if data.len()
!= num_items
.checked_mul(32)
.ok_or(Error::BadAuraAuthoritiesListLen)?
{
return Err(Error::BadAuraAuthoritiesListLen);
}
Ok(AuraAuthoritiesIter(AuraAuthoritiesIterInner::Raw(
data.chunks(32),
)))
}
pub fn from_slice(slice: &'a [AuraAuthority]) -> Self {
AuraAuthoritiesIter(AuraAuthoritiesIterInner::List(slice.iter()))
}
}
impl<'a> Iterator for AuraAuthoritiesIter<'a> {
type Item = AuraAuthorityRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.0 {
AuraAuthoritiesIterInner::List(l) => l.next().map(Into::into),
AuraAuthoritiesIterInner::Raw(l) => {
let item = l.next()?;
assert_eq!(item.len(), 32);
Some(AuraAuthorityRef {
public_key: <&[u8; 32]>::try_from(item).unwrap(),
})
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.0 {
AuraAuthoritiesIterInner::List(l) => l.size_hint(),
AuraAuthoritiesIterInner::Raw(l) => l.size_hint(),
}
}
}
impl<'a> ExactSizeIterator for AuraAuthoritiesIter<'a> {}
impl<'a> cmp::PartialEq<AuraAuthoritiesIter<'a>> for AuraAuthoritiesIter<'a> {
fn eq(&self, other: &AuraAuthoritiesIter<'a>) -> bool {
let mut a = self.clone();
let mut b = other.clone();
loop {
match (a.next(), b.next()) {
(Some(a), Some(b)) if a == b => {}
(None, None) => return true,
_ => return false,
}
}
}
}
impl<'a> cmp::Eq for AuraAuthoritiesIter<'a> {}
impl<'a> fmt::Debug for AuraAuthoritiesIter<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct AuraAuthorityRef<'a> {
pub public_key: &'a [u8; 32],
}
impl<'a> AuraAuthorityRef<'a> {
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
iter::once(self.public_key)
}
}
impl<'a> From<&'a AuraAuthority> for AuraAuthorityRef<'a> {
fn from(a: &'a AuraAuthority) -> Self {
AuraAuthorityRef {
public_key: &a.public_key,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct AuraAuthority {
pub public_key: [u8; 32],
}
impl<'a> From<AuraAuthorityRef<'a>> for AuraAuthority {
fn from(a: AuraAuthorityRef<'a>) -> Self {
AuraAuthority {
public_key: *a.public_key,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuraPreDigest {
pub slot_number: u64,
}
impl AuraPreDigest {
pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
if slice.len() != 8 {
return Err(Error::TooShort);
}
Ok(AuraPreDigest {
slot_number: u64::from_le_bytes(<[u8; 8]>::try_from(slice).unwrap()),
})
}
pub fn scale_encoding(&self) -> impl Iterator<Item = impl AsRef<[u8]> + Clone> + Clone {
iter::once(self.slot_number.to_le_bytes())
}
}