use std::collections::BTreeSet;
use aluvm::library::{Lib, LibId};
use amplify::confinement::ConfinedOrdMap;
use bitcoin::Txid;
use strict_types::TypeSystem;
use super::EAnchor;
use crate::{
AssignmentType, AssignmentsRef, BundleId, ContractId, Genesis, GlobalState, GraphSeal,
Metadata, OpFullType, OpId, Operation, Schema, Transition, TransitionBundle, TypedAssigns,
};
pub const CONSIGNMENT_MAX_LIBS: usize = 1024;
pub type Scripts = ConfinedOrdMap<LibId, Lib, 0, CONSIGNMENT_MAX_LIBS>;
#[derive(Copy, Clone, PartialEq, Eq, Debug, From)]
pub enum OpRef<'op> {
#[from]
Genesis(&'op Genesis),
#[from]
Transition(&'op Transition),
}
impl<'op> Operation for OpRef<'op> {
fn full_type(&self) -> OpFullType {
match self {
Self::Genesis(op) => op.full_type(),
Self::Transition(op) => op.full_type(),
}
}
fn id(&self) -> OpId {
match self {
Self::Genesis(op) => op.id(),
Self::Transition(op) => op.id(),
}
}
fn contract_id(&self) -> ContractId {
match self {
Self::Genesis(op) => op.contract_id(),
Self::Transition(op) => op.contract_id(),
}
}
fn nonce(&self) -> u64 {
match self {
Self::Genesis(op) => op.nonce(),
Self::Transition(op) => op.nonce(),
}
}
fn metadata(&self) -> &Metadata {
match self {
Self::Genesis(op) => op.metadata(),
Self::Transition(op) => op.metadata(),
}
}
fn globals(&self) -> &GlobalState {
match self {
Self::Genesis(op) => op.globals(),
Self::Transition(op) => op.globals(),
}
}
fn assignments(&self) -> AssignmentsRef<'op> {
match self {
Self::Genesis(op) => (&op.assignments).into(),
Self::Transition(op) => (&op.assignments).into(),
}
}
fn assignments_by_type(&self, t: AssignmentType) -> Option<TypedAssigns<GraphSeal>> {
match self {
Self::Genesis(op) => op.assignments_by_type(t),
Self::Transition(op) => op.assignments_by_type(t),
}
}
}
pub struct CheckedConsignment<'consignment, C: ConsignmentApi>(&'consignment C);
impl<'consignment, C: ConsignmentApi> CheckedConsignment<'consignment, C> {
pub fn new(consignment: &'consignment C) -> Self { Self(consignment) }
}
impl<C: ConsignmentApi> ConsignmentApi for CheckedConsignment<'_, C> {
fn schema(&self) -> &Schema { self.0.schema() }
fn types(&self) -> &TypeSystem { self.0.types() }
fn scripts(&self) -> impl Iterator<Item = &Lib> { self.0.scripts() }
fn genesis(&self) -> &Genesis { self.0.genesis() }
fn bundles_info(&self) -> impl Iterator<Item = (&TransitionBundle, &EAnchor, Txid)> {
self.0.bundles_info()
}
}
pub trait ConsignmentApi {
fn schema(&self) -> &Schema;
fn types(&self) -> &TypeSystem;
fn scripts(&self) -> impl Iterator<Item = &Lib>;
fn genesis(&self) -> &Genesis;
fn bundles_info(&self) -> impl Iterator<Item = (&TransitionBundle, &EAnchor, Txid)>;
fn bundle_ids<'iter>(&self) -> impl Iterator<Item = BundleId> + 'iter {
self.bundles_info()
.map(|(b, _, _)| b.bundle_id())
.collect::<BTreeSet<_>>()
.into_iter()
}
}