1use massa_serialization::{
4 Deserializer, SerializeError, Serializer, U32VarIntDeserializer, U32VarIntSerializer,
5 U64VarIntDeserializer, U64VarIntSerializer,
6};
7use nom::branch::alt;
8use nom::bytes::complete::tag;
9use nom::combinator::value;
10use nom::error::context;
11use nom::error::{ContextError, ParseError};
12use nom::multi::length_count;
13use nom::sequence::tuple;
14use nom::{IResult, Parser};
15use serde::{Deserialize, Serialize};
16
17use crate::block_id::{BlockId, BlockIdDeserializer, BlockIdSerializer};
18use crate::prehash::PreHashSet;
19use std::ops::Bound::{Excluded, Included};
20
21#[derive(Clone, Debug, Deserialize, Serialize)]
23pub struct Clique {
24 pub block_ids: PreHashSet<BlockId>,
26 pub fitness: u64,
29 pub is_blockclique: bool,
31}
32
33impl Default for Clique {
34 fn default() -> Self {
35 Clique {
36 block_ids: Default::default(),
37 fitness: 0,
38 is_blockclique: true,
39 }
40 }
41}
42
43#[derive(Default)]
45pub struct CliqueSerializer {
46 block_ids_length_serializer: U32VarIntSerializer,
47 fitness_serializer: U64VarIntSerializer,
48 block_id_serializer: BlockIdSerializer,
49}
50
51impl CliqueSerializer {
52 pub fn new() -> Self {
54 Self {
55 block_ids_length_serializer: U32VarIntSerializer::new(),
56 fitness_serializer: U64VarIntSerializer::new(),
57 block_id_serializer: BlockIdSerializer::new(),
58 }
59 }
60}
61
62impl Serializer<Clique> for CliqueSerializer {
63 fn serialize(&self, value: &Clique, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
83 self.block_ids_length_serializer
84 .serialize(&(value.block_ids.len() as u32), buffer)?;
85 for block_id in &value.block_ids {
86 self.block_id_serializer.serialize(block_id, buffer)?;
87 }
88 self.fitness_serializer.serialize(&value.fitness, buffer)?;
89 buffer.push(u8::from(value.is_blockclique));
90 Ok(())
91 }
92}
93
94pub struct CliqueDeserializer {
96 block_ids_length_deserializer: U32VarIntDeserializer,
97 block_id_deserializer: BlockIdDeserializer,
98 fitness_deserializer: U64VarIntDeserializer,
99}
100
101impl CliqueDeserializer {
102 pub fn new(max_bootstrap_blocks: u32) -> Self {
104 Self {
105 block_ids_length_deserializer: U32VarIntDeserializer::new(
106 Included(0),
107 Excluded(max_bootstrap_blocks),
108 ),
109 block_id_deserializer: BlockIdDeserializer::new(),
110 fitness_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
111 }
112 }
113}
114
115impl Deserializer<Clique> for CliqueDeserializer {
116 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
141 &self,
142 buffer: &'a [u8],
143 ) -> IResult<&'a [u8], Clique, E> {
144 context(
145 "Failed Clique deserialization",
146 tuple((
147 length_count(
148 context("Failed length deserialization", |input| {
149 self.block_ids_length_deserializer.deserialize(input)
150 }),
151 context("Failed block_id deserialization", |input| {
152 self.block_id_deserializer.deserialize(input)
153 }),
154 ),
155 context("Failed fitness deserialization", |input| {
156 self.fitness_deserializer.deserialize(input)
157 }),
158 context(
159 "Failed is_blockclique deserialization",
160 alt((
161 value(true, |input| tag(&[1u8])(input)),
162 value(false, |input| tag(&[0u8])(input)),
163 )),
164 ),
165 )),
166 )
167 .map(|(block_ids, fitness, is_blockclique)| Clique {
168 block_ids: block_ids.into_iter().collect(),
169 fitness,
170 is_blockclique,
171 })
172 .parse(buffer)
173 }
174}