diff --git a/Cargo.lock b/Cargo.lock index 2504a95..7dcf637 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4463,8 +4463,8 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", + "scale-info", "syn 2.0.66", - "xcq-types", ] [[package]] @@ -4498,7 +4498,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "xcq-extension", - "xcq-primitives", ] [[package]] @@ -4508,7 +4507,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "xcq-extension", - "xcq-primitives", ] [[package]] @@ -4529,7 +4527,6 @@ version = "0.1.0" dependencies = [ "parity-scale-codec", "scale-info", - "xcq-types", ] [[package]] @@ -4547,6 +4544,7 @@ dependencies = [ "clap", "parity-scale-codec", "polkavm", + "scale-info", "tracing", "tracing-subscriber 0.3.18", "xcq-executor", @@ -4556,27 +4554,6 @@ dependencies = [ "xcq-primitives", ] -[[package]] -name = "xcq-types" -version = "0.1.0" -dependencies = [ - "cfg-if", - "fortuples", - "parity-scale-codec", - "serde", - "xcq-types-derive", -] - -[[package]] -name = "xcq-types-derive" -version = "0.1.0" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "zerocopy" version = "0.7.34" diff --git a/Cargo.toml b/Cargo.toml index 95e1f4f..35c31a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ members = [ "xcq-primitives", "xcq-runtime-api", "xcq-test-runner", - "xcq-types", "examples/example-fungibles", "examples/example-helloworld", @@ -40,7 +39,6 @@ xcq-extension = { path = "xcq-extension", default-features = false } xcq-primitives = { path = "xcq-primitives", default-features = false } xcq-runtime-api = { path = "xcq-runtime-api", default-features = false } xcq-test-runner = { path = "xcq-test-runner", default-features = false } -xcq-types = { path = "xcq-types", default-features = false } # polkavm polkavm = { path = "vendor/polkavm/crates/polkavm", default-features = false } diff --git a/Makefile b/Makefile index 1104669..22f3369 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ fmt: cargo fmt --all check-wasm: - cargo check --no-default-features --target=wasm32-unknown-unknown -p xcq-api -p xcq-executor -p xcq-extension-core -p xcq-extension-fungibles -p xcq-extension -p xcq-primitives -p xcq-runtime-api -p xcq-types + cargo check --no-default-features --target=wasm32-unknown-unknown -p xcq-api -p xcq-executor -p xcq-extension-core -p xcq-extension-fungibles -p xcq-extension -p xcq-primitives -p xcq-runtime-api SKIP_WASM_BUILD= cargo check --no-default-features --target=wasm32-unknown-unknown -p poc-runtime check: check-wasm diff --git a/poc/guests/Cargo.lock b/poc/guests/Cargo.lock index 7d5621c..74dfa89 100644 --- a/poc/guests/Cargo.lock +++ b/poc/guests/Cargo.lock @@ -40,22 +40,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "equivalent" -version = "1.0.1" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "fortuples" -version = "0.9.1" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87630a8087e9cac4b7edfb6ee5e250ddca9112b57b6b17d8f5107375a3a8eace" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.63", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "hashbrown" version = "0.14.5" @@ -236,6 +245,30 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.63", +] + [[package]] name = "syn" version = "1.0.109" @@ -306,26 +339,6 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.63", - "xcq-types", -] - -[[package]] -name = "xcq-types" -version = "0.1.0" -dependencies = [ - "cfg-if", - "fortuples", - "parity-scale-codec", - "xcq-types-derive", -] - -[[package]] -name = "xcq-types-derive" -version = "0.1.0" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", + "scale-info", "syn 2.0.63", ] diff --git a/poc/runtime/Cargo.toml b/poc/runtime/Cargo.toml index 4bdbe05..19b402b 100644 --- a/poc/runtime/Cargo.toml +++ b/poc/runtime/Cargo.toml @@ -54,6 +54,7 @@ std = [ "xcq-executor/std", "xcq-extension/std", + "xcq-primitives/std", "xcq-extension-core/std", "xcq-extension-fungibles/std", ] diff --git a/poc/runtime/src/xcq.rs b/poc/runtime/src/xcq.rs index a02d1f8..878d686 100644 --- a/poc/runtime/src/xcq.rs +++ b/poc/runtime/src/xcq.rs @@ -3,12 +3,10 @@ use frame::deps::scale_info::prelude::{format, string::String}; use frame::deps::sp_api::decl_runtime_apis; use frame::prelude::*; -pub type XcqResponse = Vec; -pub type XcqError = String; -pub type XcqResult = Result; +use xcq_extension::metadata::Metadata; +pub use xcq_primitives::XcqResult; use xcq_extension::{impl_extensions, ExtensionsExecutor, Guest, Input, InvokeSource, Method}; -use xcq_primitives::metadata::Metadata; decl_runtime_apis! { pub trait XcqApi { fn execute_query(query: Vec, input: Vec) -> XcqResult; @@ -86,7 +84,7 @@ pub fn execute_query(query: Vec, input: Vec) -> XcqResult { } pub fn metadata() -> Metadata { - ExtensionImpl::runtime_metadata().into() + ExtensionImpl::metadata() } #[cfg(test)] diff --git a/xcq-api/procedural/Cargo.toml b/xcq-api/procedural/Cargo.toml index 064e941..03a678b 100644 --- a/xcq-api/procedural/Cargo.toml +++ b/xcq-api/procedural/Cargo.toml @@ -12,5 +12,5 @@ syn = { workspace = true } proc-macro2 = { workspace = true } proc-macro-crate = { workspace = true } Inflector = { workspace = true } -xcq-types = { workspace = true } parity-scale-codec = { workspace = true } +scale-info = { workspace = true } diff --git a/xcq-api/procedural/src/program/expand/mod.rs b/xcq-api/procedural/src/program/expand/mod.rs index d37c8ab..bd8c8ca 100644 --- a/xcq-api/procedural/src/program/expand/mod.rs +++ b/xcq-api/procedural/src/program/expand/mod.rs @@ -3,6 +3,7 @@ use inflector::Inflector; use parity_scale_codec::Encode; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote, ToTokens}; +use scale_info::{meta_type, PortableRegistry, Registry}; use syn::{ItemFn, PathArguments, Result}; pub fn expand(def: Def) -> Result { let preludes = generate_preludes(); @@ -48,7 +49,6 @@ fn generate_call(item: &ItemFn) -> Result { } impl #call_name { pub fn call(&self) -> #return_ty { - // TODO: use xcq-types to represent the return type let res = unsafe { host_call(self.extension_id, self.call_ptr, self.call_size) }; @@ -100,33 +100,53 @@ fn generate_return_ty_assertion(call_def: &CallDef) -> Result { .ok_or_else(|| syn::Error::new_spanned(path, "expected function return type to be a path"))?; match last_segment.ident.to_string().as_str() { "u8" => { - let encoded_ty_bytes = xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U8).encode(); + let ty = meta_type::(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } "u16" => { - let encoded_ty_bytes = xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U16).encode(); + let ty = meta_type::(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } "u32" => { - let encoded_ty_bytes = xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U32).encode(); + let ty = meta_type::(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } "u64" => { - let encoded_ty_bytes = xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U64).encode(); + let ty = meta_type::(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } "u128" => { - let encoded_ty_bytes = xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U128).encode(); + let ty = meta_type::(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } "Vec" => { @@ -136,12 +156,13 @@ fn generate_return_ty_assertion(call_def: &CallDef) -> Result { Some(syn::GenericArgument::Type(syn::Type::Path(path))) if path.path.is_ident("u8") => { - let encoded_ty_bytes = xcq_types::XcqType::Sequence(Box::new( - xcq_types::XcqType::Primitive(xcq_types::PrimitiveType::U8), - )) - .encode(); + let ty = meta_type::>(); + let mut registry = Registry::new(); + registry.register_type(&ty); + let portable_registry = PortableRegistry::from(registry); + let ty_bytes = portable_registry.encode(); quote! { - &[#(#encoded_ty_bytes),*] + &[#(#ty_bytes),*] } } _ => quote! { &[0u8] }, diff --git a/xcq-extension-core/Cargo.toml b/xcq-extension-core/Cargo.toml index 100f8bb..8b40b7d 100644 --- a/xcq-extension-core/Cargo.toml +++ b/xcq-extension-core/Cargo.toml @@ -11,8 +11,7 @@ version.workspace = true parity-scale-codec = { workspace = true } xcq-extension = { workspace = true } scale-info = { workspace = true } -xcq-primitives = { workspace = true } [features] default = ["std"] -std = ["parity-scale-codec/std", "xcq-extension/std"] +std = ["parity-scale-codec/std", "scale-info/std", "xcq-extension/std"] diff --git a/xcq-extension-fungibles/Cargo.toml b/xcq-extension-fungibles/Cargo.toml index 1a9be94..175658b 100644 --- a/xcq-extension-fungibles/Cargo.toml +++ b/xcq-extension-fungibles/Cargo.toml @@ -11,8 +11,7 @@ version.workspace = true parity-scale-codec = { workspace = true } xcq-extension = { workspace = true } scale-info = { workspace = true } -xcq-primitives = { workspace = true } [features] default = ["std"] -std = ["parity-scale-codec/std", "xcq-extension/std"] +std = ["parity-scale-codec/std", "scale-info/std", "xcq-extension/std"] diff --git a/xcq-extension/Cargo.toml b/xcq-extension/Cargo.toml index e4da5a9..4fea96c 100644 --- a/xcq-extension/Cargo.toml +++ b/xcq-extension/Cargo.toml @@ -8,20 +8,22 @@ repository.workspace = true version.workspace = true [dependencies] -parity-scale-codec = { workspace = true } polkavm = { workspace = true } -scale-info = { workspace = true } xcq-executor = { workspace = true } fortuples = { workspace = true } tracing = { workspace = true } xcq-extension-procedural = { path = "procedural" } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } xcq-primitives = { workspace = true } [features] default = ["std"] std = [ + "polkavm/std", + "xcq-executor/std", + "xcq-primitives/std", "parity-scale-codec/std", "scale-info/std", - "xcq-executor/std", "tracing/std", ] diff --git a/xcq-extension/procedural/src/decl_extensions.rs b/xcq-extension/procedural/src/decl_extensions.rs index 9cd9988..4beaa31 100644 --- a/xcq-extension/procedural/src/decl_extensions.rs +++ b/xcq-extension/procedural/src/decl_extensions.rs @@ -36,7 +36,7 @@ pub fn decl_extension_inner(item_trait: &ItemTrait) -> Result { let call_enum_def = call_enum_def(&item_trait.ident, &methods)?; let call_data_dispatchable_impl = impl_dispatchable(&item_trait.ident, &methods)?; let call_data_extension_id_impl = impl_extension_id(&item_trait.ident, &item_trait.items)?; - let call_data_metadata_impl = impl_metadata(&item_trait.ident)?; + let call_data_metadata_impl = impl_call_metadata(&item_trait.ident)?; let extension_runtime_metadata = crate::runtime_metadata::generate_decl_metadata(&item_trait, has_config)?; let expanded = quote! { @@ -61,7 +61,7 @@ fn add_super_trait(item_trait: &mut ItemTrait) -> Result<()> { // item_trait.supertraits.push(parse_quote!(#xcq_extension::ExtensionId)); item_trait .supertraits - .push(parse_quote!(#xcq_extension::ExtensionMetadata)); + .push(parse_quote!(#xcq_extension::ExtensionImplMetadata)); Ok(()) } @@ -74,7 +74,6 @@ struct Method { } fn call_enum_def(trait_ident: &Ident, methods: &[Method]) -> Result { - let xcq_primitives = generate_crate_access("xcq-primitives")?; let mut variants = Punctuated::::new(); for method in methods { let name = &method.name; @@ -98,7 +97,7 @@ fn call_enum_def(trait_ident: &Ident, methods: &[Method]) -> Result { __Phantom(core::marker::PhantomData) )); Ok(parse_quote!( - #[derive(#xcq_primitives::deps::parity_scale_codec::Decode)] + #[derive(parity_scale_codec::Decode)] pub enum Call { #variants } @@ -107,7 +106,6 @@ fn call_enum_def(trait_ident: &Ident, methods: &[Method]) -> Result { fn impl_dispatchable(trait_ident: &Ident, methods: &[Method]) -> Result { let xcq_extension = generate_crate_access("xcq-extension")?; - let xcq_primitives = generate_crate_access("xcq-primitives")?; let mut pats = Vec::::new(); for method in methods { let name = &method.name; @@ -142,7 +140,7 @@ fn impl_dispatchable(trait_ident: &Ident, methods: &[Method]) -> Result #xcq_extension::Dispatchable for Call { - fn dispatch(self) -> Result<#xcq_primitives::deps::xcq_types::vec::Vec, #xcq_extension::DispatchError> { + fn dispatch(self) -> Result, #xcq_extension::DispatchError> { match self { #( #pats => Ok(#method_calls.encode()),)* Self::__Phantom(_) => unreachable!(), @@ -167,12 +165,11 @@ fn impl_extension_id(trait_ident: &Ident, trait_items: &[TraitItem]) -> Result Result { +fn impl_call_metadata(trait_ident: &Ident) -> Result { let xcq_extension = generate_crate_access("xcq-extension")?; - let xcq_primitives = generate_crate_access("xcq-primitives")?; Ok(parse_quote! { impl #xcq_extension::CallMetadata for Call { - fn metadata() -> #xcq_primitives::metadata_ir::ExtensionMetadataIR { + fn call_metadata() -> #xcq_extension::metadata::ExtensionMetadata { Impl::extension_metadata(::EXTENSION_ID) } } diff --git a/xcq-extension/procedural/src/runtime_metadata.rs b/xcq-extension/procedural/src/runtime_metadata.rs index 1c8a3c7..e3e8ca0 100644 --- a/xcq-extension/procedural/src/runtime_metadata.rs +++ b/xcq-extension/procedural/src/runtime_metadata.rs @@ -13,7 +13,7 @@ use syn::{ /// The metadata is exposed as a generic function on the hidden module /// of the trait generated by the `decl_extensions`. pub fn generate_decl_metadata(decl: &ItemTrait, has_config: bool) -> Result { - let xcq_primitives = generate_crate_access("xcq-primitives")?; + let xcq_extension = generate_crate_access("xcq-extension")?; let mut methods = Vec::new(); // Convert `::Associated` to `T::Associated` with `T:Config` bound @@ -21,7 +21,7 @@ pub fn generate_decl_metadata(decl: &ItemTrait, has_config: bool) -> Result Result(), + ty: scale_info::meta_type::<#ty>(), } )); } let output = match &signature.output { - syn::ReturnType::Default => quote!(#xcq_primitives::deps::xcq_types::meta_type::<()>()), + syn::ReturnType::Default => quote!(scale_info::meta_type::<()>()), syn::ReturnType::Type(_, ty) => { let mut ty = ty.clone(); if has_config { replacer.visit_type_mut(&mut ty); } where_clause.push(get_type_param(&ty)); - quote!(#xcq_primitives::deps::xcq_types::meta_type::<#ty>()) + quote!(scale_info::meta_type::<#ty>()) } }; @@ -69,9 +69,9 @@ pub fn generate_decl_metadata(decl: &ItemTrait, has_config: bool) -> Result Result Result #xcq_primitives::metadata_ir::ExtensionMetadataIR + pub fn extension_metadata #impl_generics () -> #xcq_extension::metadata::ExtensionMetadata #where_clause { - #xcq_primitives::metadata_ir::ExtensionMetadataIR { + #xcq_extension::metadata::ExtensionMetadata { name: #trait_name, - methods: #xcq_primitives::deps::xcq_types::vec![ #( #methods, )* ], + methods: scale_info::prelude::vec![ #( #methods, )* ], } } )) @@ -116,10 +116,10 @@ pub fn generate_decl_metadata(decl: &ItemTrait, has_config: bool) -> Result #xcq_primitives::metadata_ir::ExtensionMetadataIR { - #xcq_primitives::metadata_ir::ExtensionMetadataIR { + pub fn extension_metadata() -> #xcq_extension::metadata::ExtensionMetadata { + #xcq_extension::metadata::ExtensionMetadata { name: #trait_name, - methods: #xcq_primitives::deps::xcq_types::vec![ #( #methods, )* ], + methods: scale_info::prelude::vec![ #( #methods, )* ], } } )) @@ -135,8 +135,6 @@ pub fn generate_impl_metadata(impls: &[ItemImpl]) -> Result { return Ok(quote!()); } - let xcq_primitives = generate_crate_access("xcq-primitives")?; - let xcq_extension = generate_crate_access("xcq-extension")?; // Get the name of the runtime for which the traits are implemented. @@ -145,7 +143,7 @@ pub fn generate_impl_metadata(impls: &[ItemImpl]) -> Result { .expect("Traits should contain at least one implementation; qed") .self_ty; - let mut metadata = Vec::new(); + let mut extension_metadata_list = Vec::new(); let mut extension_ids = Vec::new(); for impl_ in impls { @@ -187,33 +185,38 @@ pub fn generate_impl_metadata(impls: &[ItemImpl]) -> Result { } let attrs = &impl_.attrs; - metadata.push(quote!( + extension_metadata_list.push(quote!( #( #attrs )* - #trait_::runtime_metadata::#generics() + #trait_::extension_metadata::#generics() )); extension_ids.push(quote!(#extension_trait_full_path)); } - let extension_metadata_impl = quote! { - impl #xcq_extension::ExtensionMetadata for #extension_impl_name { - fn extension_metadata(extension_id: #xcq_extension::ExtensionIdTy) -> #xcq_primitives::metadata_ir::ExtensionMetadataIR { - match extension_id { - #(#extension_ids => #metadata,)* + let query_metadata_by_extension_id = quote! { + impl #xcq_extension::ExtensionImplMetadata for #extension_impl_name { + fn extension_metadata(extension_id: #xcq_extension::ExtensionIdTy) -> #xcq_extension::metadata::ExtensionMetadata { + let extension_metadata = match extension_id { + #(#extension_ids => #extension_metadata_list,)* _ => panic!("Unknown extension id"), - } + }; + extension_metadata } } }; - Ok(quote!( - #extension_metadata_impl + let aggregate_metadata = quote! { impl #extension_impl_name { - pub fn runtime_metadata() -> #xcq_primitives::metadata_ir::MetadataIR { - #xcq_primitives::metadata_ir::MetadataIR { - extensions: #xcq_primitives::deps::xcq_types::vec![ #( #metadata, )* ], - } + pub fn metadata() -> #xcq_extension::metadata::Metadata { + #xcq_extension::metadata::Metadata::new( + scale_info::prelude::vec![ #( #extension_metadata_list, )* ], + ) } } + }; + + Ok(quote!( + #query_metadata_by_extension_id + #aggregate_metadata )) } diff --git a/xcq-extension/src/dispatchable.rs b/xcq-extension/src/dispatchable.rs index 45657b5..fba1a00 100644 --- a/xcq-extension/src/dispatchable.rs +++ b/xcq-extension/src/dispatchable.rs @@ -1,4 +1,4 @@ -use crate::Vec; +use scale_info::prelude::vec::Vec; pub trait Dispatchable { fn dispatch(self) -> Result, DispatchError>; } diff --git a/xcq-extension/src/lib.rs b/xcq-extension/src/lib.rs index 4bb160a..57f06a2 100644 --- a/xcq-extension/src/lib.rs +++ b/xcq-extension/src/lib.rs @@ -1,22 +1,15 @@ -#![cfg_attr(not(feature = "std"), no_std)] -use core::marker::PhantomData; -extern crate alloc; -pub use alloc::vec::Vec; - use parity_scale_codec::Decode; -#[cfg(not(feature = "std"))] -use scale_info::prelude::{format, string::String}; +use scale_info::prelude::{format, marker::PhantomData, vec::Vec}; use xcq_executor::{Caller, Linker, XcqExecutor, XcqExecutorContext}; pub type XcqResponse = Vec; -pub type XcqError = String; -pub type XcqResult = Result; +use xcq_primitives::{XcqError, XcqResult}; mod dispatchable; pub use dispatchable::{DispatchError, Dispatchable}; -mod metadata; -pub use metadata::{CallMetadata, ExtensionMetadata}; mod extension_id; +pub mod metadata; pub use extension_id::{ExtensionId, ExtensionIdTy}; +pub use metadata::{CallMetadata, ExtensionImplMetadata}; mod error; pub use error::ExtensionError; mod macros; @@ -139,6 +132,6 @@ impl ExtensionsExecutor { pub fn execute_method(&mut self, guest: G, input: I) -> XcqResult { self.executor .execute(guest.program(), &input.method(), input.args()) - .map_err(|e| format!("{:?}", e)) + .map_err(|e| XcqError::Custom(format!("{:?}", e))) } } diff --git a/xcq-extension/src/macros.rs b/xcq-extension/src/macros.rs index baa8df9..fcc872e 100644 --- a/xcq-extension/src/macros.rs +++ b/xcq-extension/src/macros.rs @@ -5,7 +5,7 @@ use crate::ExtensionIdTy; use crate::Vec; use fortuples::fortuples; use parity_scale_codec::Encode; - +use scale_info::{PortableRegistry, Registry}; // Use the macro to implement ExtensionTuple for tuples of different lengths fortuples! { impl CallDataTuple for #Tuple where #(#Member: CallData),*{ @@ -23,7 +23,13 @@ fortuples! { fn return_ty(extension_id: ExtensionIdTy, call_index: u32) -> Result, ExtensionError> { #( if extension_id == #Member::EXTENSION_ID { - return Ok(#Member::metadata().methods[call_index as usize].output.type_info().encode()); + let extension_metadata = #Member::call_metadata(); + // comparing the registry is equivalent to comparing the type + let return_ty = extension_metadata.methods[call_index as usize].output; + let mut registry = Registry::new(); + registry.register_type(&return_ty); + let portable_registry: PortableRegistry = registry.into(); + return Ok(portable_registry.encode()); } )* Err(ExtensionError::UnsupportedExtension) diff --git a/xcq-extension/src/metadata.rs b/xcq-extension/src/metadata.rs index 278a194..9a7bfa9 100644 --- a/xcq-extension/src/metadata.rs +++ b/xcq-extension/src/metadata.rs @@ -1,12 +1,120 @@ -use xcq_primitives::metadata_ir::ExtensionMetadataIR; - use crate::extension_id; // This trait is for CallData pub trait CallMetadata { - fn metadata() -> ExtensionMetadataIR; + fn call_metadata() -> ExtensionMetadata; +} + +// This trait is for ExtensionImpl +pub trait ExtensionImplMetadata { + fn extension_metadata(extension_id: extension_id::ExtensionIdTy) -> ExtensionMetadata; +} + +#[cfg(feature = "decode")] +use parity_scale_codec::Decode; +#[cfg(feature = "serde_full")] +use serde::Serialize; + +use parity_scale_codec::Encode; +use scale_info::{ + form::{Form, MetaForm, PortableForm}, + prelude::vec::Vec, + IntoPortable, PortableRegistry, Registry, +}; +/// Metadata of extensions +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "decode", derive(Decode))] +#[cfg_attr(feature = "serde_full", derive(Serialize))] +pub struct Metadata { + pub types: PortableRegistry, + pub extensions: Vec>, } -// This trait is for runtime -pub trait ExtensionMetadata { - fn extension_metadata(extension_id: extension_id::ExtensionIdTy) -> ExtensionMetadataIR; +impl Metadata { + pub fn new(extensions: Vec) -> Self { + let mut registry = Registry::new(); + let extensions = registry.map_into_portable(extensions); + Self { + types: registry.into(), + extensions, + } + } +} + +/// Metadata of an extension. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "decode", derive(Decode))] +#[cfg_attr(feature = "serde_full", derive(Serialize))] +#[cfg_attr( + feature = "serde_full", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct ExtensionMetadata { + pub name: T::String, + pub methods: Vec>, +} + +impl IntoPortable for ExtensionMetadata { + type Output = ExtensionMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + ExtensionMetadata { + name: self.name.into_portable(registry), + methods: registry.map_into_portable(self.methods), + } + } +} + +/// Metadata of a runtime method. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "decode", derive(Decode))] +#[cfg_attr(feature = "serde_full", derive(Serialize))] +#[cfg_attr( + feature = "serde_full", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct MethodMetadata { + /// Method name. + pub name: T::String, + /// Method parameters. + pub inputs: Vec>, + /// Method output. + pub output: T::Type, +} + +impl IntoPortable for MethodMetadata { + type Output = MethodMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + MethodMetadata { + name: self.name.into_portable(registry), + inputs: registry.map_into_portable(self.inputs), + output: registry.register_type(&self.output), + } + } +} + +/// Metadata of a runtime method parameter. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "decode", derive(Decode))] +#[cfg_attr(feature = "serde_full", derive(Serialize))] +#[cfg_attr( + feature = "serde_full", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct MethodParamMetadata { + /// Parameter name. + pub name: T::String, + /// Parameter type. + pub ty: T::Type, +} + +impl IntoPortable for MethodParamMetadata { + type Output = MethodParamMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + MethodParamMetadata { + name: self.name.into_portable(registry), + ty: registry.register_type(&self.ty), + } + } } diff --git a/xcq-extension/tests/with_associated_types_works.rs b/xcq-extension/tests/with_associated_types_works.rs index 04b9933..0e51cd7 100644 --- a/xcq-extension/tests/with_associated_types_works.rs +++ b/xcq-extension/tests/with_associated_types_works.rs @@ -1,7 +1,6 @@ use parity_scale_codec::{Codec, Decode, Encode}; +use xcq_extension::metadata::Metadata; use xcq_extension::{decl_extensions, impl_extensions, ExtensionsExecutor, Guest, Input, InvokeSource, Method}; -use xcq_primitives::deps::xcq_types::{PrimitiveType, XcqType}; -use xcq_primitives::metadata::{ExtensionMetadata, Metadata, MethodMetadata, MethodParamMetadata}; mod extension_core { use super::*; @@ -199,51 +198,12 @@ fn single_call_works() { #[test] fn metadata_works() { - let metadata: Metadata = ExtensionImpl::runtime_metadata().into(); - println!("{:?}", metadata); - assert_eq!( - metadata, - Metadata { - extensions: vec![ - ExtensionMetadata { - name: "ExtensionCore", - methods: vec![MethodMetadata { - name: "has_extension", - inputs: vec![MethodParamMetadata { - name: "id", - ty: XcqType::Primitive(PrimitiveType::U64) - }], - output: XcqType::Primitive(PrimitiveType::Bool) - }] - }, - ExtensionMetadata { - name: "ExtensionFungibles", - methods: vec![ - MethodMetadata { - name: "total_supply", - inputs: vec![MethodParamMetadata { - name: "asset", - ty: XcqType::Primitive(PrimitiveType::U32) - }], - output: XcqType::Primitive(PrimitiveType::U64) - }, - MethodMetadata { - name: "balance", - inputs: vec![ - MethodParamMetadata { - name: "asset", - ty: XcqType::Primitive(PrimitiveType::U32) - }, - MethodParamMetadata { - name: "who", - ty: XcqType::Primitive(PrimitiveType::H256) - } - ], - output: XcqType::Primitive(PrimitiveType::U64) - } - ] - } - ] - } - ) + let metadata: Metadata = ExtensionImpl::metadata(); + let registry = metadata.types; + let extension_metadata_list = metadata.extensions; + // bool, u8, u32, u64, [u8;32] + assert_eq!(registry.types.len(), 5); + assert_eq!(extension_metadata_list.len(), 2); + assert_eq!(extension_metadata_list[0].name, "ExtensionCore"); + assert_eq!(extension_metadata_list[1].name, "ExtensionFungibles"); } diff --git a/xcq-primitives/Cargo.toml b/xcq-primitives/Cargo.toml index 9c65633..30dcc40 100644 --- a/xcq-primitives/Cargo.toml +++ b/xcq-primitives/Cargo.toml @@ -10,8 +10,7 @@ version.workspace = true [dependencies] parity-scale-codec = { workspace = true } scale-info = { workspace = true } -xcq-types = { workspace = true } [features] default = ["std"] -std = ["parity-scale-codec/std", "scale-info/std", "xcq-types/std"] +std = ["parity-scale-codec/std", "scale-info/std"] diff --git a/xcq-primitives/src/lib.rs b/xcq-primitives/src/lib.rs index ad78d65..f0fa12d 100644 --- a/xcq-primitives/src/lib.rs +++ b/xcq-primitives/src/lib.rs @@ -14,12 +14,3 @@ pub enum XcqError { } pub type XcqResult = Result; - -pub mod metadata; -pub mod metadata_ir; - -#[doc(hidden)] -pub mod deps { - pub use parity_scale_codec; - pub use xcq_types; -} diff --git a/xcq-primitives/src/metadata.rs b/xcq-primitives/src/metadata.rs deleted file mode 100644 index 52b418f..0000000 --- a/xcq-primitives/src/metadata.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::metadata_ir::{ExtensionMetadataIR, MetadataIR, MethodMetadataIR, MethodParamMetadataIR}; -use parity_scale_codec::Encode; -use xcq_types::{vec::Vec, XcqType}; -/// Metadata of an extension method. -#[derive(Clone, PartialEq, Eq, Debug, Encode)] -pub struct MethodMetadata { - /// Method name. - pub name: &'static str, - /// Method parameters. - pub inputs: Vec, - /// Method output. - pub output: XcqType, -} - -/// Metadata of an method parameter. -#[derive(Clone, PartialEq, Eq, Debug, Encode)] -pub struct MethodParamMetadata { - /// Parameter name. - pub name: &'static str, - /// Parameter type. - pub ty: XcqType, -} - -/// Metadata of an extension -#[derive(Clone, PartialEq, Eq, Debug, Encode)] -pub struct ExtensionMetadata { - pub name: &'static str, - pub methods: Vec, -} - -/// Metadata of extensions -#[derive(Clone, PartialEq, Eq, Debug, Encode)] -pub struct Metadata { - pub extensions: Vec, -} - -impl From for MethodParamMetadata { - fn from(ir: MethodParamMetadataIR) -> Self { - Self { - name: ir.name, - ty: ir.ty.type_info(), - } - } -} - -impl From for MethodMetadata { - fn from(ir: MethodMetadataIR) -> Self { - Self { - name: ir.name, - inputs: ir.inputs.into_iter().map(MethodParamMetadata::from).collect(), - output: ir.output.type_info(), - } - } -} - -impl From for ExtensionMetadata { - fn from(ir: ExtensionMetadataIR) -> Self { - Self { - name: ir.name, - methods: ir.methods.into_iter().map(MethodMetadata::from).collect(), - } - } -} - -impl From for Metadata { - fn from(ir: MetadataIR) -> Self { - Self { - extensions: ir.extensions.into_iter().map(ExtensionMetadata::from).collect(), - } - } -} diff --git a/xcq-primitives/src/metadata_ir.rs b/xcq-primitives/src/metadata_ir.rs deleted file mode 100644 index 659d259..0000000 --- a/xcq-primitives/src/metadata_ir.rs +++ /dev/null @@ -1,36 +0,0 @@ -use xcq_types::{vec::Vec, MetaType}; -/// Metadata of a runtime method. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct MethodMetadataIR { - /// Method name. - pub name: &'static str, - /// Method parameters. - pub inputs: Vec, - /// Method output. - pub output: MetaType, -} - -/// Metadata of a runtime method parameter. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct MethodParamMetadataIR { - /// Parameter name. - pub name: &'static str, - /// Parameter type. - pub ty: MetaType, -} - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct ExtensionMetadataIR { - pub name: &'static str, - pub methods: Vec, -} - -/// Metadata of extensions -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct MetadataIR { - pub extensions: Vec, -} - -pub trait RuntimeMetadata { - fn runtime_metadata() -> MetadataIR; -} diff --git a/xcq-test-runner/Cargo.toml b/xcq-test-runner/Cargo.toml index 018af19..740ddda 100644 --- a/xcq-test-runner/Cargo.toml +++ b/xcq-test-runner/Cargo.toml @@ -9,14 +9,15 @@ version.workspace = true [dependencies] clap = { workspace = true } -tracing = { workspace = true } +tracing = { workspace = true, features = ["std"] } tracing-subscriber = { workspace = true } parity-scale-codec = { workspace = true, features = ["std"] } +scale-info = { workspace = true, features = ["std"] } xcq-executor = { workspace = true, features = ["std"] } xcq-extension = { workspace = true, features = ["std"] } xcq-extension-core = { workspace = true, features = ["std"] } xcq-extension-fungibles = { workspace = true, features = ["std"] } -xcq-primitives = { workspace = true } +xcq-primitives = { workspace = true, features = ["std"] } -polkavm = { workspace = true } +polkavm = { workspace = true, features = ["std"] } diff --git a/xcq-types/Cargo.toml b/xcq-types/Cargo.toml deleted file mode 100644 index 02937e2..0000000 --- a/xcq-types/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "xcq-types" -description = "Metatype system for XCQ" -authors.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true -version.workspace = true - -[dependencies] -cfg-if = "1.0" -parity-scale-codec = { workspace = true } -serde = { version = "1", default-features = false, optional = true, features = [ - "derive", -] } -fortuples = { workspace = true } -xcq-types-derive = { path = "derive" } - -[features] -default = ["std"] -std = ["parity-scale-codec/std"] diff --git a/xcq-types/derive/Cargo.toml b/xcq-types/derive/Cargo.toml deleted file mode 100644 index 39887fd..0000000 --- a/xcq-types/derive/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "xcq-types-derive" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -quote = { workspace = true } -syn = { workspace = true } -proc-macro2 = { workspace = true } -proc-macro-crate = { workspace = true } diff --git a/xcq-types/derive/src/lib.rs b/xcq-types/derive/src/lib.rs deleted file mode 100644 index e4dcabe..0000000 --- a/xcq-types/derive/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -use proc_macro::TokenStream; -use proc_macro2::TokenStream as TokenStream2; -use proc_macro_crate::{crate_name, FoundCrate}; -use quote::quote; -use syn::{punctuated::Punctuated, token::Comma, Data, DataEnum, DataStruct, DeriveInput, Field, Fields}; - -#[proc_macro_derive(XcqTypeInfo)] -pub fn derive_xcq_type_info(input: TokenStream) -> TokenStream { - match generate(input.into()) { - Ok(output) => output.into(), - Err(err) => err.to_compile_error().into(), - } -} - -fn generate(input: TokenStream2) -> syn::Result { - let type_info_impl: XcqTypeInfoImpl = XcqTypeInfoImpl::parse(input)?; - let type_info_impl_toks = type_info_impl.expand()?; - Ok(quote! { - // A rust pattern to ensure that the type info is implemented. - #[allow(non_upper_case_globals, unused_attributes, unused_imports)] - const _: () = { - #type_info_impl_toks - }; - }) -} - -struct XcqTypeInfoImpl { - ast: DeriveInput, -} - -impl XcqTypeInfoImpl { - fn parse(input: TokenStream2) -> syn::Result { - let ast = syn::parse2::(input)?; - // Assume no attributes - if !ast.attrs.is_empty() { - return Err(syn::Error::new_spanned(ast, "unexpected attributes")); - } - Ok(Self { ast }) - } - - fn expand(&self) -> syn::Result { - let xcq_types = import_xcq_types(); - let ident = &self.ast.ident; - - // Assume no generics - if self.ast.generics.type_params().next().is_some() { - return Err(syn::Error::new_spanned( - &self.ast.generics, - "generics are not supported", - )); - } - - let type_info = match &self.ast.data { - Data::Struct(ref s) => self.generate_struct_type(s), - Data::Enum(ref e) => self.generate_enum_type(e), - Data::Union(_) => { - return Err(syn::Error::new_spanned(&self.ast, "unions are not supported")); - } - }; - - // TODO: No token replacement supported yet - Ok(quote! { - impl #xcq_types::XcqTypeInfo for #ident { - type Identity = Self; - fn type_info() -> #xcq_types::XcqType { - #type_info - } - } - }) - } - - fn generate_struct_type(&self, data_struct: &DataStruct) -> TokenStream2 { - let xcq_types = import_xcq_types(); - let ident = &self.ast.ident; - let fields = match data_struct.fields { - Fields::Named(ref fields) => self.generate_fields(&fields.named), - Fields::Unnamed(ref fields) => self.generate_fields(&fields.unnamed), - Fields::Unit => return quote! {}, - }; - - quote! { - #xcq_types::StructType { - ident: stringify!(#ident).as_bytes().to_vec(), - fields: vec![#(#fields),*], - }.into() - } - } - - fn generate_enum_type(&self, data_enum: &DataEnum) -> TokenStream2 { - let xcq_types = import_xcq_types(); - let ident = &self.ast.ident; - let variants = data_enum.variants.iter().map(|variant| { - let ident = &variant.ident; - let fields = match variant.fields { - Fields::Named(ref fields) => self.generate_fields(&fields.named), - Fields::Unnamed(ref fields) => self.generate_fields(&fields.unnamed), - Fields::Unit => return quote! {}, - }; - quote! { - #xcq_types::Variant { - ident: stringify!(#ident).as_bytes().to_vec(), - fields: vec![#(#fields),*], - } - } - }); - quote! { - #xcq_types::EnumType { - ident: stringify!(#ident).as_bytes().to_vec(), - variants: vec![#(#variants),*], - }.into() - } - } - - fn generate_fields(&self, fields: &Punctuated) -> Vec { - let xcq_types = import_xcq_types(); - fields - .iter() - .map(|f| { - let ty = &f.ty; - let ident_toks = match &f.ident { - Some(ident) => quote! { stringify!(#ident).as_bytes().to_vec()}, - None => quote! { vec![] }, - }; - quote! { - #xcq_types::Field { - ident: #ident_toks, - ty: <#ty as #xcq_types::XcqTypeInfo>::type_info(), - } - } - }) - .collect() - } -} - -fn import_xcq_types() -> TokenStream2 { - let found_crate = crate_name("xcq-types").expect("xcq-types not found in Cargo.toml"); - match found_crate { - FoundCrate::Itself => quote! { crate }, - FoundCrate::Name(name) => { - let crate_ = syn::Ident::new(&name.replace('-', "_"), proc_macro2::Span::call_site()); - quote! { ::#crate_ } - } - } -} diff --git a/xcq-types/src/impls.rs b/xcq-types/src/impls.rs deleted file mode 100644 index a95e652..0000000 --- a/xcq-types/src/impls.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::{boxed::Box, rc::Rc, string::String, sync::Arc, vec::Vec}; -use crate::{EnumType, Field, PrimitiveType, StructType, Variant}; -use crate::{XcqType, XcqTypeInfo}; -use fortuples::fortuples; - -macro_rules! impl_from_xcqtype_variant { - ($($from:ty => $variant: ident,)*) => { - $( - impl From<$from> for XcqType { - fn from(x: $from) -> Self { - Self::$variant(x) - } - } - )* - }; -} - -impl_from_xcqtype_variant! { - StructType => Struct, - EnumType => Enum, - PrimitiveType => Primitive, -} - -// Implement `XcqTypeInfo` for primitive types. -macro_rules! impl_metadata_for_primitives { - ( $($t:ty=> $ident_kind:expr ),*) => { - $( - impl XcqTypeInfo for $t { - type Identity = Self; - fn type_info() -> XcqType { - $ident_kind.into() - } - } - )* - } -} -impl_metadata_for_primitives! { - bool => PrimitiveType::Bool, - u8 => PrimitiveType::U8, - u16 => PrimitiveType::U16, - u32 => PrimitiveType::U32, - u64 => PrimitiveType::U64, - u128 => PrimitiveType::U128, - i8 => PrimitiveType::I8, - i16 => PrimitiveType::I16, - i32 => PrimitiveType::I32, - i64 => PrimitiveType::I64, - i128 => PrimitiveType::I128, - [u8;32] => PrimitiveType::H256 -} - -fortuples! { - impl XcqTypeInfo for #Tuple where #(#Member: XcqTypeInfo+'static),* { - type Identity = Self; - fn type_info() -> XcqType { - XcqType::Tuple(vec![ #(#Member::type_info()),* ]) - } - } -} - -impl XcqTypeInfo for Option -where - T: XcqTypeInfo + 'static, -{ - type Identity = Self; - fn type_info() -> XcqType { - EnumType { - ident: b"Option".to_vec(), - variants: vec![ - Variant { - ident: b"None".to_vec(), - fields: vec![], - }, - Variant { - ident: b"Some".to_vec(), - fields: vec![Field { - ident: vec![], - ty: T::type_info(), - }], - }, - ], - } - .into() - } -} - -impl XcqTypeInfo for Result -where - T: XcqTypeInfo + 'static, - E: XcqTypeInfo + 'static, -{ - type Identity = Self; - fn type_info() -> XcqType { - EnumType { - ident: b"Result".to_vec(), - variants: vec![ - Variant { - ident: b"Ok".to_vec(), - fields: vec![Field { - ident: vec![], - ty: T::type_info(), - }], - }, - Variant { - ident: b"Err".to_vec(), - fields: vec![Field { - ident: vec![], - ty: E::type_info(), - }], - }, - ], - } - .into() - } -} - -macro_rules! impl_metadata_for_smart_pointers { - ($($type:ty),*) => { - $( - impl XcqTypeInfo for $type - where - T: XcqTypeInfo + ?Sized + 'static, - { - type Identity = T; - fn type_info() -> XcqType { - Self::Identity::type_info() - } - } - )* - }; -} - -impl_metadata_for_smart_pointers! { - Box, - Arc, - Rc, - &T, - &mut T -} - -impl XcqTypeInfo for [T] -where - T: XcqTypeInfo + 'static, -{ - type Identity = Self; - fn type_info() -> XcqType { - XcqType::Sequence(Box::new(T::type_info())) - } -} - -impl XcqTypeInfo for Vec -where - T: XcqTypeInfo + 'static, -{ - type Identity = [T]; - fn type_info() -> XcqType { - Self::Identity::type_info() - } -} - -impl XcqTypeInfo for str { - type Identity = str; - fn type_info() -> XcqType { - XcqType::Sequence(Box::new(PrimitiveType::U8.into())) - } -} - -impl XcqTypeInfo for String { - type Identity = str; - fn type_info() -> XcqType { - Self::Identity::type_info() - } -} -// No impl for PhantomData, codec::Compact, Range, RangeInclusive, str, BTreeMap, BTreeSet, BinaryHeap, VecDeque yet. -// No support for self-referential types yet. diff --git a/xcq-types/src/lib.rs b/xcq-types/src/lib.rs deleted file mode 100644 index aa2ec7b..0000000 --- a/xcq-types/src/lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(not(feature = "std"))] -#[macro_use] -extern crate alloc; - -mod ty; -pub use ty::*; -mod impls; -mod prelude; -pub use prelude::*; -mod meta_type; -pub use meta_type::MetaType; -#[cfg(test)] -mod tests; - -pub use xcq_types_derive::XcqTypeInfo; - -/// Implementors return the meta type information. -pub trait XcqTypeInfo { - /// This is used to uniquely identify the type via [`core::any::TypeId::of`] - /// In most case it is Self, but for reference types it is the type of the reference. - type Identity: ?Sized + 'static; - fn type_info() -> XcqType; -} -/// helper trait for combining `XcqTypeInfo` and `'static -pub trait XcqStaticTypeInfo: XcqTypeInfo + 'static {} - -impl XcqStaticTypeInfo for T where T: XcqTypeInfo + 'static {} - -/// Returns the runtime bridge to the types compile-time type information. -pub fn meta_type() -> MetaType -where - T: ?Sized + XcqTypeInfo + 'static, -{ - MetaType::new::() -} diff --git a/xcq-types/src/meta_type.rs b/xcq-types/src/meta_type.rs deleted file mode 100644 index c59fda7..0000000 --- a/xcq-types/src/meta_type.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::prelude::{ - any::TypeId, - cmp::Ordering, - fmt::{Debug, Error as FmtError, Formatter}, - hash::{Hash, Hasher}, -}; - -use crate::{XcqType, XcqTypeInfo}; - -/// A metatype abstraction. -/// -/// Allows to store compile-time type information at runtime. -/// This again allows to derive type ID and type definition from it. -/// -/// This needs a conversion to another representation of types -/// in order to be serializable. -#[derive(Clone, Copy)] -pub struct MetaType { - /// Function pointer to get type information. - fn_type_info: fn() -> XcqType, - // The standard type ID (ab)used in order to provide - // cheap implementations of the standard traits - // such as `PartialEq`, `PartialOrd`, `Debug` and `Hash`. - type_id: TypeId, -} - -impl PartialEq for MetaType { - fn eq(&self, other: &Self) -> bool { - self.type_id == other.type_id - } -} - -impl Eq for MetaType {} - -impl PartialOrd for MetaType { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for MetaType { - fn cmp(&self, other: &Self) -> Ordering { - self.type_id.cmp(&other.type_id) - } -} - -impl Hash for MetaType { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.type_id.hash(state) - } -} - -impl Debug for MetaType { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - self.type_id.fmt(f) - } -} - -impl MetaType { - /// Creates a new meta type from the given compile-time known type. - pub fn new() -> Self - where - T: XcqTypeInfo + ?Sized + 'static, - { - Self { - fn_type_info: ::type_info, - type_id: TypeId::of::(), - } - } - - /// Returns the meta type information. - pub fn type_info(&self) -> XcqType { - (self.fn_type_info)() - } - - /// Returns the type identifier provided by `core::any`. - pub fn type_id(&self) -> TypeId { - self.type_id - } -} diff --git a/xcq-types/src/prelude.rs b/xcq-types/src/prelude.rs deleted file mode 100644 index dcb6824..0000000 --- a/xcq-types/src/prelude.rs +++ /dev/null @@ -1,50 +0,0 @@ -use cfg_if::cfg_if; - -cfg_if! { - if #[cfg(feature = "std")] { - pub use std::{ - any, - borrow, - boxed, - cmp, - collections, - fmt, - format, - hash, - marker, - mem, - num, - ops, - string, - sync, - time, - vec, - rc, - iter, - }; - } else { - pub use alloc::{ - borrow, - boxed, - collections, - format, - string, - sync, - vec, - rc - }; - - pub use core::{ - any, - cmp, - fmt, - hash, - marker, - mem, - num, - ops, - time, - iter, - }; - } -} diff --git a/xcq-types/src/tests.rs b/xcq-types/src/tests.rs deleted file mode 100644 index fcbb20f..0000000 --- a/xcq-types/src/tests.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::{EnumType, Field, PrimitiveType, StructType, Variant, XcqType, XcqTypeInfo}; - -fn assert_type_fn(expect: XcqType) { - assert_eq!(T::type_info(), expect); -} - -macro_rules! assert_type { - ($ty:ty, $expected: expr) => {{ - assert_type_fn::<$ty>($expected); - }}; -} - -#[test] -fn primitives() { - assert_type!(bool, XcqType::Primitive(PrimitiveType::Bool)); - assert_type!(&str, XcqType::Sequence(Box::new(PrimitiveType::U8.into()))); - assert_type!(i8, XcqType::Primitive(PrimitiveType::I8)); - assert_type!([bool], XcqType::Sequence(Box::new(PrimitiveType::Bool.into()))); -} - -#[test] -fn prelude_items() { - assert_type!(String, XcqType::Sequence(Box::new(PrimitiveType::U8.into()))); - - assert_type!( - Option, - XcqType::Enum(EnumType { - ident: b"Option".to_vec(), - variants: vec![ - Variant { - ident: b"None".to_vec(), - fields: vec![], - }, - Variant { - ident: b"Some".to_vec(), - fields: vec![Field { - ident: vec![], - ty: PrimitiveType::U128.into(), - }], - }, - ], - }) - ); - - assert_type!( - Result, - XcqType::Enum(EnumType { - ident: b"Result".to_vec(), - variants: vec![ - Variant { - ident: b"Ok".to_vec(), - fields: vec![Field { - ident: vec![], - ty: PrimitiveType::Bool.into(), - }], - }, - Variant { - ident: b"Err".to_vec(), - fields: vec![Field { - ident: vec![], - ty: XcqType::Sequence(Box::new(PrimitiveType::U8.into())), - }], - }, - ], - }) - ); -} - -#[test] -fn tuple_primitives() { - assert_type!((), XcqType::Tuple(vec![])); - assert_type!((bool,), XcqType::Tuple(vec![PrimitiveType::Bool.into()])); - assert_type!( - (bool, i8), - XcqType::Tuple(vec![PrimitiveType::Bool.into(), PrimitiveType::I8.into()]) - ); - assert_type!( - ((i8, i16), (u32, u64)), - XcqType::Tuple(vec![ - XcqType::Tuple(vec![PrimitiveType::I8.into(), PrimitiveType::I16.into()]), - XcqType::Tuple(vec![PrimitiveType::U32.into(), PrimitiveType::U64.into()]), - ]) - ); -} - -#[derive(XcqTypeInfo)] -struct Person { - #[allow(dead_code)] - name: String, - #[allow(dead_code)] - age_in_years: u8, -} -#[test] -fn struct_types() { - assert_type!( - Person, - XcqType::Struct(StructType { - ident: b"Person".to_vec(), - fields: vec![ - Field { - ident: b"name".to_vec(), - ty: XcqType::Sequence(Box::new(XcqType::Primitive(PrimitiveType::U8.into()))), - }, - Field { - ident: b"age_in_years".to_vec(), - ty: PrimitiveType::U8.into(), - }, - ], - }) - ); -} diff --git a/xcq-types/src/ty/enum.rs b/xcq-types/src/ty/enum.rs deleted file mode 100644 index 063f51a..0000000 --- a/xcq-types/src/ty/enum.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::{vec::Vec, Field}; -use parity_scale_codec::Encode; - -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] -pub struct Variant { - pub ident: Vec, - pub fields: Vec, -} - -/// A Enum type, consisting of variants -/// -/// # Example -/// -/// ## A Rust enum with unit -/// ``` -/// enum MyEnum { -/// RustAllowsUnitVariants, -/// AndAlsoForTupleStructs(i32, bool), -/// OrNamedStructs { name: String, age: u8 }, -/// } -/// ``` -/// -/// ## A C-like enum type -/// -/// ``` -/// enum Color { -/// Red, -/// Green, -/// Blue, -/// } -/// ``` -/// -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] -pub struct EnumType { - pub ident: Vec, - pub variants: Vec, -} diff --git a/xcq-types/src/ty/field.rs b/xcq-types/src/ty/field.rs deleted file mode 100644 index 0b3b0cd..0000000 --- a/xcq-types/src/ty/field.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::vec::Vec; -use crate::XcqType; -use parity_scale_codec::Encode; -// A Named or Unnamed field in a composite type -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] -pub struct Field { - pub ident: Vec, - pub ty: XcqType, -} diff --git a/xcq-types/src/ty/mod.rs b/xcq-types/src/ty/mod.rs deleted file mode 100644 index d4888e0..0000000 --- a/xcq-types/src/ty/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -use parity_scale_codec::Encode; -mod r#enum; -mod field; -mod primitive; -mod r#struct; -use crate::{boxed::Box, vec::Vec}; - -pub use self::{field::*, primitive::*, r#enum::*, r#struct::*}; - -/// Note: no Array Type yet -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] -pub enum XcqType { - Primitive(PrimitiveType), - Struct(StructType), - Enum(EnumType), - // TODO: deal with self-referential types - Tuple(Vec), - // TODO: deal with self-referential types - Sequence(Box), -} diff --git a/xcq-types/src/ty/primitive.rs b/xcq-types/src/ty/primitive.rs deleted file mode 100644 index 63ee1cd..0000000 --- a/xcq-types/src/ty/primitive.rs +++ /dev/null @@ -1,26 +0,0 @@ -use parity_scale_codec::Encode; - -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] -pub enum PrimitiveType { - Bool, - Char, - U8, - U16, - U32, - U64, - U128, - I8, - I16, - I32, - I64, - I128, - // TODO: representation - U256, - // TODO: representation - I256, - /// [u8; 32] - H256, - // TODO: more fixed-size arrays represented as primitives -} diff --git a/xcq-types/src/ty/struct.rs b/xcq-types/src/ty/struct.rs deleted file mode 100644 index a0d6743..0000000 --- a/xcq-types/src/ty/struct.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::{vec::Vec, Field}; -use parity_scale_codec::Encode; - -/// A struct type, consisting of a named (struct) or unnamed (tuple struct) fields or unit struct. -/// Note: in fact, it can represent a -/// -/// # Example -/// -/// ## A Rust struct with named fields. -/// -/// ``` -/// struct Person { -/// name: String, -/// age_in_years: u8, -/// friends: Vec, -/// } -/// ``` -/// -/// ## A tuple struct with unnamed fields. -/// -/// ``` -/// struct Color(u8, u8, u8); -/// ``` -/// -/// ## A so-called unit struct -/// -/// ``` -/// struct JustAMarker; -/// ``` -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] -pub struct StructType { - pub ident: Vec, - pub fields: Vec, -}