use super::prove::{count_under, under};
use super::{CarriedTokens, ClosureIssue, PartitionCargo, PartitionedEmission};
use crate::identity::{encode_bytes, encode_length};
use crate::kind::{Destination, Role};
use crate::plan::Membership;
use crate::render::RenderedProjection;
const NOTHING_PLANNED: u8 = 0;
const CARRIED: u8 = 1;
const NOT_JOINED: u8 = 2;
pub(super) fn claim<R: Role>(
planned: &Membership<R>,
rendered: &RenderedProjection<R>,
emission: &PartitionedEmission,
) -> Vec<u8> {
let mut material = Vec::new();
planned.encode_into(&mut material);
encode_length(R::ALL.len(), &mut material);
for role in R::ALL {
material.extend_from_slice(&role.slot().to_be_bytes());
encode_length(count_under(rendered, *role), &mut material);
if let Some(unit) = under(rendered, *role) {
encode_bytes(unit.identity().as_bytes(), &mut material);
encode_bytes(unit.digest().as_bytes(), &mut material);
}
}
emission.encode_into(&mut material);
material
}
impl PartitionedEmission {
fn encode_into(&self, into: &mut Vec<u8>) {
encode_length(Destination::ALL.len(), into);
for destination in Destination::ALL {
encode_bytes(destination.name().as_bytes(), into);
if let Some(cargo) = self.joined(*destination) {
cargo.encode_into(into);
} else {
into.push(NOT_JOINED);
encode_bytes(&[], into);
}
}
}
}
impl PartitionCargo {
fn encode_into(&self, into: &mut Vec<u8>) {
match self {
Self::NothingPlanned => {
into.push(NOTHING_PLANNED);
encode_bytes(&[], into);
}
Self::Carried(carried) => {
into.push(CARRIED);
carried.encode_into(into);
}
}
}
}
impl CarriedTokens {
fn encode_into(&self, into: &mut Vec<u8>) {
encode_bytes(self.digest().as_bytes(), into);
}
}
impl<R: Role> ClosureIssue<R> {
#[must_use]
pub fn canonical_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
self.encode_into(&mut bytes);
bytes
}
pub fn encode_into(&self, into: &mut Vec<u8>) {
into.push(self.slot());
let mut material = Vec::new();
self.material_into(&mut material);
encode_bytes(&material, into);
}
fn material_into(&self, into: &mut Vec<u8>) {
match self {
Self::MemberMissing { role }
| Self::MemberUnplanned { role }
| Self::OriginOrphan { role }
| Self::DigestMismatch { role }
| Self::SemanticKeyMismatch { role }
| Self::MaterializationMismatch { role }
| Self::MembershipDisagreement { role }
| Self::ArtifactAddressAbsent { role } => seat_into(*role, into),
Self::MemberDuplicated { role, observed }
| Self::MemberPlannedTwice { role, observed } => {
seat_into(*role, into);
into.extend_from_slice(&observed.to_be_bytes());
}
Self::ReconstructionEmpty => {}
Self::ReconstructionUndeclarable { observed } => {
into.extend_from_slice(&observed.to_be_bytes());
}
Self::JoinedTreeUnbounded { destination } => {
encode_bytes(destination.name().as_bytes(), into);
}
Self::ArtifactAddressDoubled { role, address } => {
seat_into(*role, into);
encode_bytes(&address.citation_bytes(), into);
}
}
}
}
fn seat_into<R: Role>(role: R, into: &mut Vec<u8>) {
into.extend_from_slice(&role.slot().to_be_bytes());
}