common_primitives/
schema.rs

1extern crate alloc;
2use crate::impl_codec_bitflags;
3#[cfg(feature = "std")]
4use crate::utils;
5use alloc::{vec, vec::Vec};
6use enumflags2::{bitflags, BitFlags};
7use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
8use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
9use serde::{Deserialize, Serialize};
10use sp_runtime::RuntimeDebug;
11#[cfg(feature = "std")]
12use utils::*;
13
14/// Schema Id is the unique identifier for a Schema
15pub type SchemaId = u16;
16
17/// Schema version number
18pub type SchemaVersion = u8;
19
20/// Types of modeling in which a message payload may be defined
21#[derive(
22	Copy,
23	Clone,
24	Encode,
25	Decode,
26	DecodeWithMemTracking,
27	PartialEq,
28	Debug,
29	TypeInfo,
30	Eq,
31	MaxEncodedLen,
32	Serialize,
33	Deserialize,
34)]
35pub enum ModelType {
36	/// Message payload modeled with Apache Avro: <https://avro.apache.org/docs/current/spec.html>
37	AvroBinary,
38	/// Message payload modeled with Apache Parquet: <https://parquet.apache.org/>
39	Parquet,
40}
41
42/// Types of payload locations
43#[derive(
44	Copy,
45	Clone,
46	Encode,
47	Decode,
48	DecodeWithMemTracking,
49	PartialEq,
50	Debug,
51	TypeInfo,
52	Eq,
53	MaxEncodedLen,
54	Serialize,
55	Deserialize,
56)]
57pub enum PayloadLocation {
58	/// Message payload is located on chain
59	OnChain,
60	/// Message payload is located on IPFS
61	IPFS,
62	/// Itemized payload location for onchain storage in itemized form
63	Itemized,
64	/// Paginated payload location for onchain storage in paginated form
65	Paginated,
66}
67
68/// Support for up to 16 user-enabled features on a collection.
69#[bitflags]
70#[repr(u16)]
71#[derive(
72	Copy,
73	Clone,
74	RuntimeDebug,
75	PartialEq,
76	Eq,
77	Encode,
78	Decode,
79	DecodeWithMemTracking,
80	MaxEncodedLen,
81	TypeInfo,
82	Serialize,
83	Deserialize,
84)]
85pub enum SchemaSetting {
86	/// Schema setting to enforce append-only behavior on payload.
87	/// Applied to schemas of type `PayloadLocation::Itemized`.
88	AppendOnly,
89	/// Schema may enforce signature requirement on payload.
90	/// Applied to schemas of type `PayloadLocation::Itemized` or `PayloadLocation::Paginated`.
91	SignatureRequired,
92}
93
94/// Wrapper type for `BitFlags<SchemaSetting>` that implements `Codec`.
95#[derive(Clone, Copy, PartialEq, Eq, Default, RuntimeDebug)]
96pub struct SchemaSettings(pub BitFlags<SchemaSetting>);
97
98/// RPC Response form for a Schema
99#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
100#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
101pub struct SchemaResponse {
102	/// The unique identifier for this Schema
103	pub schema_id: SchemaId,
104	/// The data that represents how this schema is structured
105	#[cfg_attr(feature = "std", serde(with = "as_string"))]
106	pub model: Vec<u8>,
107	/// The model format type for how the schema model is represented
108	pub model_type: ModelType,
109	/// The payload location
110	pub payload_location: PayloadLocation,
111	/// grants for the schema
112	pub settings: Vec<SchemaSetting>,
113}
114
115/// RPC Response form for a Schema Info
116#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
117#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
118pub struct SchemaInfoResponse {
119	/// The unique identifier for this Schema
120	pub schema_id: SchemaId,
121	/// The model format type for how the schema model is represented
122	pub model_type: ModelType,
123	/// The payload location
124	pub payload_location: PayloadLocation,
125	/// grants for the schema
126	pub settings: Vec<SchemaSetting>,
127}
128
129/// This allows other pallets to resolve Schema information. With generic SchemaId
130pub trait SchemaProvider<SchemaId> {
131	/// Gets the Schema details associated with this `SchemaId` if any
132	fn get_schema_by_id(schema_id: SchemaId) -> Option<SchemaResponse>;
133
134	/// Gets the Schema Info associated with this `SchemaId` if any
135	fn get_schema_info_by_id(schema_id: SchemaId) -> Option<SchemaInfoResponse>;
136}
137
138/// This allows other Pallets to check validity of schema ids.
139pub trait SchemaValidator<SchemaId> {
140	/// Checks that a collection of SchemaIds are all valid
141	fn are_all_schema_ids_valid(schema_ids: &[SchemaId]) -> bool;
142
143	/// Set the schema counter for testing purposes.
144	#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
145	fn set_schema_count(n: SchemaId);
146}
147
148impl SchemaSettings {
149	/// Returns new SchemaSettings with all settings disabled
150	pub fn all_disabled() -> Self {
151		Self(BitFlags::EMPTY)
152	}
153	/// Get all setting enabled
154	pub fn get_enabled(&self) -> BitFlags<SchemaSetting> {
155		self.0
156	}
157	/// Check if a setting is enabled
158	pub fn is_enabled(&self, grant: SchemaSetting) -> bool {
159		self.0.contains(grant)
160	}
161	/// Enable a setting
162	pub fn set(&mut self, grant: SchemaSetting) {
163		self.0.insert(grant)
164	}
165	/// Copy the settings from a BitFlags
166	pub fn from(settings: BitFlags<SchemaSetting>) -> Self {
167		Self(settings)
168	}
169}
170impl_codec_bitflags!(SchemaSettings, u16, SchemaSetting);
171
172/// RPC Response from a schema name query
173#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
174#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
175pub struct SchemaVersionResponse {
176	/// Schema name in following format: namespace.descriptor
177	#[cfg_attr(feature = "std", serde(with = "as_string"))]
178	pub schema_name: Vec<u8>,
179	/// The version for this schema
180	pub schema_version: SchemaVersion,
181	/// The unique identifier for this Schema
182	pub schema_id: SchemaId,
183}
184
185#[cfg(test)]
186mod tests {
187	use super::*;
188
189	#[test]
190	fn schema_settings_when_disabled_has_no_enabled() {
191		let settings = SchemaSettings::all_disabled();
192		assert_eq!(settings.get_enabled(), BitFlags::EMPTY);
193	}
194
195	#[test]
196	fn schema_settings_set_from_all_enabled_check() {
197		let settings = SchemaSettings::from(BitFlags::ALL);
198		assert!(settings.is_enabled(SchemaSetting::AppendOnly));
199		assert!(settings.is_enabled(SchemaSetting::SignatureRequired));
200	}
201}