Skip to content

Commit

Permalink
Add feature for enabling decoding (#59)
Browse files Browse the repository at this point in the history
* Add feature for enabling decoding

* Fmt

* Fix up no_std test errors and warnings

* Only derive Decode when decode feature enabled

* Fix ununsed import warnings for scale::Decode on --no-default-features

* Apply conditional Decode derive to TypeDefCompact
  • Loading branch information
ascjones authored Feb 4, 2021
1 parent 6257337 commit f0f689b
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 78 deletions.
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 {}

/// 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

0 comments on commit f0f689b

Please sign in to comment.