1use crate::internal_prelude::*;
2
3pub type ScryptoTypeKind<L> = TypeKind<ScryptoCustomTypeKind, L>;
4pub type ScryptoLocalTypeKind = LocalTypeKind<ScryptoCustomSchema>;
5pub type ScryptoAggregatorTypeKind = AggregatorTypeKind<ScryptoCustomSchema>;
6pub type VersionedScryptoSchema = VersionedSchema<ScryptoCustomSchema>;
7pub type ScryptoSingleTypeSchema = SingleTypeSchema<ScryptoCustomSchema>;
8pub type ScryptoTypeCollectionSchema = TypeCollectionSchema<ScryptoCustomSchema>;
9pub type ScryptoSchema = Schema<ScryptoCustomSchema>;
10pub type ScryptoTypeData<L> = TypeData<ScryptoCustomTypeKind, L>;
11pub type ScryptoLocalTypeData = LocalTypeData<ScryptoCustomSchema>;
12pub type ScryptoAggregatorTypeData = AggregatorTypeData<ScryptoCustomSchema>;
13pub type ScryptoTypeValidation = TypeValidation<ScryptoCustomTypeValidation>;
14pub type ScryptoTypeAggregator = TypeAggregator<ScryptoCustomTypeKind>;
15
16pub trait ScryptoCheckedFixedSchema: CheckedFixedSchema<ScryptoCustomSchema> {}
17impl<T: CheckedFixedSchema<ScryptoCustomSchema>> ScryptoCheckedFixedSchema for T {}
18
19pub trait ScryptoCheckedBackwardsCompatibleSchema:
20 CheckedBackwardsCompatibleSchema<ScryptoCustomSchema>
21{
22}
23impl<T: CheckedBackwardsCompatibleSchema<ScryptoCustomSchema>>
24 ScryptoCheckedBackwardsCompatibleSchema for T
25{
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoSbor)]
30pub enum ScryptoCustomTypeKind {
31 Reference,
32 Own,
33 Decimal,
34 PreciseDecimal,
35 NonFungibleLocalId,
36}
37
38#[derive(Debug, Copy, Clone, PartialEq, Eq, ManifestSbor, ScryptoSbor)]
39pub enum ScryptoCustomTypeKindLabel {
40 Reference,
41 Own,
42 Decimal,
43 PreciseDecimal,
44 NonFungibleLocalId,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoSbor)]
48pub enum ScryptoCustomTypeValidation {
49 Reference(ReferenceValidation),
50 Own(OwnValidation),
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoSbor)]
54pub enum ReferenceValidation {
55 IsGlobal,
56 IsGlobalPackage,
57 IsGlobalComponent,
58 IsGlobalResourceManager,
59 IsGlobalTyped(Option<PackageAddress>, String),
60 IsInternal,
61 IsInternalTyped(Option<PackageAddress>, String),
62}
63
64impl ReferenceValidation {
65 fn compare(base: &Self, compared: &Self) -> ValidationChange {
66 match (base, compared) {
67 (base, compared) if base == compared => ValidationChange::Unchanged,
68 (ReferenceValidation::IsGlobal, compared) if compared.requires_global() => {
69 ValidationChange::Strengthened
70 }
71 (base, ReferenceValidation::IsGlobal) if base.requires_global() => {
72 ValidationChange::Weakened
73 }
74 (ReferenceValidation::IsInternal, compared) if compared.requires_internal() => {
75 ValidationChange::Strengthened
76 }
77 (base, ReferenceValidation::IsInternal) if base.requires_internal() => {
78 ValidationChange::Weakened
79 }
80 (_, _) => ValidationChange::Incomparable,
81 }
82 }
83
84 fn requires_global(&self) -> bool {
85 match self {
86 ReferenceValidation::IsGlobal => true,
87 ReferenceValidation::IsGlobalPackage => true,
88 ReferenceValidation::IsGlobalComponent => true,
89 ReferenceValidation::IsGlobalResourceManager => true,
90 ReferenceValidation::IsGlobalTyped(_, _) => true,
91 ReferenceValidation::IsInternal => false,
92 ReferenceValidation::IsInternalTyped(_, _) => false,
93 }
94 }
95
96 fn requires_internal(&self) -> bool {
97 match self {
98 ReferenceValidation::IsGlobal => false,
99 ReferenceValidation::IsGlobalPackage => false,
100 ReferenceValidation::IsGlobalComponent => false,
101 ReferenceValidation::IsGlobalResourceManager => false,
102 ReferenceValidation::IsGlobalTyped(_, _) => false,
103 ReferenceValidation::IsInternal => true,
104 ReferenceValidation::IsInternalTyped(_, _) => true,
105 }
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoSbor)]
110pub enum OwnValidation {
111 IsBucket,
112 IsProof,
113 IsVault,
114 IsKeyValueStore,
115 IsGlobalAddressReservation,
116 IsTypedObject(Option<PackageAddress>, String),
117}
118
119impl OwnValidation {
120 fn compare(base: &Self, compared: &Self) -> ValidationChange {
121 if base == compared {
124 ValidationChange::Unchanged
125 } else {
126 ValidationChange::Incomparable
127 }
128 }
129
130 pub fn could_match_manifest_bucket(&self) -> bool {
131 match self {
132 OwnValidation::IsBucket => true,
133 OwnValidation::IsProof => false,
134 OwnValidation::IsVault => false,
135 OwnValidation::IsKeyValueStore => false,
136 OwnValidation::IsGlobalAddressReservation => false,
137 OwnValidation::IsTypedObject(_, _) => true,
139 }
140 }
141
142 pub fn could_match_manifest_proof(&self) -> bool {
143 match self {
144 OwnValidation::IsBucket => false,
145 OwnValidation::IsProof => true,
146 OwnValidation::IsVault => false,
147 OwnValidation::IsKeyValueStore => false,
148 OwnValidation::IsGlobalAddressReservation => false,
149 OwnValidation::IsTypedObject(_, _) => true,
151 }
152 }
153
154 pub fn could_match_manifest_address_reservation(&self) -> bool {
155 match self {
156 OwnValidation::IsBucket => false,
157 OwnValidation::IsProof => false,
158 OwnValidation::IsVault => false,
159 OwnValidation::IsKeyValueStore => false,
160 OwnValidation::IsGlobalAddressReservation => true,
161 OwnValidation::IsTypedObject(_, _) => false,
162 }
163 }
164}
165
166impl ReferenceValidation {
167 pub fn could_match_manifest_address(&self) -> bool {
168 match self {
169 ReferenceValidation::IsGlobal => true,
170 ReferenceValidation::IsGlobalPackage => true,
171 ReferenceValidation::IsGlobalComponent => true,
172 ReferenceValidation::IsGlobalResourceManager => true,
173 ReferenceValidation::IsGlobalTyped(_, _) => true,
174 ReferenceValidation::IsInternal => true,
175 ReferenceValidation::IsInternalTyped(_, _) => true,
176 }
177 }
178}
179
180impl<L: SchemaTypeLink> CustomTypeKind<L> for ScryptoCustomTypeKind {
181 type CustomTypeValidation = ScryptoCustomTypeValidation;
182 type CustomTypeKindLabel = ScryptoCustomTypeKindLabel;
183
184 fn label(&self) -> Self::CustomTypeKindLabel {
185 match self {
186 ScryptoCustomTypeKind::Reference => ScryptoCustomTypeKindLabel::Reference,
187 ScryptoCustomTypeKind::Own => ScryptoCustomTypeKindLabel::Own,
188 ScryptoCustomTypeKind::Decimal => ScryptoCustomTypeKindLabel::Decimal,
189 ScryptoCustomTypeKind::PreciseDecimal => ScryptoCustomTypeKindLabel::PreciseDecimal,
190 ScryptoCustomTypeKind::NonFungibleLocalId => {
191 ScryptoCustomTypeKindLabel::NonFungibleLocalId
192 }
193 }
194 }
195}
196
197impl CustomTypeKindLabel for ScryptoCustomTypeKindLabel {
198 fn name(&self) -> &'static str {
199 match self {
200 ScryptoCustomTypeKindLabel::Reference => "Reference",
201 ScryptoCustomTypeKindLabel::Own => "Own",
202 ScryptoCustomTypeKindLabel::Decimal => "Decimal",
203 ScryptoCustomTypeKindLabel::PreciseDecimal => "PreciseDecimal",
204 ScryptoCustomTypeKindLabel::NonFungibleLocalId => "NonFungibleLocalId",
205 }
206 }
207}
208
209impl CustomTypeValidation for ScryptoCustomTypeValidation {
210 fn compare(base: &Self, compared: &Self) -> ValidationChange {
211 match (base, compared) {
212 (
213 ScryptoCustomTypeValidation::Reference(base),
214 ScryptoCustomTypeValidation::Reference(compared),
215 ) => ReferenceValidation::compare(base, compared),
216 (ScryptoCustomTypeValidation::Reference(_), ScryptoCustomTypeValidation::Own(_)) => {
217 ValidationChange::Incomparable
218 }
219 (ScryptoCustomTypeValidation::Own(_), ScryptoCustomTypeValidation::Reference(_)) => {
220 ValidationChange::Incomparable
221 }
222 (
223 ScryptoCustomTypeValidation::Own(base),
224 ScryptoCustomTypeValidation::Own(compared),
225 ) => OwnValidation::compare(base, compared),
226 }
227 }
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Copy)]
231pub struct ScryptoCustomSchema {}
232
233lazy_static::lazy_static! {
234 static ref EMPTY_SCHEMA: Schema<ScryptoCustomSchema> = {
235 Schema::empty()
236 };
237}
238
239impl CustomSchema for ScryptoCustomSchema {
240 type CustomLocalTypeKind = ScryptoCustomTypeKind;
241 type CustomAggregatorTypeKind = ScryptoCustomTypeKind;
242 type CustomTypeKindLabel = ScryptoCustomTypeKindLabel;
243 type CustomTypeValidation = ScryptoCustomTypeValidation;
244 type DefaultCustomExtension = ScryptoCustomExtension;
245
246 fn linearize_type_kind(
247 type_kind: Self::CustomLocalTypeKind,
248 _type_indices: &IndexSet<TypeHash>,
249 ) -> Self::CustomAggregatorTypeKind {
250 type_kind
251 }
252
253 fn resolve_well_known_type(
254 well_known_id: WellKnownTypeId,
255 ) -> Option<&'static LocalTypeData<Self>> {
256 resolve_scrypto_well_known_type(well_known_id)
257 }
258
259 fn validate_custom_type_kind(
260 _context: &SchemaContext,
261 type_kind: &Self::CustomLocalTypeKind,
262 ) -> Result<(), SchemaValidationError> {
263 match type_kind {
264 ScryptoCustomTypeKind::Reference
265 | ScryptoCustomTypeKind::Own
266 | ScryptoCustomTypeKind::Decimal
267 | ScryptoCustomTypeKind::PreciseDecimal
268 | ScryptoCustomTypeKind::NonFungibleLocalId => {
269 }
271 }
272 Ok(())
273 }
274
275 fn validate_type_metadata_with_custom_type_kind(
276 _: &SchemaContext,
277 type_kind: &Self::CustomLocalTypeKind,
278 type_metadata: &TypeMetadata,
279 ) -> Result<(), SchemaValidationError> {
280 match type_kind {
283 ScryptoCustomTypeKind::Reference
284 | ScryptoCustomTypeKind::Own
285 | ScryptoCustomTypeKind::Decimal
286 | ScryptoCustomTypeKind::PreciseDecimal
287 | ScryptoCustomTypeKind::NonFungibleLocalId => {
288 validate_childless_metadata(type_metadata)?;
289 }
290 }
291 Ok(())
292 }
293
294 fn validate_custom_type_validation(
295 _context: &SchemaContext,
296 custom_type_kind: &Self::CustomLocalTypeKind,
297 custom_type_validation: &Self::CustomTypeValidation,
298 ) -> Result<(), SchemaValidationError> {
299 match custom_type_kind {
300 ScryptoCustomTypeKind::Reference => {
301 if let ScryptoCustomTypeValidation::Reference(_) = custom_type_validation {
302 Ok(())
303 } else {
304 Err(SchemaValidationError::TypeValidationMismatch)
305 }
306 }
307 ScryptoCustomTypeKind::Own => {
308 if let ScryptoCustomTypeValidation::Own(_) = custom_type_validation {
309 Ok(())
310 } else {
311 Err(SchemaValidationError::TypeValidationMismatch)
312 }
313 }
314 ScryptoCustomTypeKind::Decimal
315 | ScryptoCustomTypeKind::PreciseDecimal
316 | ScryptoCustomTypeKind::NonFungibleLocalId => {
317 Err(SchemaValidationError::TypeValidationMismatch)
321 }
322 }
323 }
324
325 fn empty_schema() -> &'static Schema<Self> {
326 &EMPTY_SCHEMA
327 }
328}
329
330pub trait HasSchemaHash {
331 fn generate_schema_hash(&self) -> SchemaHash;
332}
333
334impl HasSchemaHash for VersionedScryptoSchema {
335 fn generate_schema_hash(&self) -> SchemaHash {
336 SchemaHash::from(hash(scrypto_encode(self).unwrap()))
337 }
338}
339
340pub fn replace_self_package_address(
341 schema: &mut VersionedScryptoSchema,
342 package_address: PackageAddress,
343) {
344 for type_validation in &mut schema.v1_mut().type_validations {
345 match type_validation {
346 TypeValidation::Custom(ScryptoCustomTypeValidation::Own(
347 OwnValidation::IsTypedObject(package, _),
348 ))
349 | TypeValidation::Custom(ScryptoCustomTypeValidation::Reference(
350 ReferenceValidation::IsGlobalTyped(package, _),
351 ))
352 | TypeValidation::Custom(ScryptoCustomTypeValidation::Reference(
353 ReferenceValidation::IsInternalTyped(package, _),
354 )) => {
355 if package.is_none() {
356 *package = Some(package_address)
357 }
358 }
359 _ => {}
360 }
361 }
362}