1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]

//! Efficient and compact serialization of Rust types.
//!
//! This library provides structures to easily retrieve compile-time type
//! information at runtime and also to serialize this information in a compact
//! form.
//!
//! # Registry
//!
//! At the heart of its functionality is the [`Registry`](`crate::Registry`) that acts as cache for
//! known types in order to efficiently deduplicate them and thus compactify the overall
//! serialization.
//!
//! # Type Information
//!
//! Information about types is provided via the [`TypeInfo`](`crate::TypeInfo`) trait.
//!
//! This trait should be implemented for all types that are serializable.
//! For this the library provides implementations for all commonly used Rust
//! standard types and provides derive macros for simpler implementation of user
//! provided custom types.
//!
//! # Compaction Forms
//!
//! There is an uncompact form, called [`MetaForm`](`crate::form::MetaForm`) that acts as a bridge
//! from compile-time type information at runtime in order to easily retrieve all information needed
//! to uniquely identify types.
//!
//! The compact form is retrieved by the [`IntoCompact`](`crate::IntoCompact`) trait and internally
//! used by the [`Registry`](`crate::Registry`) in order to convert the uncompact types
//! into their compact form.
//!
//! # Symbols and Namespaces
//!
//! To differentiate two types sharing the same name namespaces are used.
//! Commonly the namespace is equal to the one where the type has been defined in. For Rust prelude
//! types such as [`Option`](`std::option::Option`) and [`Result`](`std::result::Result`) the root
//! namespace (empty namespace) is used.
//!
//! To use this library simply use the [`MetaForm`](`crate::form::MetaForm`) initially with your own data
//! structures and at best make them generic over the [`Form`](`crate::form::Form`) trait just as has
//! been done in this crate with [`TypeInfo`](`crate::TypeInfo`) in order to go for a simple
//! implementation of [`IntoCompact`](`crate::IntoCompact`). Use a single instance of the [`Registry`](`crate::Registry`) for
//! compaction and provide this registry instance upon serialization. Done.
//!
//! A usage example can be found in ink! here:
//! https://github.com/paritytech/ink/blob/master/abi/src/specs.rs

#[cfg(not(feature = "std"))]
extern crate alloc;

/// Takes a number of types and returns a vector that contains their respective
/// [`MetaType`](`crate::MetaType`) instances.
///
/// This is useful for places that require inputs of iterators over [`MetaType`](`crate::MetaType`)
/// instances and provide a way out of code bloat in these scenarious.
///
/// # Example
///
/// ```
/// # use scale_info::tuple_meta_type;
/// assert_eq!(
///     tuple_meta_type!(i32, [u8; 32], String),
///     {
///         use scale_info::MetaType;
///         let mut vec = Vec::new();
///         vec.push(MetaType::new::<i32>());
///         vec.push(MetaType::new::<[u8; 32]>());
///         vec.push(MetaType::new::<String>());
///         vec
///     }
/// );
/// ```
#[macro_export]
macro_rules! tuple_meta_type {
	( $($ty:ty),* ) => {
		{
			#[cfg(not(feature = "std"))]
			extern crate alloc as _alloc;
			#[cfg(not(feature = "std"))]
			#[allow(unused_mut)]
			let mut v = _alloc::vec![];

			#[cfg(feature = "std")]
			#[allow(unused_mut)]
			let mut v = std::vec![];

			$(
				v.push($crate::MetaType::new::<$ty>());
			)*
			v
		}
	}
}

mod tm_std;

pub mod build;
pub mod form;
mod impls;
pub mod interner;
mod meta_type;
mod registry;
mod ty;
mod utils;

#[cfg(test)]
mod tests;

pub use self::{
	meta_type::MetaType,
	registry::{IntoCompact, Registry, RegistryReadOnly},
	ty::*,
};

#[cfg(feature = "derive")]
pub use scale_info_derive::TypeInfo;

/// Implementors return their meta type information.
pub trait TypeInfo {
	/// Returns the static type identifier for `Self`.
	fn type_info() -> Type;
}

/// Returns the runtime bridge to the types compile-time type information.
pub fn meta_type<T>() -> MetaType
where
	T: ?Sized + TypeInfo + 'static,
{
	MetaType::new::<T>()
}