Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature for enabling decoding #59

Merged
merged 7 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ std = [
derive = [
"scale-info-derive"
]
# enables decoding and deserialization of portable scale-info type metadata
decode = []

[workspace]
members = [
Expand Down
36 changes: 15 additions & 21 deletions src/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
use crate::prelude::{
any::TypeId,
fmt::Debug,
marker::PhantomData,
string::String,
};

use crate::{
Expand All @@ -53,18 +51,9 @@ pub trait Form {
/// The type representing the type.
type Type: PartialEq + Eq + PartialOrd + Ord + Clone + Debug;
/// The string type.
type String: FormString;
type String: AsRef<str> + PartialEq + Eq + PartialOrd + Ord + Clone + Debug;
}

/// Trait for types which can be used to represent strings in type definitions.
pub trait FormString:
AsRef<str> + PartialEq + Eq + PartialOrd + Ord + Clone + Debug
{
}

impl FormString for &'static str {}
impl FormString for String {}

Comment on lines -59 to -67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glad it is gone

/// A meta meta-type.
///
/// Allows to be converted into other forms such as portable form
Expand All @@ -85,16 +74,21 @@ impl Form for MetaForm {
/// This resolves some lifetime issues with self-referential structs (such as
/// the registry itself) but can no longer be used to resolve to the original
/// underlying data.
///
/// `type String` is owned in order to enable decoding
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub struct PortableForm<S = &'static str>(PhantomData<S>);
pub enum PortableForm {}

impl<S> Form for PortableForm<S>
where
S: FormString,
{
type Type = UntrackedSymbol<TypeId>;
type String = S;
cfg_if::cfg_if! {
if #[cfg(any(feature = "std", feature = "decode"))] {
impl Form for PortableForm {
type Type = UntrackedSymbol<TypeId>;
// Owned string required for decoding/deserialization
type String = crate::prelude::string::String;
}
} else {
impl Form for PortableForm {
type Type = UntrackedSymbol<TypeId>;
type String = &'static str;
}
}
}
34 changes: 9 additions & 25 deletions src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use crate::prelude::{
use crate::{
form::{
Form,
FormString,
PortableForm,
},
interner::{
Expand All @@ -44,13 +43,9 @@ use crate::{
meta_type::MetaType,
Type,
};
use scale::{
Decode,
Encode,
};
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{
de::DeserializeOwned,
Deserialize,
Serialize,
};
Expand All @@ -68,7 +63,7 @@ impl IntoPortable for &'static str {
type Output = <PortableForm as Form>::String;

fn into_portable(self, _registry: &mut Registry) -> Self::Output {
self
self.into()
}
}

Expand Down Expand Up @@ -171,16 +166,10 @@ impl Registry {

/// A read-only registry containing types in their portable form for serialization.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(
feature = "serde",
serde(bound(serialize = "S: Serialize", deserialize = "S: DeserializeOwned"))
)]
pub struct PortableRegistry<S = &'static str>
where
S: FormString,
{
types: Vec<Type<PortableForm<S>>>,
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(Clone, Debug, PartialEq, Eq, Encode)]
pub struct PortableRegistry {
types: Vec<Type<PortableForm>>,
}

impl From<Registry> for PortableRegistry {
Expand All @@ -191,19 +180,14 @@ impl From<Registry> for PortableRegistry {
}
}

impl<S> PortableRegistry<S>
where
S: FormString,
{
impl PortableRegistry {
/// Returns the type definition for the given identifier, `None` if no type found for that ID.
pub fn resolve(&self, id: NonZeroU32) -> Option<&Type<PortableForm<S>>> {
pub fn resolve(&self, id: NonZeroU32) -> Option<&Type<PortableForm>> {
self.types.get((id.get() - 1) as usize)
}

/// Returns an iterator for all types paired with their associated NonZeroU32 identifier.
pub fn enumerate(
&self,
) -> impl Iterator<Item = (NonZeroU32, &Type<PortableForm<S>>)> {
pub fn enumerate(&self) -> impl Iterator<Item = (NonZeroU32, &Type<PortableForm>)> {
self.types.iter().enumerate().map(|(i, ty)| {
let id = NonZeroU32::new(i as u32 + 1).expect("i + 1 > 0; qed");
(id, ty)
Expand Down
8 changes: 3 additions & 5 deletions src/ty/composite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ use crate::{
Registry,
};
use derive_more::From;
use scale::{
Decode,
Encode,
};
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{
de::DeserializeOwned,
Expand Down Expand Up @@ -71,7 +68,8 @@ use serde::{
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode)]
pub struct TypeDefComposite<T: Form = MetaForm> {
/// The fields of the composite type.
#[cfg_attr(
Expand Down
4 changes: 2 additions & 2 deletions src/ty/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::{
TypeInfo,
};
use scale::{
Decode,
Encode,
HasCompact,
};
Expand Down Expand Up @@ -66,7 +65,8 @@ use serde::{
/// may change.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)]
pub struct Field<T: Form = MetaForm> {
/// The name of the field. None for unnamed fields.
#[cfg_attr(
Expand Down
29 changes: 17 additions & 12 deletions src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ use crate::{
TypeInfo,
};
use derive_more::From;
use scale::{
Decode,
Encode,
};
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{
de::DeserializeOwned,
Expand Down Expand Up @@ -63,7 +60,8 @@ pub use self::{
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
pub struct Type<T: Form = MetaForm> {
/// The unique path to the type. Can be empty for built-in types
#[cfg_attr(
Expand Down Expand Up @@ -162,7 +160,8 @@ where
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
pub enum TypeDef<T: Form = MetaForm> {
/// A composite type (e.g. a struct or a tuple)
Composite(TypeDefComposite<T>),
Expand Down Expand Up @@ -200,9 +199,10 @@ impl IntoPortable for TypeDef {
}

/// A primitive Rust type.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub enum TypeDefPrimitive {
/// `bool` type
Bool,
Expand Down Expand Up @@ -237,8 +237,9 @@ pub enum TypeDefPrimitive {
}

/// An array type.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefArray<T: Form = MetaForm> {
/// The length of the array type.
len: u32,
Expand Down Expand Up @@ -291,7 +292,8 @@ where
))
)]
#[cfg_attr(feature = "serde", serde(transparent))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefTuple<T: Form = MetaForm> {
/// The types of the tuple fields.
fields: Vec<T::Type>,
Expand Down Expand Up @@ -336,7 +338,8 @@ where

/// A type to refer to a sequence of elements of the same type.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefSequence<T: Form = MetaForm> {
/// The element type of the sequence type.
#[cfg_attr(feature = "serde", serde(rename = "type"))]
Expand Down Expand Up @@ -384,8 +387,9 @@ where
}

/// A type wrapped in [`Compact`].
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefCompact<T: Form = MetaForm> {
/// The type wrapped in [`Compact`], i.e. the `T` in `Compact<T>`.
#[cfg_attr(feature = "serde", serde(rename = "type"))]
Expand Down Expand Up @@ -429,7 +433,8 @@ where
/// required to explicitly skip fields that cannot be represented in SCALE
/// encoding, using the `#[codec(skip)]` attribute.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Debug)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefPhantom<T: Form = MetaForm> {
/// The PhantomData type parameter
#[cfg_attr(feature = "serde", serde(rename = "type"))]
Expand Down
8 changes: 3 additions & 5 deletions src/ty/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ use crate::{
IntoPortable,
Registry,
};
use scale::{
Decode,
Encode,
};
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{
de::DeserializeOwned,
Expand All @@ -50,7 +47,6 @@ use serde::{
/// has been defined. The last
///
/// Rust prelude type may have an empty namespace definition.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
Expand All @@ -60,6 +56,8 @@ use serde::{
))
)]
#[cfg_attr(feature = "serde", serde(transparent))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Encode)]
pub struct Path<T: Form = MetaForm> {
/// The segments of the namespace.
segments: Vec<T::String>,
Expand Down
11 changes: 5 additions & 6 deletions src/ty/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ use crate::{
Registry,
};
use derive_more::From;
use scale::{
Decode,
Encode,
};
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{
de::DeserializeOwned,
Expand Down Expand Up @@ -84,7 +81,8 @@ use serde::{
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode)]
pub struct TypeDefVariant<T: Form = MetaForm> {
/// The variants of a variant type
#[cfg_attr(
Expand Down Expand Up @@ -149,7 +147,8 @@ where
deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
))
)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode, Decode)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)]
pub struct Variant<T: Form = MetaForm> {
/// The name of the variant.
name: T::String,
Expand Down
4 changes: 2 additions & 2 deletions test_suite/tests/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fn scale_encode_then_decode_to_readonly() {
let mut encoded = registry.encode();
let original_serialized = serde_json::to_value(registry).unwrap();

let readonly_decoded = PortableRegistry::<String>::decode(&mut &encoded[..]).unwrap();
let readonly_decoded = PortableRegistry::decode(&mut &encoded[..]).unwrap();
assert!(readonly_decoded
.resolve(NonZeroU32::new(1).unwrap())
.is_some());
Expand All @@ -79,7 +79,7 @@ fn json_serialize_then_deserialize_to_readonly() {
let registry: PortableRegistry = registry.into();
let original_serialized = serde_json::to_value(registry).unwrap();
// assert_eq!(original_serialized, serde_json::Value::Null);
let readonly_deserialized: PortableRegistry<String> =
let readonly_deserialized: PortableRegistry =
serde_json::from_value(original_serialized.clone()).unwrap();
assert!(readonly_deserialized
.resolve(NonZeroU32::new(1).unwrap())
Expand Down