#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::{string::String, vec::Vec};
pub mod format;
pub mod view;
pub use format::{
FINAL_SECTION_NAME, RAW_SECTION_NAME, RAW_SECTION_PREFIX, RAW_SPEC_FORMAT,
SpecSection, classify_section,
};
#[cfg(feature = "owned-model")]
pub use thruput_spec::{
ContractArrayType, ContractEnumDef, ContractEnumVariant, ContractEventDef,
ContractExceptionType, ContractField, ContractMethodEffect,
ContractSignedTokenPreimage, ContractSpec, ContractSpecId,
ContractSpecInterface, ContractSpecMethod, ContractSpecString,
ContractStructDef, ContractType, ContractTypeDef, ContractTypeDefKind,
ContractTypeKind, ContractUnionCase, ContractUnionCaseKind,
ContractUnionCaseType, ContractUnionDef, ContractVectorType,
};
#[cfg(feature = "owned-model")]
mod fragment;
#[cfg(feature = "owned-model")]
pub use fragment::*;
pub use view::*;
#[cfg(feature = "alloc")]
use xdrs::VecM;
mod thruput_xdr_types;
pub trait ContractTypeSpec {
const TYPE_DEF: view::ContractTypeDefView<'static>;
}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a contract event",
label = "not a contract event",
note = "add `#[derive(Event)]` to `{Self}` — `emits(...)` in \
`#[contract(...)]` requires it"
)]
pub trait ContractEventSpec {
const EVENT_DEF: view::ContractEventDefView<'static>;
#[doc(hidden)]
const __THRUPUT_SPEC_ANCHOR_ROOT: fn() -> usize =
Self::__thruput_spec_anchor;
#[doc(hidden)]
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
0
}
}
pub trait ContractTypeName {
const NAME: view::ContractSpecIdView<'static>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContractTypeInfo<'a> {
pub ty: view::ContractTypeView<'a>,
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot appear in a contract signature",
label = "not a contract-spec type",
note = "annotate the defining type with `#[contract_type]` (error \
types: `#[contract_exception]`, events: `#[derive(Event)]`)"
)]
pub trait ContractTypeRefSpec {
const INFO: ContractTypeInfo<'static>;
const SIGNED_PREIMAGE: Option<&'static view::ContractTypeView<'static>> =
Some(&Self::INFO.ty);
#[doc(hidden)]
const __THRUPUT_SPEC_ANCHOR_ROOT: fn() -> usize =
Self::__thruput_spec_anchor;
#[doc(hidden)]
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
0
}
}
#[doc(hidden)]
#[inline(always)]
pub fn mix_anchor_fn(current: usize, anchor: fn() -> usize) -> usize {
current ^ core::hint::black_box(anchor as usize)
}
impl ContractTypeRefSpec for () {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Void,
};
}
impl ContractTypeRefSpec for bool {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Bool,
};
}
impl ContractTypeRefSpec for u8 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::U8,
};
}
impl ContractTypeRefSpec for u32 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::U32,
};
}
impl ContractTypeRefSpec for i32 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::I32,
};
}
impl ContractTypeRefSpec for u64 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::U64,
};
}
impl ContractTypeRefSpec for i64 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::I64,
};
}
impl ContractTypeRefSpec for u128 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::U128,
};
}
impl ContractTypeRefSpec for i128 {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::I128,
};
}
impl ContractTypeRefSpec for str {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::String,
};
}
impl<T> ContractTypeRefSpec for [T]
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Vector(view::ContractVectorTypeView {
element: &type_ref::<T>(),
max_len: u32::MAX,
}),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
impl ContractTypeRefSpec for &[u8] {
const INFO: ContractTypeInfo<'static> =
<[u8] as ContractTypeRefSpec>::INFO;
}
impl ContractTypeRefSpec for &str {
const INFO: ContractTypeInfo<'static> = <str as ContractTypeRefSpec>::INFO;
}
impl<const MAX: u32> ContractTypeRefSpec for xdr_common::StringM<MAX> {
const INFO: ContractTypeInfo<'static> = <str as ContractTypeRefSpec>::INFO;
}
impl<const MAX: usize> ContractTypeRefSpec for heapless::String<MAX> {
const INFO: ContractTypeInfo<'static> = <str as ContractTypeRefSpec>::INFO;
}
impl<const MAX: u32> ContractTypeRefSpec for xdr_common::BytesM<MAX> {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Vector(view::ContractVectorTypeView {
element: &view::ContractTypeView::U8,
max_len: MAX,
}),
};
}
impl<T, const N: usize> ContractTypeRefSpec for heapless::Vec<T, N>
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Vector(view::ContractVectorTypeView {
element: &type_ref::<T>(),
max_len: N as u32,
}),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
impl<T, const N: usize> ContractTypeRefSpec for [T; N]
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Array(view::ContractArrayTypeView {
element: &type_ref::<T>(),
len: N as u32,
}),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
#[cfg(feature = "alloc")]
impl ContractTypeRefSpec for String {
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::String,
};
}
#[cfg(feature = "alloc")]
impl<T> ContractTypeRefSpec for Vec<T>
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Vector(view::ContractVectorTypeView {
element: &type_ref::<T>(),
max_len: u32::MAX,
}),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
#[cfg(feature = "alloc")]
impl<T, const N: u32> ContractTypeRefSpec for VecM<T, N>
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Vector(view::ContractVectorTypeView {
element: &type_ref::<T>(),
max_len: N,
}),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
impl<T> ContractTypeRefSpec for Option<T>
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Option(&type_ref::<T>()),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
#[cfg(feature = "alloc")]
impl<T> ContractTypeRefSpec for alloc::boxed::Box<T>
where
T: ContractTypeRefSpec,
{
const INFO: ContractTypeInfo<'static> = T::INFO;
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
mix_anchor_fn(
0,
<T as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT,
)
}
}
macro_rules! impl_tuple_type_ref_spec {
($(($($name:ident),+)),+ $(,)?) => {
$(
impl<$($name),+> ContractTypeRefSpec for ($($name,)+)
where
$($name: ContractTypeRefSpec),+
{
const INFO: ContractTypeInfo<'static> = ContractTypeInfo {
ty: view::ContractTypeView::Tuple(&[$(type_ref::<$name>()),+]),
};
#[cfg_attr(target_arch = "riscv32", inline(never))]
#[cfg_attr(
target_arch = "riscv32",
unsafe(link_section = "thruputspecanchortextv0")
)]
fn __thruput_spec_anchor() -> usize {
let mut acc = 0usize;
$(acc = mix_anchor_fn(acc, <$name as ContractTypeRefSpec>::__THRUPUT_SPEC_ANCHOR_ROOT);)+
acc
}
}
)+
};
}
impl_tuple_type_ref_spec!(
(A),
(A, B),
(A, B, C),
(A, B, C, D),
(A, B, C, D, E),
(A, B, C, D, E, F),
(A, B, C, D, E, F, G),
(A, B, C, D, E, F, G, H),
(A, B, C, D, E, F, G, H, I),
(A, B, C, D, E, F, G, H, I, J),
(A, B, C, D, E, F, G, H, I, J, K),
(A, B, C, D, E, F, G, H, I, J, K, L),
(A, B, C, D, E, F, G, H, I, J, K, L, M),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
);
pub const fn symbol<T: ContractTypeSpec>() -> view::ContractSpecIdView<'static>
{
T::TYPE_DEF.symbol()
}
pub const fn type_ref<T: ContractTypeRefSpec + ?Sized>()
-> view::ContractTypeView<'static> {
T::INFO.ty
}