Commit fa6b0065 authored by Hero Bird's avatar Hero Bird Committed by GitHub

ink! ABI (#104)

* [abi] Create ink_abi sub crate

* [abi] Add initial types for abi generation

* [abi] Add EventParamSpec to include indexed event params

* [abi] Add documentation field to specs

* [abi] Add license and readme links and clean up authors

* [abi] Add missing license headers

* [abi] Fix some compile errors

* [abi] Make macros usable internally

* [abi] Create type_spec_of_tuple constructor macro

* [abi] Implement serialization for tuples

* [abi] Implement serialize for array types

* [abi] Remove module prefix of Vec<T>

* [abi] Apply rustfmt

* [abi] Improve minor formatting

* [abi] Add trait to allow external crate to specify serialize of TypeSpec<T>

* [abi] Make rustfmt happy

* [abi] Handle missing Vec in no_std environment

We really need a further abstraction to handle memory types.
Right now they life in ink_core but we shouldn't depend on ink_core from within ink_abi.
So we want to extract the memory sub module out of ink_core into its own crate that we can from then on depend on.

* [abi] Use same array pre-impls as metadata prototype impl

* [abi] Depend on cennznet/type-metadata + adjustments

* [abi] add missing license headers

* [abi] fixes for renamings in type-metadata crate

* [abi] add IntoCompact impls for layout types

* [abi] properly forward std feature

* [abi] implement Serialize for Key

* [abi] apply rustfmt and add some layout constructors

This also removes the dependency from ink_abi to ink_core and adds derive feature to type-metadata dependency.

* [core] implement ink_abi traits for ink_core abstractions

* adjust ink_abi Cargo.toml to using std feature by default

# Conflicts:
#	abi/Cargo.toml

* [core] Integrate ink_abi no_std compat into ink_core

* [lang] initial skeleton of codegen for ink_abi

* Enhance Flush (#136)

* [core] Enhance Flush trait to make it work with SyncCell and SyncChunk

* apply rustfmt

* [core] implement ink_abi traits for ink_core abstractions

* [core] Integrate ink_abi no_std compat into ink_core

* [core] Apply cargo fmt

* [cli] initial adjustments for ink_abi to ink! template

* [abi] clean-up of Cargo.toml

* [abi] remove invalid lib docs

* [utils] Update utilities docs

* [abi] improve JSON encoding of layout structs

* [abi] improve JSON encoding and add builder pattern constructors

* [abi] Add InkProject meta type

* [abi] temporarily depend on improve-json-output type-metadata branch

* [core] adjust type-metadata temporary branch to use the same as ink_abi

* [ci] add travis CI nightly-2019-08-01 channel (experimental)

* [abi] add MessageSpecBuilder::{args, docs} methods

* [core] implement Metadata for AccountId and Hash of DefaultSrmlTypes

* [abi] change type of selector from u64 to u32

* [lang] add some helper routines

* [lang] add code generation for new ABI format

* [abi,core] use master branch for type-metadata again

* [lang] implement initial code gen for ABI generation

* [examples] adjust Flipper contract example to ink_abi generation

* [lang] remove old generate-abi-description feature and associated code

* [examples] remove traces of removed generate-api-description feature

* [core] make cells_origin and chunks_origin only visible for test-env

* [cli] adjust template for ink-abi update

* [abi] implement ink_abi_derive for HasLayout derive macro

* [lang] make use of new ink_abi_derive functionality

* [examples] adjust Flipper for new ink_abi derive crate feature

This is needed because we disable default features.

* [abi] remove some commented-out code

* [chores] update README and include ink_abi docs

* [abi] apply rustfmt

* [lang] apply rustfmt

* [abi] apply rustfmt to non derive crate

* [core] apply rustfmt

* [lang] trim doc strings coming from syn::Attribute

* [examples] rename .tools directory to .ink

* [examples] fix bug with no_std and "std" crate feature

* [lang] fix bug in abi generation for events

* [examples] adjust events example to new ink_abi

* [lang] fix some more edge cases with doc string trimming

* [lang] fix a bug that path matching for function arguments was off

* [examples] adjust Incrementer to new ink_abi

* [cli] rename .tools to .ink in template

* [cli] update template Cargo.toml

* [examples] temporarily fix type-metadata hick-up

* [examples] make ink_abi optional

* [examples] adjust Erc20 token example to new ink_abi

* [cli] fix template no_std support

* [*] use master branch of type-metadata crate again

* [examples] replace parity-codec/std with scale/std

* [core] derive Metadata for some util types

This unfortunately was lost upon the latest rebase.

* [ci] update from nightly-2019-08-01/2019-07-19 to just nightly-2019-08-09

* [abi] remove commented-out code

* [abi] add some docs to specs items

* Update abi/src/specs.rs
Co-Authored-By: Andrew Jones's avatarAndrew Jones <ascjones@gmail.com>

* Update abi/src/specs.rs
Co-Authored-By: Andrew Jones's avatarAndrew Jones <ascjones@gmail.com>

* Update core/src/storage/collections/stash/impls.rs
Co-Authored-By: Andrew Jones's avatarAndrew Jones <ascjones@gmail.com>

* Update core/src/storage/collections/stash/impls.rs
Co-Authored-By: Andrew Jones's avatarAndrew Jones <ascjones@gmail.com>

* [examples] remove some more commented-out code

* [lang] remove outdated docs

* [lang] extract fn docs impl into helper method

* [lang] fix compile-error in `filter_doc_attributes`

* [core] use derive feature from ink_abi

* [examples] adjust shared_vec example for ink_abi

* [lang] trim doc comments raw string escape sequence

* [lang] adjust noop test for ink_abi

* [lang] adjust flipper test for ink_abi

* [lang] improve raw-string char sequence fix

* [lang] adjust incrementer test for ink_abi

* [lang] adjust events test for ink_abi

* [lang] fix whitespace (tabs) issues in lang tests

* [ci] add examples to CI

* [ci] remove +nightly attribute for examples

* [abi] remove instances of std usage

* [core] remove instances of std usage

* [examples] erc20: remove std usage in no_std environment

* [core] factor out ink_abi and type-metadata and guard their use with ink-generate-abi feature

* [examples] adjust examples to newest refactoring in ink_core

* [cli] adjust template to ink_core refactorings

* [scripts] add new script to quickly check all example smart contracts

* [ci] make use of new check-examples script

* [*] apply rustfmt

* [scripts] adjust check-examples to no longer set test-env

* [scripts] Add check-workspace script

* [examples] make test-env a default feature

* [cli] make test-env a default feature for the template

* [ci] update CI to use the new check-workspace script
parent 9525f2f5
......@@ -7,7 +7,7 @@ rust:
# - stable
# - beta
- nightly
- nightly-2019-07-19
- nightly-2019-08-09
matrix:
allow_failures:
......@@ -35,6 +35,7 @@ install:
# Print rustc and cargo versions
- rustc -vV
- cargo -vV
- bash --version
# Install cargo-kcov Cargo plugin
- cargo install --force cargo-kcov
- cargo kcov -vV
......@@ -61,92 +62,19 @@ before_script:
script:
- |
cargo check --verbose --all --all-features
check_all_features=$?
./scripts/check-workspace.sh
check_workspace=$?
cargo check --verbose --all --no-default-features
check_no_default=$?
./scripts/check-examples.sh
check_examples=$?
cargo fmt --verbose --all -- --check
fmt=$?
cargo clippy --verbose --all --all-features -- -D warnings
clippy_all_features=$?
cargo clippy --verbose --all --no-default-features -- -D warnings
clippy_no_default=$?
cargo test --verbose --all --all-features
test=$?
cargo kcov --verbose --coveralls --all --no-clean-rebuild
kcov=$?
bash <(curl -s https://codecov.io/bash)
cargo build --verbose --all --no-default-features --release --target=wasm32-unknown-unknown
build_wasm=$?
echo "CI Summary"
echo "=========="
echo ""
if [ $check_all_features -eq 0 ]
if [ $check_examples -eq 0 ] && [ $check_workspace -eq 0 ]
then
echo "compile (all-features): ok"
else
echo "compile (all-features): ERROR"
fi
# Execute and upload kcov results
cargo kcov --verbose --coveralls --all --no-clean-rebuild
kcov=$?
bash <(curl -s https://codecov.io/bash)
if [ $check_no_default -eq 0 ]
then
echo "compile (no-default-features): ok"
else
echo "compile (no-default-features): ERROR"
fi
if [ $fmt -eq 0 ]
then
echo "formatting: ok"
else
echo "formatting: ERROR"
fi
if [ $clippy_all_features -eq 0 ]
then
echo "clippy (all-features): ok"
else
echo "clippy (all-features): ERROR"
fi
if [ $clippy_no_default -eq 0 ]
then
echo "clippy (no-default-features): ok"
else
echo "clippy (no-default-features): ERROR"
fi
if [ $test -eq 0 ]
then
echo "test (all-features): ok"
else
echo "test (all-features): ERROR"
fi
if [ $build_wasm -eq 0 ]
then
echo "build Wasm: ok"
else
echo "build Wasm: ERROR"
fi
if [ $kcov -eq 0 ]
then
echo "coverage analysis: ok"
else
echo "coverage analysis: ERROR"
fi
if [ $check_all_features -eq 0 ] && [ $check_no_default -eq 0 ] && [ $fmt -eq 0 ] && [ $clippy_all_features -eq 0 ] && [ $clippy_no_default -eq 0 ] && [ $test -eq 0 ] && [ $build_wasm -eq 0 ]
then
echo "All checks have passed!"
exit 0
else
......
......@@ -6,9 +6,11 @@ members = [
"model",
"lang",
"cli",
"abi",
]
exclude = [
"examples/",
"cli/template/",
]
[profile.release]
......
# ink! - Parity's ink to write smart contracts
| Linux | Codecov | Coveralls | LoC | Docs (Core) | Docs (Model) |
|:------------------:|:--------------------:|:----------------------:|:----------------:|:-----------------:|:-----------------:|
| [![linux][A1]][A2] | [![codecov][C1]][C2] | [![coveralls][D1]][D2] | [![loc][E1]][E2] | [![docs][F1]][F2] | [![docs][G1]][G2] |
| Linux | Codecov | Coveralls | LoC |
|:------------------:|:--------------------:|:----------------------:|:----------------:|
| [![linux][A1]][A2] | [![codecov][C1]][C2] | [![coveralls][D1]][D2] | [![loc][E1]][E2] |
[A1]: https://travis-ci.org/paritytech/ink.svg?branch=master
[A2]: https://travis-ci.org/paritytech/ink
......@@ -16,19 +16,28 @@
[E1]: https://tokei.rs/b1/github/paritytech/ink?category=code
[E2]: https://github.com/Aaronepower/tokei#badges
[F1]: https://img.shields.io/badge/docs-nightly-black.svg
[F2]: https://paritytech.github.io/ink/ink_core/index.html
[F1]: https://img.shields.io/badge/docs-core-blue.svg
[F2]: https://paritytech.github.io/ink/ink_core
[G1]: https://img.shields.io/badge/docs-nightly-purple.svg
[G2]: https://paritytech.github.io/ink/ink_model/index.html
[G1]: https://img.shields.io/badge/docs-model-blue.svg
[G2]: https://paritytech.github.io/ink/ink_model
[H1]: https://img.shields.io/badge/docs-abi-blue.svg
[H2]: https://paritytech.github.io/ink/ink_abi
**IMPORTANT NOTE:** WORK IN PROGRESS! Do not expect this to be working.
ink is an [eDSL](https://wiki.haskell.org/Embedded_domain_specific_language) to write WebAssembly based smart contracts using the Rust programming language.
ink! is an [eDSL](https://wiki.haskell.org/Embedded_domain_specific_language) to write WebAssembly based smart contracts using the Rust programming language targeting Substrate blockchains.
## Developer Documentation
| `ink_abi` | `ink_core` | `ink_model` |
|-----------|------------|-------------|
| [![][H1]][H2] | [![][F1]][F2] | [![][G1]][G2] |
## Example
Below is an example using the eDSL demonstrating a simple Flipper smart contract
Below is an example using ink! demonstrating a simple Flipper smart contract
that has a boolean state that can be flipped or returned.
```rust
......
[package]
name = "ink_abi"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0"
readme = "README.md"
description = "Rust based eDSL for writing smart contracts for Substrate"
keywords = ["wasm", "parity", "webassembly", "blockchain", "edsl"]
categories = ["no-std", "embedded"]
include = ["/Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"]
[dependencies]
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
derive_more = { version = "0.14", features = ["no_std"] }
ink_abi_derive = { version = "0.1.0", path = "derive", default-features = false, optional = true }
type-metadata = { git = "https://github.com/type-metadata/type-metadata.git", default-features = false, features = ["derive"] }
[features]
default = [
"std",
"derive",
]
derive = [
"ink_abi_derive"
]
std = [
"ink_abi_derive/std",
"serde/std",
"type-metadata/std",
]
../LICENSE
\ No newline at end of file
../README.md
\ No newline at end of file
[package]
name = "ink_abi_derive"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "Apache-2.0"
readme = "../README.md"
[lib]
proc-macro = true
[dependencies]
quote = "0.6"
syn = { version = "0.15", features = ["full"] }
proc-macro2 = "0.4"
[features]
default = ["std"]
std = []
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
macro_rules! bail {
($($args:tt)*) => {
return Err(format_err!($($args)*).into())
}
}
macro_rules! format_err {
($tokens:expr, $($msg:tt)*) => {
match &$tokens {
t => {
syn::parse::Error::new_spanned(t, format_args!($($msg)*))
}
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::impl_wrapper::wrap;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{
self,
parse::Result,
parse_quote,
punctuated::Punctuated,
Data,
DataStruct,
DeriveInput,
Field,
Fields,
Token,
};
pub fn generate(input: TokenStream2) -> TokenStream2 {
match generate_impl(input.into()) {
Ok(output) => output.into(),
Err(err) => err.to_compile_error().into(),
}
}
pub fn generate_impl(input: TokenStream2) -> Result<TokenStream2> {
let mut ast: DeriveInput = syn::parse2(input)?;
ast.generics.type_params_mut().for_each(|p| {
p.bounds.push(parse_quote!(_ink_abi::HasLayout));
});
let ident = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let layout = match &ast.data {
Data::Struct(ref s) => generate_struct_layout(s),
Data::Enum(ref _e) => bail!(&ast, "enums are not supported"),
Data::Union(ref _u) => bail!(&ast, "unions are not supported"),
};
let has_layout_impl = quote! {
impl #impl_generics _ink_abi::HasLayout for #ident #ty_generics #where_clause {
fn layout(&self) -> _ink_abi::StorageLayout {
#layout.into()
}
}
};
Ok(wrap(ident, "HAS_LAYOUT", has_layout_impl).into())
}
fn generate_fields_layout<'a>(
fields: &'a Punctuated<Field, Token![,]>,
) -> impl Iterator<Item = TokenStream2> + 'a {
fields.iter().enumerate().map(|(n, field)| {
let ident = &field.ident;
if let Some(ident) = ident {
quote! {
_ink_abi::LayoutField::new(stringify!(#ident), self.#ident.layout())
}
} else {
quote! {
_ink_abi::LayoutField::new(stringify!(#n), self.#n.layout())
}
}
})
}
fn generate_struct_fields_layout(fields: &Punctuated<Field, Token![,]>) -> TokenStream2 {
let fields_layout = generate_fields_layout(fields);
quote! {
use type_metadata::Metadata as _;
_ink_abi::LayoutStruct::new(Self::meta_type(), __core::vec![
#( #fields_layout, )*
])
}
}
fn generate_struct_layout(data_struct: &DataStruct) -> TokenStream2 {
match data_struct.fields {
Fields::Named(ref fs) => generate_struct_fields_layout(&fs.named),
Fields::Unnamed(ref fs) => generate_struct_fields_layout(&fs.unnamed),
Fields::Unit => {
quote! {
use type_metadata::Metadata as _;
_ink_abi::LayoutStruct::new(Self::meta_type(), __core::vec![])
}
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
#[cfg(not(feature = "std"))]
use alloc::{
format,
string::{
String,
ToString,
},
};
use proc_macro2::{
Span,
TokenStream as TokenStream2,
};
use quote::quote;
use syn::Ident;
pub fn wrap(
ident: &Ident,
trait_name: &'static str,
impl_quote: TokenStream2,
) -> TokenStream2 {
let mut renamed = String::from(format!("_IMPL_{}_FOR_", trait_name));
renamed.push_str(ident.to_string().trim_start_matches("r#"));
let dummy_const = Ident::new(&renamed, Span::call_site());
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
use type_metadata as _type_metadata;
use ink_abi as _ink_abi;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
mod __core {
pub use ::core::*;
pub use ::std::{vec, vec::Vec};
}
#[cfg(not(feature = "std"))]
mod __core {
pub use ::core::*;
pub use ::alloc::{vec, vec::Vec};
}
#impl_quote;
};
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
extern crate proc_macro;
#[macro_use]
mod error;
mod has_layout;
mod impl_wrapper;
use proc_macro::TokenStream;
#[proc_macro_derive(HasLayout)]
pub fn has_layout(input: TokenStream) -> TokenStream {
has_layout::generate(input.into()).into()
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use derive_more::From;
use serde::Serialize;
use type_metadata::{
form::{
CompactForm,
Form,
MetaForm,
},
IntoCompact,
Registry,
};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
/// Implemented by types that have a storage layout.
///
/// Has to be used on previously allocated instances of the types.
pub trait HasLayout {
fn layout(&self) -> StorageLayout;
}
/// Either a concrete layout bound or another layout sub-struct.
#[derive(Debug, PartialEq, Eq, Serialize, From)]
#[serde(bound = "F::TypeId: Serialize")]
#[serde(untagged)]
pub enum StorageLayout<F: Form = MetaForm> {
/// A concrete layout bound.
Range(LayoutRange<F>),
/// A nested sub-struct with layout bounds.
Struct(LayoutStruct<F>),
}
impl IntoCompact for StorageLayout {
type Output = StorageLayout<CompactForm>;
fn into_compact(self, registry: &mut Registry) -> Self::Output {
match self {
StorageLayout::Range(layout_range) => {
StorageLayout::Range(layout_range.into_compact(registry))
}
StorageLayout::Struct(layout_struct) => {
StorageLayout::Struct(layout_struct.into_compact(registry))
}
}
}
}
/// A concrete range of keys.
///
/// Basically a thin-wrapper around keys from `ink_core` library for serialization purposes.
#[derive(Debug, PartialEq, Eq, From, Serialize)]
#[serde(transparent)]
pub struct LayoutKey(
/// Internals must be compatible with `ink_core::storage::Key`.
pub [u8; 32],
);
/// A struct storage layout.
#[derive(Debug, PartialEq, Eq, Serialize)]
#[serde(bound = "F::TypeId: Serialize")]
pub struct LayoutStruct<F: Form = MetaForm> {
#[serde(rename = "struct.type")]
self_ty: F::TypeId,
/// The sub-fields of the struct.
#[serde(rename = "struct.fields")]
fields: Vec<LayoutField<F>>,
}
impl LayoutStruct {
/// Creates a new layout struct.
pub fn new<F>(self_ty: <MetaForm as Form>::TypeId, fields: F) -> Self
where
F: IntoIterator<Item = LayoutField>,
{
Self {
self_ty,
fields: fields.into_iter().collect::<Vec<_>>(),
}
}
}
impl IntoCompact for LayoutStruct {
type Output = LayoutStruct<CompactForm>;
fn into_compact(self, registry: &mut Registry) -> Self::Output {
LayoutStruct {
self_ty: registry.register_type(&self.self_ty),
fields: self
.fields
.into_iter()
.map(|field| field.into_compact(registry))
.collect::<Vec<_>>(),
}
}
}
/// The layout for a particular field of a struct layout.
#[derive(Debug, PartialEq, Eq, Serialize)]
#[serde(bound = "F::TypeId: Serialize")]
pub struct LayoutField<F: Form = MetaForm> {
/// The name of the field.
name: F::String,
/// The kind of the field.
///
/// This is either a direct layout bound
/// or another recursive layout sub-struct.
#[serde(rename = "layout")]
sub_layout: StorageLayout<F>,
}
impl LayoutField {
/// Creates a new layout field from the given name and sub-structural layout.
pub fn new(name: <MetaForm as Form>::String, sub_layout: StorageLayout) -> Self {
Self { name, sub_layout }
}
/// Creates a new layout field for the given field instance.
pub fn of<T>(name: <MetaForm as Form>::String, field: &T) -> Self
where
T: HasLayout,
{
Self::new(name, field.layout())
}
}
impl IntoCompact for LayoutField {
type Output = LayoutField<CompactForm>;
fn into_compact(self, registry: &mut Registry) -> Self::Output {
LayoutField {
name: registry.register_string(self.name),
sub_layout: self.sub_layout.into_compact(registry),
}
}
}
/// Direct range of associated storage keys.
///
/// This may represent either a single cell, a whole chunk of cells or something in between.
#[derive(Debug, PartialEq, Eq, Serialize)]
#[serde(bound = "F::TypeId: Serialize")]
pub struct LayoutRange<F: Form = MetaForm> {
/// The single key for cells or the starting key address for chunks.
#[serde(rename = "range.offset")]
offset: LayoutKey,
/// The amount of associated key addresses starting from the offset key.
#[serde(rename = "range.len")]
len: u32,
/// The element type stored under the associated keys.
#[serde(rename = "range.elem_type")]
elem_ty: F::TypeId,
}
impl IntoCompact for LayoutRange {
type Output = LayoutRange<CompactForm>;
fn into_compact(self, registry: &mut Registry) -> Self::Output {
LayoutRange {
offset: self.offset,
len: self.len,
elem_ty: registry.register_type(&self.elem_ty),
}
}
}
impl LayoutRange {
/// Creates a layout range representing a single cell.
pub fn cell<K>(at: K, elem_ty: <MetaForm as Form>::TypeId) -> Self
where
K: Into<LayoutKey>,
{
Self {
offset: at.into(),
len: 1,
elem_ty,
}
}
/// Creates a layout range for a whole chunk starting at the offset key.
pub fn chunk<K>(offset: K, elem_ty: <MetaForm as Form>::TypeId) -> Self
where
K: Into<LayoutKey>,
{
Self {
offset: offset.into(),
len: 0xFFFF_FFFF,
elem_ty,
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
mod layout;
mod specs;