use super::{
Account, Context, ContradictionPair, DigestContract, InvalidationTrigger, Membership,
PlanIssue, PlannedMember, PlannedOutput,
};
use crate::identity::{self, Identity, encode_bytes, encode_length};
use crate::kind::{Kind, Role};
fn capture_into(captured: &Identity<identity::CapturedDeclaration>, into: &mut Vec<u8>) {
encode_bytes(captured.as_bytes(), into);
}
impl<K: Kind> Account<K> {
#[must_use]
pub fn intent_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
self.intent_into(&mut bytes);
bytes
}
pub fn encode_into(&self, into: &mut Vec<u8>) {
self.intent_into(into);
encode_set(self.dependencies().iter(), capture_into, into);
}
fn intent_into(&self, into: &mut Vec<u8>) {
encode_bytes(self.kind().as_bytes(), into);
encode_bytes(self.content_commitment().as_bytes(), into);
}
}
impl Context {
pub fn encode_into(&self, into: &mut Vec<u8>) {
self.profile().encode_into(into);
encode_bytes(self.generator().as_bytes(), into);
}
}
impl InvalidationTrigger {
pub fn encode_into(&self, into: &mut Vec<u8>) {
into.push(self.slot());
match self {
Self::CapturedDeclaration { watched } => encode_bytes(watched.as_bytes(), into),
Self::Profile { watched } => watched.encode_into(into),
Self::Generator { watched } => encode_bytes(watched.as_bytes(), into),
Self::ProjectionContent { watched } => encode_bytes(watched.as_bytes(), into),
Self::Declared { name, watched } => {
encode_bytes(name.as_bytes(), into);
encode_bytes(&watched.citation_bytes(), into);
}
}
}
}
impl DigestContract {
pub fn encode_into(&self, into: &mut Vec<u8>) {
encode_bytes(self.anchored_to.as_bytes(), into);
}
}
impl PlannedOutput {
pub fn encode_into(&self, into: &mut Vec<u8>) {
encode_bytes(self.semantic_key.as_bytes(), into);
self.origin.encode_into(into);
self.expected_profile.encode_into(into);
match self.address {
None => {
into.push(0);
encode_bytes(&[], into);
}
Some(address) => {
into.push(1);
encode_bytes(&address.citation_bytes(), into);
}
}
self.digest_contract.encode_into(into);
}
}
impl<R: Role> PlannedMember<R> {
pub fn encode_into(&self, into: &mut Vec<u8>) {
into.extend_from_slice(&self.role.slot().to_be_bytes());
self.output.encode_into(into);
}
}
impl<R: Role> Membership<R> {
pub fn encode_into(&self, into: &mut Vec<u8>) {
encode_length(R::ALL.len(), into);
for role in R::ALL {
into.extend_from_slice(&role.slot().to_be_bytes());
let under: Vec<&PlannedMember<R>> = self.members_under(*role).collect();
encode_length(under.len(), into);
for member in under {
member.encode_into(into);
}
}
}
}
impl ContradictionPair {
fn encode_into(&self, into: &mut Vec<u8>) {
encode_bytes(&self.left.citation_bytes(), into);
encode_bytes(&self.right.citation_bytes(), into);
}
}
impl PlanIssue {
#[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::ContradictoryFacts { between } => between.encode_into(into),
Self::UnknownKind { named } => encode_bytes(named.as_bytes(), into),
Self::ProfileUnsupported { profile } => profile.encode_into(into),
Self::BoundExceeded {
axis,
bound,
observed,
} => {
into.push(axis.slot());
into.extend_from_slice(&bound.to_be_bytes());
into.extend_from_slice(&observed.to_be_bytes());
}
Self::MembershipIncomplete { absent } => encode_bytes(absent.as_bytes(), into),
Self::OrphanGeneratedNode { node } => encode_bytes(node.as_bytes(), into),
Self::MembershipDoubled {
role_slot,
observed,
} => {
into.extend_from_slice(&role_slot.to_be_bytes());
into.extend_from_slice(&observed.to_be_bytes());
}
Self::TrailDiscontinuous { at } => into.extend_from_slice(&at.to_be_bytes()),
Self::CauseSetUnwatchable { named, watchable } => {
into.extend_from_slice(&named.to_be_bytes());
into.extend_from_slice(&watchable.to_be_bytes());
}
Self::MembershipForeign { seat } | Self::AddressInert { seat } => {
encode_bytes(seat.as_bytes(), into);
}
}
}
}
pub(super) fn encode_set<'member, T: 'member, Encode>(
members: impl Iterator<Item = &'member T>,
encode: Encode,
into: &mut Vec<u8>,
) where
Encode: Fn(&T, &mut Vec<u8>),
{
let mut encoded: Vec<Vec<u8>> = members
.map(|member| {
let mut bytes = Vec::new();
encode(member, &mut bytes);
bytes
})
.collect();
encoded.sort_unstable();
encode_length(encoded.len(), into);
for member in &encoded {
encode_bytes(member, into);
}
}