1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(not(any(feature = "std", feature = "alloc")))]
4compile_error!("Either feature `std` or `alloc` must be enabled for this crate.");
5#[cfg(all(feature = "std", feature = "alloc"))]
6compile_error!("Feature `std` and `alloc` can't be enabled at the same time.");
7
8use bitflags::bitflags;
9use radix_common::prelude::*;
10
11#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
12pub struct KeyValueStoreGenericSubstitutions {
13 pub key_generic_substitution: GenericSubstitution,
14 pub value_generic_substitution: GenericSubstitution,
15 pub allow_ownership: bool, }
17
18#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
19pub enum GenericBound {
20 Any,
21}
22
23#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
24pub enum BlueprintHook {
25 OnVirtualize,
26 OnMove,
27 OnDrop,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
32pub struct BlueprintSchemaInit {
33 pub generics: Vec<GenericBound>,
35 pub schema: VersionedScryptoSchema,
37 pub state: BlueprintStateSchemaInit,
39 pub events: BlueprintEventSchemaInit,
41 pub types: BlueprintTypeSchemaInit,
44 pub functions: BlueprintFunctionsSchemaInit,
46 pub hooks: BlueprintHooksInit,
48}
49
50impl Default for BlueprintSchemaInit {
51 fn default() -> Self {
52 Self {
53 generics: Vec::new(),
54 schema: Schema {
55 type_kinds: Vec::new(),
56 type_metadata: Vec::new(),
57 type_validations: Vec::new(),
58 }
59 .into_versioned(),
60 state: BlueprintStateSchemaInit::default(),
61 events: BlueprintEventSchemaInit::default(),
62 types: BlueprintTypeSchemaInit::default(),
63 functions: BlueprintFunctionsSchemaInit::default(),
64 hooks: BlueprintHooksInit::default(),
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor, ManifestSbor)]
72pub struct BlueprintStateSchemaInit {
73 pub fields: Vec<FieldSchema<TypeRef<LocalTypeId>>>,
74 pub collections: Vec<BlueprintCollectionSchema<TypeRef<LocalTypeId>>>,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor, ManifestSbor)]
78#[sbor(transparent)]
79pub struct BlueprintEventSchemaInit {
80 pub event_schema: IndexMap<String, TypeRef<LocalTypeId>>,
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor, ManifestSbor)]
84#[sbor(transparent)]
85pub struct BlueprintTypeSchemaInit {
86 pub type_schema: IndexMap<String, LocalTypeId>,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
90pub struct FunctionSchemaInit {
91 pub receiver: Option<ReceiverInfo>,
92 pub input: TypeRef<LocalTypeId>,
93 pub output: TypeRef<LocalTypeId>,
94 pub export: String,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor, ManifestSbor)]
98pub struct BlueprintFunctionsSchemaInit {
99 pub functions: IndexMap<String, FunctionSchemaInit>,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor, ManifestSbor)]
103pub struct BlueprintHooksInit {
104 pub hooks: IndexMap<BlueprintHook, String>,
106}
107
108impl BlueprintSchemaInit {
109 pub fn exports(&self) -> Vec<String> {
110 self.functions
111 .functions
112 .values()
113 .map(|t| t.export.clone())
114 .chain(self.hooks.hooks.values().cloned())
115 .collect()
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
120pub enum TypeRef<T> {
121 Static(T), Generic(u8), }
125
126impl<T> TypeRef<T> {
127 pub fn into_static(self) -> Option<T> {
128 let Self::Static(value) = self else {
129 return None;
130 };
131 Some(value)
132 }
133
134 pub fn assert_static(self) -> T {
135 self.into_static().expect("Must be static")
136 }
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
140pub struct BlueprintKeyValueSchema<T> {
141 pub key: T,
142 pub value: T,
143 pub allow_ownership: bool,
144}
145
146impl<T> BlueprintKeyValueSchema<T> {
147 pub fn map<U, F: Fn(T) -> U + Copy>(self, f: F) -> BlueprintKeyValueSchema<U> {
148 BlueprintKeyValueSchema {
149 key: f(self.key),
150 value: f(self.value),
151 allow_ownership: self.allow_ownership,
152 }
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
157pub enum BlueprintCollectionSchema<T> {
158 KeyValueStore(BlueprintKeyValueSchema<T>),
159 Index(BlueprintKeyValueSchema<T>),
160 SortedIndex(BlueprintKeyValueSchema<T>),
161}
162
163impl<T> BlueprintCollectionSchema<T> {
164 pub fn map<U, F: Fn(T) -> U + Copy>(self, f: F) -> BlueprintCollectionSchema<U> {
165 match self {
166 BlueprintCollectionSchema::Index(schema) => {
167 BlueprintCollectionSchema::Index(schema.map(f))
168 }
169 BlueprintCollectionSchema::SortedIndex(schema) => {
170 BlueprintCollectionSchema::SortedIndex(schema.map(f))
171 }
172 BlueprintCollectionSchema::KeyValueStore(schema) => {
173 BlueprintCollectionSchema::KeyValueStore(schema.map(f))
174 }
175 }
176 }
177}
178
179pub trait BlueprintFeature {
180 fn feature_name(&self) -> &'static str;
181}
182
183#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
185pub enum Condition {
186 Always,
187 IfFeature(String),
188 IfOuterFeature(String),
189}
190
191impl Condition {
192 pub fn if_feature(feature: impl BlueprintFeature) -> Self {
193 Self::IfFeature(feature.feature_name().into())
194 }
195
196 pub fn if_outer_feature(feature: impl BlueprintFeature) -> Self {
197 Self::IfOuterFeature(feature.feature_name().into())
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
202pub enum FieldTransience {
203 NotTransient,
204 TransientStatic {
206 default_value: Vec<u8>,
208 },
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
213pub struct FieldSchema<V> {
214 pub field: V,
215 pub condition: Condition,
217 pub transience: FieldTransience,
219}
220
221impl FieldSchema<TypeRef<LocalTypeId>> {
222 pub fn if_feature<I: Into<LocalTypeId>, S: ToString>(value: I, feature: S) -> Self {
223 FieldSchema {
224 field: TypeRef::Static(value.into()),
225 condition: Condition::IfFeature(feature.to_string()),
226 transience: FieldTransience::NotTransient,
227 }
228 }
229
230 pub fn if_outer_feature<I: Into<LocalTypeId>, S: ToString>(value: I, feature: S) -> Self {
231 FieldSchema {
232 field: TypeRef::Static(value.into()),
233 condition: Condition::IfOuterFeature(feature.to_string()),
234 transience: FieldTransience::NotTransient,
235 }
236 }
237
238 pub fn static_field<I: Into<LocalTypeId>>(value: I) -> Self {
239 FieldSchema {
240 field: TypeRef::Static(value.into()),
241 condition: Condition::Always,
242 transience: FieldTransience::NotTransient,
243 }
244 }
245
246 pub fn transient_field<I: Into<LocalTypeId>, E: ScryptoEncode>(
247 value: I,
248 default_value: E,
249 ) -> Self {
250 FieldSchema {
251 field: TypeRef::Static(value.into()),
252 condition: Condition::Always,
253 transience: FieldTransience::TransientStatic {
254 default_value: scrypto_encode(&default_value).unwrap(),
255 },
256 }
257 }
258}
259
260bitflags! {
261 #[derive(Sbor)]
262 pub struct RefTypes: u32 {
263 const NORMAL = 0b00000001;
264 const DIRECT_ACCESS = 0b00000010;
265 }
266}
267
268#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
269pub struct ReceiverInfo {
270 pub receiver: Receiver,
271 pub ref_types: RefTypes,
272}
273
274impl ReceiverInfo {
275 pub fn normal_ref() -> Self {
276 Self {
277 receiver: Receiver::SelfRef,
278 ref_types: RefTypes::NORMAL,
279 }
280 }
281
282 pub fn normal_ref_mut() -> Self {
283 Self {
284 receiver: Receiver::SelfRefMut,
285 ref_types: RefTypes::NORMAL,
286 }
287 }
288}
289
290#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
291pub enum Receiver {
292 SelfRef,
293 SelfRefMut,
294}