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/// DelegationGrpup Id is the unique identifier for a DelegationGroup
15pub type IntentGroupId = u16;
16
17/// Intent Id is the unique identifier for an Intent
18pub type IntentId = u16;
19
20/// Schema Id is the unique identifier for a Schema
21pub type SchemaId = u16;
22
23/// Schema version number
24// TODO: Remove once all traces of this are gone (ie, removed from runtime API)
25pub type SchemaVersion = u8;
26
27/// Types of modeling in which a message payload may be defined
28#[derive(
29	Copy,
30	Clone,
31	Encode,
32	Decode,
33	DecodeWithMemTracking,
34	PartialEq,
35	Debug,
36	TypeInfo,
37	Eq,
38	MaxEncodedLen,
39	Serialize,
40	Deserialize,
41)]
42pub enum ModelType {
43	/// Message payload modeled with Apache Avro: <https://avro.apache.org/docs/current/spec.html>
44	AvroBinary,
45	/// Message payload modeled with Apache Parquet: <https://parquet.apache.org/>
46	Parquet,
47}
48
49/// Types of payload locations
50#[derive(
51	Copy,
52	Clone,
53	Encode,
54	Decode,
55	DecodeWithMemTracking,
56	PartialEq,
57	Debug,
58	TypeInfo,
59	Eq,
60	MaxEncodedLen,
61	Serialize,
62	Deserialize,
63)]
64pub enum PayloadLocation {
65	/// Message payload is located on chain
66	OnChain,
67	/// Message payload is located on IPFS
68	IPFS,
69	/// Itemized payload location for onchain storage in itemized form
70	Itemized,
71	/// Paginated payload location for onchain storage in paginated form
72	Paginated,
73}
74
75/// Support for up to 16 user-enabled features on a collection.
76#[bitflags]
77#[repr(u16)]
78#[derive(
79	Copy,
80	Clone,
81	RuntimeDebug,
82	PartialEq,
83	Eq,
84	Encode,
85	Decode,
86	DecodeWithMemTracking,
87	MaxEncodedLen,
88	TypeInfo,
89	Serialize,
90	Deserialize,
91)]
92pub enum SchemaSetting {
93	/// Intent setting to enforce append-only behavior on payload.
94	/// Applied to Intents of type `PayloadLocation::Itemized`.
95	AppendOnly,
96	/// Intent may enforce signature requirement on payload.
97	/// Applied to Intents of type `PayloadLocation::Itemized` or `PayloadLocation::Paginated`.
98	SignatureRequired,
99}
100
101/// Wrapper type for `BitFlags<IntentSetting>` that implements `Codec`.
102#[derive(Clone, Copy, PartialEq, Eq, Default, RuntimeDebug)]
103pub struct SchemaSettings(pub BitFlags<IntentSetting>);
104
105/// TODO: temporary alias until we can remove this type from the public API
106pub type IntentSetting = SchemaSetting;
107
108/// TODO: temporary alias until we can remove this type from the public API
109pub type IntentSettings = SchemaSettings;
110
111/// Status of a Schema
112#[derive(
113	Copy,
114	Clone,
115	Encode,
116	Decode,
117	DecodeWithMemTracking,
118	PartialEq,
119	Debug,
120	TypeInfo,
121	Eq,
122	MaxEncodedLen,
123	Serialize,
124	Deserialize,
125)]
126pub enum SchemaStatus {
127	/// Schema is current and approved for writing
128	Active,
129	/// Schema is viable for writing, but is deprecated and may become unsupported soon
130	Deprecated,
131	/// Schema is unsupported; writing to this schema is prohibited
132	Unsupported,
133}
134
135/// RPC response structure for an IntentGroup
136#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
137#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
138pub struct IntentGroupResponse {
139	/// The unique identifier for this IntentGroup
140	pub intent_group_id: IntentGroupId,
141	/// The list of currently supported IntentIds for this IntentGroup
142	pub intent_ids: Vec<IntentId>,
143}
144
145/// RPC response structure for an Intent
146#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
147#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
148pub struct IntentResponse {
149	/// The unique identifier for this Intent
150	pub intent_id: IntentId,
151	/// The payload location
152	pub payload_location: PayloadLocation,
153	/// settings for the Intent
154	pub settings: Vec<IntentSetting>,
155	/// The list of currently-supported SchemaIds for this Intent
156	pub schema_ids: Option<Vec<SchemaId>>,
157}
158
159/// RPC Response form for a Schema
160#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
161#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
162pub struct SchemaResponse {
163	/// The unique identifier for this Schema
164	pub schema_id: SchemaId,
165	/// The data that represents how this schema is structured
166	#[cfg_attr(feature = "std", serde(with = "as_string"))]
167	pub model: Vec<u8>,
168	/// The model format type for how the schema model is represented
169	pub model_type: ModelType,
170	/// The payload location associated with this Schema's associated Intent
171	pub payload_location: PayloadLocation,
172	/// The settings for this Schema's associated Intent
173	pub settings: Vec<SchemaSetting>,
174}
175
176/// RPC Response form for a Schema V2
177#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
178#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
179pub struct SchemaResponseV2 {
180	/// The unique identifier for this Schema
181	pub schema_id: SchemaId,
182	/// The IntentId of the Intent that this Schema implements
183	pub intent_id: IntentId,
184	/// The data that represents how this schema is structured
185	#[cfg_attr(feature = "std", serde(with = "as_string"))]
186	pub model: Vec<u8>,
187	/// The model format type for how the schema model is represented
188	pub model_type: ModelType,
189	/// The status of this Schema (Active, Deprecated, Unsupported)
190	pub status: SchemaStatus,
191	/// The payload location associated with this Schema's associated Intent
192	pub payload_location: PayloadLocation,
193	/// The settings for this Schema's associated Intent
194	pub settings: Vec<IntentSetting>,
195}
196
197impl Into<SchemaResponse> for SchemaResponseV2 {
198	/// Convert SchemaResponseV2 into SchemaResponse
199	fn into(self) -> SchemaResponse {
200		SchemaResponse {
201			schema_id: self.schema_id,
202			model: self.model,
203			model_type: self.model_type,
204			payload_location: self.payload_location,
205			settings: self.settings,
206		}
207	}
208}
209
210/// RPC Response form for a Schema Info
211#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
212#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
213pub struct SchemaInfoResponse {
214	/// The unique identifier for this Schema
215	pub schema_id: SchemaId,
216	/// The model format type for how the schema model is represented
217	pub model_type: ModelType,
218	/// The payload location associated with this Schema's associated Intent
219	pub payload_location: PayloadLocation,
220	/// The settings for this Schema's associated Intent
221	pub settings: Vec<IntentSetting>,
222	/// The IntentId of the Intent that this Schema implements
223	pub intent_id: IntentId,
224	/// The status of this Schema (Active, Deprecated, Unsupported)
225	/// Currently has no runtime effect; intended for future use.
226	pub status: SchemaStatus,
227}
228
229#[derive(
230	Copy,
231	Clone,
232	Encode,
233	Decode,
234	DecodeWithMemTracking,
235	PartialEq,
236	Debug,
237	TypeInfo,
238	Eq,
239	MaxEncodedLen,
240	Serialize,
241	Deserialize,
242)]
243/// Enum type for the different types of entities that a FullyQualifiedName can represent
244pub enum MappedEntityIdentifier {
245	/// An Intent
246	Intent(IntentId),
247	/// An IntentGroup
248	IntentGroup(IntentGroupId),
249}
250
251impl Default for MappedEntityIdentifier {
252	fn default() -> Self {
253		Self::Intent(Default::default())
254	}
255}
256
257/// RPC response form for a name resolution lookup
258#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
259#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
260pub struct NameLookupResponse {
261	/// The name for this entity
262	pub name: Vec<u8>,
263	/// The resolved entity
264	pub entity_id: MappedEntityIdentifier,
265}
266
267/// This allows other pallets to resolve Schema information. With generic SchemaId
268pub trait SchemaProvider<SchemaId> {
269	/// Gets the Schema details associated with this `SchemaId` if any
270	fn get_schema_by_id(schema_id: SchemaId) -> Option<SchemaResponseV2>;
271
272	/// Gets the Schema Info associated with this `SchemaId` if any
273	fn get_schema_info_by_id(schema_id: SchemaId) -> Option<SchemaInfoResponse>;
274
275	/// Gets the Intent associated with this `IntentId`, if any
276	fn get_intent_by_id(intent_id: IntentId) -> Option<IntentResponse>;
277}
278
279/// This allows other Pallets to check the validity of schema ids.
280pub trait SchemaValidator<SchemaId> {
281	/// Checks that all IntentIds in a collection are valid.
282	fn are_all_intent_ids_valid(intent_ids: &[IntentId]) -> bool;
283
284	/// Set the schema counter for testing purposes.
285	#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
286	fn set_schema_count(n: SchemaId);
287
288	/// Set the Intent counter for testing purposes.
289	#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
290	fn set_intent_count(n: IntentId);
291}
292
293impl IntentSettings {
294	/// Returns new SchemaSettings with all settings disabled
295	pub fn all_disabled() -> Self {
296		Self(BitFlags::EMPTY)
297	}
298	/// Get all setting enabled
299	pub fn get_enabled(&self) -> BitFlags<IntentSetting> {
300		self.0
301	}
302	/// Check if a setting is enabled
303	pub fn is_enabled(&self, grant: IntentSetting) -> bool {
304		self.0.contains(grant)
305	}
306	/// Enable a setting
307	pub fn set(&mut self, grant: IntentSetting) {
308		self.0.insert(grant)
309	}
310	/// Copy the settings from a BitFlags
311	pub fn from(settings: BitFlags<IntentSetting>) -> Self {
312		Self(settings)
313	}
314}
315impl_codec_bitflags!(IntentSettings, u16, IntentSetting);
316
317impl From<Vec<IntentSetting>> for IntentSettings {
318	/// Copy the settings from a vector of individual settings enums
319	fn from(settings: Vec<IntentSetting>) -> Self {
320		Self(BitFlags::from_iter(settings))
321	}
322}
323
324/// RPC Response from a schema name query
325#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
326#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
327pub struct SchemaVersionResponse {
328	/// Schema name in following format: namespace.descriptor
329	#[cfg_attr(feature = "std", serde(with = "as_string"))]
330	pub schema_name: Vec<u8>,
331	/// The version for this schema
332	pub schema_version: SchemaVersion,
333	/// The unique identifier for this Schema
334	pub schema_id: SchemaId,
335}
336
337#[cfg(test)]
338mod tests {
339	use super::*;
340
341	#[test]
342	fn intent_settings_when_disabled_has_no_enabled() {
343		let settings = IntentSettings::all_disabled();
344		assert_eq!(settings.get_enabled(), BitFlags::EMPTY);
345	}
346
347	#[test]
348	fn intent_settings_set_from_all_enabled_check() {
349		let settings = IntentSettings::from(BitFlags::ALL);
350		assert!(settings.is_enabled(IntentSetting::AppendOnly));
351		assert!(settings.is_enabled(IntentSetting::SignatureRequired));
352	}
353}