Skip to content

Commit

Permalink
iface: split IfaceClass and IfaceWrapper traits
Browse files Browse the repository at this point in the history
required to get rid of needless generics appearing after the introduction of ContractStateRead
  • Loading branch information
dr-orlovsky committed Aug 1, 2024
1 parent f0a85cd commit 9ad9495
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 27 deletions.
27 changes: 14 additions & 13 deletions src/interface/iface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use strict_encoding::{
};
use strict_types::{SemId, SymbolicSys, TypeLib};

use crate::interface::{IfaceDisplay, IfaceImpl, VerNo};
use crate::persistence::SchemaIfaces;
use crate::interface::{ContractIface, IfaceDisplay, IfaceImpl, VerNo};
use crate::persistence::{ContractStateRead, SchemaIfaces};
use crate::LIB_NAME_RGB_STD;

/// Interface identifier.
Expand Down Expand Up @@ -336,24 +336,25 @@ pub struct TransitionIface {
///
/// Interface standards like RGB20, RGB21 and RGB25 are actually interface
/// classes.
///
/// The instances implementing this trait are used as wrappers around
/// [`ContractIface`] object, allowing a simple API matching the interface class
/// requirements.
pub trait IfaceClass {
pub trait IfaceClass: Clone + Default {
const IFACE_NAME: &'static str;
const IFACE_IDS: &'static [IfaceId];

/// An object which allows to configure specific interface features to
/// select one interface from the class.
type Features: Sized + Clone + Default;
type Wrapper<S: ContractStateRead>: IfaceWrapper<S>;

fn stl(&self) -> TypeLib;
fn iface(&self) -> Iface;
fn iface_id(&self) -> IfaceId;
}

/// The instances implementing this trait are used as wrappers around
/// [`ContractIface`] object, allowing a simple API matching the interface class
/// requirements.
pub trait IfaceWrapper<S: ContractStateRead> {
/// Object which represent concise summary about a contract;
type Info: Clone + Eq + Debug;

fn iface(features: Self::Features) -> Iface;
fn iface_id(features: Self::Features) -> IfaceId;
fn stl() -> TypeLib;
fn with(iface: ContractIface<S>) -> Self;

/// Constructs information object describing a specific class in terms of
/// the interface class.
Expand Down
3 changes: 2 additions & 1 deletion src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ pub use contractum::IfaceDisplay;
pub use filter::{FilterExclude, FilterIncludeAll, OutpointFilter};
pub use iface::{
ArgMap, AssignIface, ExtensionIface, GenesisIface, GlobalIface, Iface, IfaceClass, IfaceId,
IfaceInconsistency, IfaceRef, Modifier, OpName, OwnedIface, Req, TransitionIface, ValencyIface,
IfaceInconsistency, IfaceRef, IfaceWrapper, Modifier, OpName, OwnedIface, Req, TransitionIface,
ValencyIface,
};
pub use iimpl::{IfaceImpl, ImplId, NamedField, NamedType, NamedVariant, SchemaTypeIndex};
pub use inheritance::{CheckInheritance, ExtensionError, InheritanceFailure};
Expand Down
26 changes: 13 additions & 13 deletions src/persistence/stock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use crate::containers::{
use crate::info::{ContractInfo, IfaceInfo, SchemaInfo};
use crate::interface::{
BuilderError, ContractBuilder, ContractIface, Iface, IfaceClass, IfaceId, IfaceRef,
TransitionBuilder,
IfaceWrapper, TransitionBuilder,
};
use crate::{MergeRevealError, RevealError};

Expand Down Expand Up @@ -502,12 +502,16 @@ impl<S: StashProvider, H: StateProvider, P: IndexProvider> Stock<S, H, P> {
#[allow(clippy::multiple_bound_locations)]
pub fn contracts_by<'a, C: IfaceClass + 'a>(
&'a self,
) -> Result<impl Iterator<Item = C::Info> + 'a, StockError<S, H, P>>
where C: From<ContractIface<H::ContractRead<'a>>> {
) -> Result<
impl Iterator<
Item = <C::Wrapper<H::ContractRead<'_>> as IfaceWrapper<H::ContractRead<'_>>>::Info,
> + 'a,
StockError<S, H, P>,
> {
Ok(self.stash.geneses_by::<C>()?.filter_map(|genesis| {
self.contract_iface_class::<C>(genesis.contract_id())
.as_ref()
.map(C::info)
.map(<C::Wrapper<H::ContractRead<'_>> as IfaceWrapper<H::ContractRead<'_>>>::info)
.ok()
}))
}
Expand Down Expand Up @@ -547,27 +551,23 @@ impl<S: StashProvider, H: StateProvider, P: IndexProvider> Stock<S, H, P> {
}

#[allow(clippy::multiple_bound_locations)]
pub fn contract_iface_class<'a, C: IfaceClass>(
&'a self,
pub fn contract_iface_class<C: IfaceClass>(
&self,
contract_id: ContractId,
) -> Result<C, StockError<S, H, P, ContractIfaceError>>
where
C: From<ContractIface<H::ContractRead<'a>>>,
{
) -> Result<C::Wrapper<H::ContractRead<'_>>, StockError<S, H, P, ContractIfaceError>> {
let (schema_ifaces, state, info) = self.contract_raw(contract_id)?;
let iimpl = self.stash.impl_for::<C>(schema_ifaces)?;

let iface = self.stash.iface(iimpl.iface_id)?;
let (types, _) = self.stash.extract(&schema_ifaces.schema, [iface])?;

Ok(ContractIface {
Ok(C::Wrapper::with(ContractIface {
state,
schema: schema_ifaces.schema.clone(),
iface: iimpl.clone(),
types,
info,
}
.into())
}))
}

/// Returns the best matching abstract interface to a contract.
Expand Down

0 comments on commit 9ad9495

Please sign in to comment.