use std::collections::BTreeSet;
use super::{encode_hashes, BloomFilter};
use crate::storage::parse;
use crate::ChangeHash;
#[allow(dead_code)]
const SYNC_STATE_TYPE: u8 = 0x43;
#[allow(dead_code)]
#[derive(Debug, thiserror::Error)]
pub(crate) enum DecodeError {
#[error("{0:?}")]
Parse(String),
#[error("wrong type: expected one of {expected_one_of:?} but found {found}")]
WrongType { expected_one_of: Vec<u8>, found: u8 },
#[error("not enough input")]
NotEnoughInput,
}
impl From<parse::leb128::Error> for DecodeError {
fn from(_: parse::leb128::Error) -> Self {
Self::Parse("bad leb128 encoding".to_string())
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub(crate) struct State {
pub(crate) shared_heads: Vec<ChangeHash>,
pub(crate) last_sent_heads: Vec<ChangeHash>,
pub(crate) their_heads: Option<Vec<ChangeHash>>,
pub(crate) their_need: Option<Vec<ChangeHash>>,
pub(crate) their_have: Option<Vec<Have>>,
pub(crate) sent_hashes: BTreeSet<ChangeHash>,
pub(crate) in_flight: bool,
pub(crate) have_responded: bool,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, serde::Serialize)]
pub(crate) struct Have {
pub(crate) last_sync: Vec<ChangeHash>,
pub(crate) bloom: BloomFilter,
}
impl State {
pub(crate) fn new() -> Self {
Default::default()
}
#[allow(dead_code)]
pub(crate) fn encode(&self) -> Vec<u8> {
let mut buf = vec![SYNC_STATE_TYPE];
encode_hashes(&mut buf, &self.shared_heads);
buf
}
#[allow(dead_code)]
pub(crate) fn decode(input: &[u8]) -> Result<Self, DecodeError> {
let input = parse::Input::new(input);
match Self::parse(input) {
Ok((_, state)) => Ok(state),
Err(parse::ParseError::Incomplete(_)) => Err(DecodeError::NotEnoughInput),
Err(parse::ParseError::Error(e)) => Err(e),
}
}
pub(crate) fn parse(input: parse::Input<'_>) -> parse::ParseResult<'_, Self, DecodeError> {
let (i, record_type) = parse::take1(input)?;
if record_type != SYNC_STATE_TYPE {
return Err(parse::ParseError::Error(DecodeError::WrongType {
expected_one_of: vec![SYNC_STATE_TYPE],
found: record_type,
}));
}
let (i, shared_heads) = parse::length_prefixed(parse::change_hash)(i)?;
Ok((
i,
Self {
shared_heads,
last_sent_heads: Vec::new(),
their_heads: None,
their_need: None,
their_have: Some(Vec::new()),
sent_hashes: BTreeSet::new(),
in_flight: false,
have_responded: false,
},
))
}
}