extern crate alloc;
use alloc::vec::Vec;
use crate::metis::dot::Dot;
use crate::metis::dot_set::{
DotSet, HAVE_SET_STATION_LEN, HAVE_SET_WIRE_HEADER_LEN, HaveSetDecodeBudget, HaveSetDecodeError,
};
use crate::metis::{Cut, VersionVector};
use super::super::gate::EpochAddress;
use super::error::WireCutError;
pub(super) const WIRE_DOT_LEN: usize = 12;
pub(super) const WIRE_ADDRESS_LEN: usize = 8 + WIRE_DOT_LEN;
pub(super) fn cut_embedding_len(vector: &VersionVector) -> usize {
HAVE_SET_WIRE_HEADER_LEN + vector.iter().count() * HAVE_SET_STATION_LEN
}
pub(super) fn encode_cut_into(out: &mut Vec<u8>, vector: &VersionVector) {
out.extend_from_slice(&DotSet::from_cut(vector).to_bytes());
}
pub(super) fn decode_cut(rest: &[u8]) -> Result<(VersionVector, &[u8]), WireCutError> {
let (set, tail) =
DotSet::from_prefix_with_budget(rest, HaveSetDecodeBudget::new(0)).map_err(|error| {
match error {
HaveSetDecodeError::RunTooLong { station, start, .. } => {
WireCutError::Gapped { station, start }
}
other => WireCutError::HaveSet(other),
}
})?;
Ok((Cut::floor_of(&set).as_vector().clone(), tail))
}
pub(super) fn read_u32(rest: &[u8]) -> Option<(u32, &[u8])> {
let word: [u8; 4] = rest.get(..4)?.try_into().ok()?;
Some((u32::from_be_bytes(word), &rest[4..]))
}
pub(super) fn read_u64(rest: &[u8]) -> Option<(u64, &[u8])> {
let word: [u8; 8] = rest.get(..8)?.try_into().ok()?;
Some((u64::from_be_bytes(word), &rest[8..]))
}
pub(super) fn read_dot(rest: &[u8]) -> Option<((u32, u64), &[u8])> {
let (station, rest) = read_u32(rest)?;
let (index, rest) = read_u64(rest)?;
Some(((station, index), rest))
}
pub(super) fn encode_dot_into(out: &mut Vec<u8>, dot: Dot) {
out.extend_from_slice(&dot.station().to_be_bytes());
out.extend_from_slice(&dot.counter().to_be_bytes());
}
pub(super) fn encode_address_into(out: &mut Vec<u8>, address: EpochAddress) {
out.extend_from_slice(&address.generation().to_be_bytes());
encode_dot_into(out, address.declaration());
}
pub(super) type AddressParts<'a> = ((u64, (u32, u64)), &'a [u8]);
pub(super) fn read_address_parts(rest: &[u8]) -> Option<AddressParts<'_>> {
let (generation, rest) = read_u64(rest)?;
let (dot, rest) = read_dot(rest)?;
Some(((generation, dot), rest))
}