thruput_contract_spec/fragment.rs
1//! Owned raw-spec fragment types.
2//!
3//! `thruputspecraw*` fragments are internal to the SDK toolchain: the
4//! `#[contract]` macros emit them (as const views) and spec-tool parses and
5//! canonicalizes them. Downstream consumers only ever see the finalized
6//! `ContractSpec`, so the fragment types live here rather than in the
7//! protocol-level `thruput-spec` crate.
8//!
9//! These types are the raw wire format. Any change to their encoding — a new
10//! field, a new variant, a reordering — must bump
11//! [`RAW_SPEC_FORMAT`](crate::RAW_SPEC_FORMAT) and its mirrors; see
12//! [`crate::format`]. The stream is unframed, so a consumer that disagrees
13//! about the layout desynchronizes rather than failing cleanly.
14
15use thruput_spec::{
16 ContractEventDef, ContractExceptionType, ContractSpecId,
17 ContractSpecMethod, ContractSpecString, ContractTypeDef,
18};
19use xdrs::*;
20
21#[derive(
22 ReadXDR,
23 WriteXDR,
24 ConstXDRSize,
25 Clone,
26 Debug,
27 PartialEq,
28 Eq,
29 Hash,
30 PartialOrd,
31 Ord,
32)]
33pub struct SpecInterfaceFragment {
34 pub interface_name: ContractSpecString,
35 pub interface_version: ContractSpecString,
36 /// The item that declares this interface: the `#[contract]` trait's spec
37 /// id (`CRATE@MAJOR::module::path::Trait`), or `CRATE@MAJOR` for a bare
38 /// impl or free-function contract. See [`SpecInterfaceAnchor::declared_by`].
39 pub declared_by: ContractSpecId,
40 pub throws: VecM<ContractExceptionType>,
41 pub emits: VecM<ContractSpecId>,
42}
43
44#[derive(
45 ReadXDR,
46 WriteXDR,
47 ConstXDRSize,
48 Clone,
49 Debug,
50 PartialEq,
51 Eq,
52 Hash,
53 PartialOrd,
54 Ord,
55)]
56/// A method belonging to `interface_name`@`interface_version`.
57///
58/// Emitted only by a site that also anchors that interface — a `#[contract]`
59/// impl, or `export_interface_spec!` in a carrier. A `#[contract]` trait
60/// definition emits its [`SpecInterfaceFragment`] as a candidate but no
61/// methods: two unrelated traits can collide on one interface key (default
62/// name = trait ident, default version = crate version), and candidate
63/// methods from a trait nothing implements would otherwise publish as
64/// phantom methods of the contract that merely links them. (`declared_by`
65/// now separates such traits in spec-tool as well.)
66pub struct SpecMethodFragment {
67 pub interface_name: ContractSpecString,
68 pub interface_version: ContractSpecString,
69 /// The item that declares this interface: the `#[contract]` trait's spec
70 /// id (`CRATE@MAJOR::module::path::Trait`), or `CRATE@MAJOR` for a bare
71 /// impl or free-function contract. See [`SpecInterfaceAnchor::declared_by`].
72 pub declared_by: ContractSpecId,
73 pub method: ContractSpecMethod,
74}
75
76#[derive(
77 ReadXDR,
78 WriteXDR,
79 ConstXDRSize,
80 Clone,
81 Debug,
82 PartialEq,
83 Eq,
84 Hash,
85 PartialOrd,
86 Ord,
87)]
88pub struct SpecInterfaceAnchor {
89 pub interface_name: ContractSpecString,
90 pub interface_version: ContractSpecString,
91 /// The item that declares the anchored interface: the `#[contract]`
92 /// trait's spec id (`CRATE@MAJOR::module::path::Trait`), or `CRATE@MAJOR`
93 /// for a bare impl or free-function contract.
94 ///
95 /// The interface *key* is (name, version) because that is all the wire
96 /// carries — `interface_id` and every entrypoint id hash the bare name
97 /// and major version, so that independent crates can implement one
98 /// interface. Two unrelated traits can therefore share a key. This field
99 /// is spec-only and tells them apart: spec-tool keeps only the fragments
100 /// of the declarer an artifact anchors, and rejects an artifact that
101 /// anchors two declarers under one key, since nothing on the wire could
102 /// tell their interfaces apart.
103 pub declared_by: ContractSpecId,
104}
105
106#[derive(
107 ReadXDR,
108 WriteXDR,
109 ConstXDRSize,
110 Clone,
111 Debug,
112 PartialEq,
113 Eq,
114 Hash,
115 PartialOrd,
116 Ord,
117)]
118#[repr(i32)]
119pub enum SpecFragment {
120 SpecInterface {
121 interface_fragment: SpecInterfaceFragment,
122 } = 0,
123 SpecMethod {
124 method_fragment: SpecMethodFragment,
125 } = 1,
126 SpecTypeDef {
127 type_def: ContractTypeDef,
128 } = 2,
129 ExportedSpecTypeDef {
130 type_def: ContractTypeDef,
131 } = 3,
132 SpecEvent {
133 event_def: ContractEventDef,
134 } = 4,
135 ExportedSpecEvent {
136 event_def: ContractEventDef,
137 } = 5,
138 InterfaceAnchor {
139 interface_anchor: SpecInterfaceAnchor,
140 } = 6,
141}