mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 15:41:02 +00:00
Remove unneeded code (#737)
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"codec",
|
||||
"codec/derive",
|
||||
"environmental",
|
||||
"core/bft",
|
||||
"core/cli",
|
||||
"core/client",
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[package]
|
||||
name = "parity-codec"
|
||||
description = "Serialization and deserialization codec for runtime values"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
arrayvec = { version = "0.4", default_features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
= Codec
|
||||
|
||||
.Summary
|
||||
[source, toml]
|
||||
----
|
||||
include::Cargo.toml[lines=2..5]
|
||||
----
|
||||
|
||||
.Description
|
||||
----
|
||||
include::src/lib.rs[tag=description]
|
||||
----
|
||||
@@ -1,20 +0,0 @@
|
||||
[package]
|
||||
name = "parity-codec-derive"
|
||||
description = "Serialization and deserialization derive macro"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "0.14"
|
||||
quote = "0.6"
|
||||
proc-macro2 = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
parity-codec = { path = "../" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
@@ -1,111 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::{Span, TokenStream, Ident};
|
||||
use syn::{
|
||||
Data, Fields,
|
||||
spanned::Spanned,
|
||||
};
|
||||
|
||||
pub fn quote(data: &Data, type_name: &Ident, input: &TokenStream) -> TokenStream {
|
||||
let call_site = Span::call_site();
|
||||
match *data {
|
||||
Data::Struct(ref data) => match data.fields {
|
||||
Fields::Named(_) | Fields::Unnamed(_) => create_instance(
|
||||
call_site,
|
||||
quote! { #type_name },
|
||||
input,
|
||||
&data.fields,
|
||||
),
|
||||
Fields::Unit => {
|
||||
quote_spanned! {call_site =>
|
||||
drop(#input);
|
||||
Some(#type_name)
|
||||
}
|
||||
},
|
||||
},
|
||||
Data::Enum(ref data) => {
|
||||
assert!(data.variants.len() < 256, "Currently only enums with at most 256 variants are encodable.");
|
||||
|
||||
let recurse = data.variants.iter().enumerate().map(|(i, v)| {
|
||||
let name = &v.ident;
|
||||
let index = super::index(v, i);
|
||||
|
||||
let create = create_instance(
|
||||
call_site,
|
||||
quote! { #type_name :: #name },
|
||||
input,
|
||||
&v.fields,
|
||||
);
|
||||
|
||||
quote_spanned! { v.span() =>
|
||||
x if x == #index as u8 => {
|
||||
#create
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match #input.read_byte()? {
|
||||
#( #recurse )*
|
||||
_ => None,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
Data::Union(_) => panic!("Union types are not supported."),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_instance(call_site: Span, name: TokenStream, input: &TokenStream, fields: &Fields) -> TokenStream {
|
||||
match *fields {
|
||||
Fields::Named(ref fields) => {
|
||||
let recurse = fields.named.iter().map(|f| {
|
||||
let name = &f.ident;
|
||||
let field = quote_spanned!(call_site => #name);
|
||||
|
||||
quote_spanned! { f.span() =>
|
||||
#field: ::codec::Decode::decode(#input)?
|
||||
}
|
||||
});
|
||||
|
||||
quote_spanned! {call_site =>
|
||||
Some(#name {
|
||||
#( #recurse, )*
|
||||
})
|
||||
}
|
||||
},
|
||||
Fields::Unnamed(ref fields) => {
|
||||
let recurse = fields.unnamed.iter().map(|f| {
|
||||
quote_spanned! { f.span() =>
|
||||
::codec::Decode::decode(#input)?
|
||||
}
|
||||
});
|
||||
|
||||
quote_spanned! {call_site =>
|
||||
Some(#name (
|
||||
#( #recurse, )*
|
||||
))
|
||||
}
|
||||
},
|
||||
Fields::Unit => {
|
||||
quote_spanned! {call_site =>
|
||||
Some(#name)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use core::str::from_utf8;
|
||||
#[cfg(feature = "std")]
|
||||
use std::str::from_utf8;
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use syn::{
|
||||
Data, Field, Fields, Ident, Index,
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
token::Comma,
|
||||
};
|
||||
|
||||
type FieldsList = Punctuated<Field, Comma>;
|
||||
|
||||
fn encode_fields<F>(
|
||||
dest: &TokenStream,
|
||||
fields: &FieldsList,
|
||||
field_name: F,
|
||||
) -> TokenStream where
|
||||
F: Fn(usize, &Option<Ident>) -> TokenStream,
|
||||
{
|
||||
let recurse = fields.iter().enumerate().map(|(i, f)| {
|
||||
let field = field_name(i, &f.ident);
|
||||
|
||||
quote_spanned! { f.span() =>
|
||||
#dest.push(#field);
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#( #recurse )*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quote(data: &Data, type_name: &Ident, self_: &TokenStream, dest: &TokenStream) -> TokenStream {
|
||||
let call_site = Span::call_site();
|
||||
match *data {
|
||||
Data::Struct(ref data) => match data.fields {
|
||||
Fields::Named(ref fields) => encode_fields(
|
||||
dest,
|
||||
&fields.named,
|
||||
|_, name| quote_spanned!(call_site => &#self_.#name),
|
||||
),
|
||||
Fields::Unnamed(ref fields) => encode_fields(
|
||||
dest,
|
||||
&fields.unnamed,
|
||||
|i, _| {
|
||||
let index = Index { index: i as u32, span: call_site };
|
||||
quote_spanned!(call_site => &#self_.#index)
|
||||
},
|
||||
),
|
||||
Fields::Unit => quote_spanned! { call_site =>
|
||||
drop(#dest);
|
||||
},
|
||||
},
|
||||
Data::Enum(ref data) => {
|
||||
assert!(data.variants.len() < 256, "Currently only enums with at most 256 variants are encodable.");
|
||||
|
||||
let recurse = data.variants.iter().enumerate().map(|(i, f)| {
|
||||
let name = &f.ident;
|
||||
let index = super::index(f, i);
|
||||
|
||||
match f.fields {
|
||||
Fields::Named(ref fields) => {
|
||||
let field_name = |_, ident: &Option<Ident>| quote_spanned!(call_site => #ident);
|
||||
let names = fields.named
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, f)| field_name(i, &f.ident));
|
||||
|
||||
let encode_fields = encode_fields(
|
||||
dest,
|
||||
&fields.named,
|
||||
|a, b| field_name(a, b),
|
||||
);
|
||||
|
||||
quote_spanned! { f.span() =>
|
||||
#type_name :: #name { #( ref #names, )* } => {
|
||||
#dest.push_byte(#index as u8);
|
||||
#encode_fields
|
||||
}
|
||||
}
|
||||
},
|
||||
Fields::Unnamed(ref fields) => {
|
||||
let field_name = |i, _: &Option<Ident>| {
|
||||
let data = stringify(i as u8);
|
||||
let ident = from_utf8(&data).expect("We never go beyond ASCII");
|
||||
let ident = Ident::new(ident, call_site);
|
||||
quote_spanned!(call_site => #ident)
|
||||
};
|
||||
let names = fields.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, f)| field_name(i, &f.ident));
|
||||
|
||||
let encode_fields = encode_fields(
|
||||
dest,
|
||||
&fields.unnamed,
|
||||
|a, b| field_name(a, b),
|
||||
);
|
||||
|
||||
quote_spanned! { f.span() =>
|
||||
#type_name :: #name ( #( ref #names, )* ) => {
|
||||
#dest.push_byte(#index as u8);
|
||||
#encode_fields
|
||||
}
|
||||
}
|
||||
},
|
||||
Fields::Unit => {
|
||||
quote_spanned! { f.span() =>
|
||||
#type_name :: #name => {
|
||||
#dest.push_byte(#index as u8);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match *#self_ {
|
||||
#( #recurse )*,
|
||||
}
|
||||
}
|
||||
},
|
||||
Data::Union(_) => panic!("Union types are not supported."),
|
||||
}
|
||||
}
|
||||
pub fn stringify(id: u8) -> [u8; 2] {
|
||||
const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
|
||||
let len = CHARS.len() as u8;
|
||||
let symbol = |id: u8| CHARS[(id % len) as usize];
|
||||
let a = symbol(id);
|
||||
let b = symbol(id / len);
|
||||
|
||||
[a, b]
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Derives serialization and deserialization codec for complex structs for simple marshalling.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{DeriveInput, Generics, GenericParam, Ident};
|
||||
|
||||
mod decode;
|
||||
mod encode;
|
||||
|
||||
const ENCODE_ERR: &str = "derive(Encode) failed";
|
||||
|
||||
#[proc_macro_derive(Encode, attributes(codec))]
|
||||
pub fn encode_derive(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = syn::parse(input).expect(ENCODE_ERR);
|
||||
let name = &input.ident;
|
||||
|
||||
let generics = add_trait_bounds(input.generics, parse_quote!(::codec::Encode));
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
let self_ = quote!(self);
|
||||
let dest_ = quote!(dest);
|
||||
let encoding = encode::quote(&input.data, name, &self_, &dest_);
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics ::codec::Encode for #name #ty_generics #where_clause {
|
||||
fn encode_to<EncOut: ::codec::Output>(&#self_, #dest_: &mut EncOut) {
|
||||
#encoding
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expanded.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Decode, attributes(codec))]
|
||||
pub fn decode_derive(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = syn::parse(input).expect(ENCODE_ERR);
|
||||
let name = &input.ident;
|
||||
|
||||
let generics = add_trait_bounds(input.generics, parse_quote!(::codec::Decode));
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
let input_ = quote!(input);
|
||||
let decoding = decode::quote(&input.data, name, &input_);
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics ::codec::Decode for #name #ty_generics #where_clause {
|
||||
fn decode<DecIn: ::codec::Input>(#input_: &mut DecIn) -> Option<Self> {
|
||||
#decoding
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expanded.into()
|
||||
}
|
||||
|
||||
fn add_trait_bounds(mut generics: Generics, bounds: syn::TypeParamBound) -> Generics {
|
||||
for param in &mut generics.params {
|
||||
if let GenericParam::Type(ref mut type_param) = *param {
|
||||
type_param.bounds.push(bounds.clone());
|
||||
}
|
||||
}
|
||||
generics
|
||||
}
|
||||
|
||||
fn index(v: &syn::Variant, i: usize) -> proc_macro2::TokenStream {
|
||||
// look for an index in attributes
|
||||
let index = v.attrs.iter().filter_map(|attr| {
|
||||
let pair = attr.path.segments.first()?;
|
||||
let seg = pair.value();
|
||||
|
||||
if seg.ident == Ident::new("codec", seg.ident.span()) {
|
||||
assert_eq!(attr.path.segments.len(), 1);
|
||||
|
||||
let meta = attr.interpret_meta();
|
||||
if let Some(syn::Meta::List(ref l)) = meta {
|
||||
if let syn::NestedMeta::Meta(syn::Meta::NameValue(ref nv)) = l.nested.last().unwrap().value() {
|
||||
assert_eq!(nv.ident, Ident::new("index", nv.ident.span()));
|
||||
if let syn::Lit::Str(ref s) = nv.lit {
|
||||
let byte: u8 = s.value().parse().expect("Numeric index expected.");
|
||||
return Some(byte)
|
||||
}
|
||||
panic!("Invalid syntax for `codec` attribute: Expected string literal.")
|
||||
}
|
||||
}
|
||||
panic!("Invalid syntax for `codec` attribute: Expected `name = value` pair.")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).next();
|
||||
|
||||
// then fallback to discriminant or just index
|
||||
index.map(|i| quote! { #i })
|
||||
.unwrap_or_else(|| v.discriminant
|
||||
.as_ref()
|
||||
.map(|&(_, ref expr)| quote! { #expr })
|
||||
.unwrap_or_else(|| quote! { #i })
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate parity_codec as codec;
|
||||
|
||||
#[macro_use]
|
||||
extern crate parity_codec_derive;
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
#[derive(Debug, PartialEq, Encode, Decode)]
|
||||
struct Unit;
|
||||
|
||||
#[derive(Debug, PartialEq, Encode, Decode)]
|
||||
struct Indexed(u32, u64);
|
||||
|
||||
#[derive(Debug, PartialEq, Encode, Decode)]
|
||||
struct Struct<A, B, C> {
|
||||
pub a: A,
|
||||
pub b: B,
|
||||
pub c: C,
|
||||
}
|
||||
|
||||
type TestType = Struct<u32, u64, Vec<u8>>;
|
||||
|
||||
impl <A, B, C> Struct<A, B, C> {
|
||||
fn new(a: A, b: B, c: C) -> Self {
|
||||
Self { a, b, c }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Encode, Decode)]
|
||||
enum EnumType {
|
||||
#[codec(index = "15")]
|
||||
A,
|
||||
B(u32, u64),
|
||||
C {
|
||||
a: u32,
|
||||
b: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Encode, Decode)]
|
||||
enum EnumWithDiscriminant {
|
||||
A = 1,
|
||||
B = 15,
|
||||
C = 255,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_work_for_simple_enum() {
|
||||
let a = EnumType::A;
|
||||
let b = EnumType::B(1, 2);
|
||||
let c = EnumType::C { a: 1, b: 2 };
|
||||
|
||||
a.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &b"\x0f");
|
||||
});
|
||||
b.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0");
|
||||
});
|
||||
c.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0");
|
||||
});
|
||||
|
||||
let mut da: &[u8] = b"\x0f";
|
||||
assert_eq!(EnumType::decode(&mut da), Some(a));
|
||||
let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0";
|
||||
assert_eq!(EnumType::decode(&mut db), Some(b));
|
||||
let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0";
|
||||
assert_eq!(EnumType::decode(&mut dc), Some(c));
|
||||
let mut dz: &[u8] = &[0];
|
||||
assert_eq!(EnumType::decode(&mut dz), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_work_for_enum_with_discriminant() {
|
||||
EnumWithDiscriminant::A.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &[1]);
|
||||
});
|
||||
EnumWithDiscriminant::B.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &[15]);
|
||||
});
|
||||
EnumWithDiscriminant::C.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &[255]);
|
||||
});
|
||||
|
||||
let mut da: &[u8] = &[1];
|
||||
assert_eq!(EnumWithDiscriminant::decode(&mut da), Some(EnumWithDiscriminant::A));
|
||||
let mut db: &[u8] = &[15];
|
||||
assert_eq!(EnumWithDiscriminant::decode(&mut db), Some(EnumWithDiscriminant::B));
|
||||
let mut dc: &[u8] = &[255];
|
||||
assert_eq!(EnumWithDiscriminant::decode(&mut dc), Some(EnumWithDiscriminant::C));
|
||||
let mut dz: &[u8] = &[2];
|
||||
assert_eq!(EnumWithDiscriminant::decode(&mut dz), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_derive_encode() {
|
||||
let v = TestType::new(15, 9, b"Hello world".to_vec());
|
||||
|
||||
v.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &b"\x0f\0\0\0\x09\0\0\0\0\0\0\0\x0b\0\0\0Hello world")
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_derive_decode() {
|
||||
let slice = b"\x0f\0\0\0\x09\0\0\0\0\0\0\0\x0b\0\0\0Hello world".to_vec();
|
||||
|
||||
let v = TestType::decode(&mut &*slice);
|
||||
|
||||
assert_eq!(v, Some(TestType::new(15, 9, b"Hello world".to_vec())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_work_for_unit() {
|
||||
let v = Unit;
|
||||
|
||||
v.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &[]);
|
||||
});
|
||||
|
||||
let mut a: &[u8] = &[];
|
||||
assert_eq!(Unit::decode(&mut a), Some(Unit));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_work_for_indexed() {
|
||||
let v = Indexed(1, 2);
|
||||
|
||||
v.using_encoded(|ref slice| {
|
||||
assert_eq!(slice, &b"\x01\0\0\0\x02\0\0\0\0\0\0\0")
|
||||
});
|
||||
|
||||
let mut v: &[u8] = b"\x01\0\0\0\x02\0\0\0\0\0\0\0";
|
||||
assert_eq!(Indexed::decode(&mut v), Some(Indexed(1, 2)));
|
||||
}
|
||||
@@ -1,540 +0,0 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Serialisation.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use alloc::boxed::Box;
|
||||
use core::{mem, slice};
|
||||
use arrayvec::ArrayVec;
|
||||
|
||||
/// Trait that allows reading of data into a slice.
|
||||
pub trait Input {
|
||||
/// Read into the provided input slice. Returns the number of bytes read.
|
||||
fn read(&mut self, into: &mut [u8]) -> usize;
|
||||
|
||||
/// Read a single byte from the input.
|
||||
fn read_byte(&mut self) -> Option<u8> {
|
||||
let mut buf = [0u8];
|
||||
match self.read(&mut buf[..]) {
|
||||
0 => None,
|
||||
1 => Some(buf[0]),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<'a> Input for &'a [u8] {
|
||||
fn read(&mut self, into: &mut [u8]) -> usize {
|
||||
let len = ::core::cmp::min(into.len(), self.len());
|
||||
into[..len].copy_from_slice(&self[..len]);
|
||||
*self = &self[len..];
|
||||
len
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<R: ::std::io::Read> Input for R {
|
||||
fn read(&mut self, into: &mut [u8]) -> usize {
|
||||
match (self as &mut ::std::io::Read).read_exact(into) {
|
||||
Ok(()) => into.len(),
|
||||
Err(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that allows writing of data.
|
||||
pub trait Output: Sized {
|
||||
/// Write to the output.
|
||||
fn write(&mut self, bytes: &[u8]);
|
||||
|
||||
fn push_byte(&mut self, byte: u8) {
|
||||
self.write(&[byte]);
|
||||
}
|
||||
|
||||
fn push<V: Encode + ?Sized>(&mut self, value: &V) {
|
||||
value.encode_to(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl Output for Vec<u8> {
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
self.extend(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<W: ::std::io::Write> Output for W {
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
(self as &mut ::std::io::Write).write_all(bytes).expect("Codec outputs are infallible");
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that allows zero-copy write of value-references to slices in LE format.
|
||||
/// Implementations should override `using_encoded` for value types and `encode_to` for allocating types.
|
||||
pub trait Encode {
|
||||
/// Convert self to a slice and append it to the destination.
|
||||
fn encode_to<T: Output>(&self, dest: &mut T) {
|
||||
self.using_encoded(|buf| dest.write(buf));
|
||||
}
|
||||
|
||||
/// Convert self to an owned vector.
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut r = Vec::new();
|
||||
self.encode_to(&mut r);
|
||||
r
|
||||
}
|
||||
|
||||
/// Convert self to a slice and then invoke the given closure with it.
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
f(&self.encode())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that allows zero-copy read of value-references from slices in LE format.
|
||||
pub trait Decode: Sized {
|
||||
/// Attempt to deserialise the value from input.
|
||||
fn decode<I: Input>(value: &mut I) -> Option<Self>;
|
||||
}
|
||||
|
||||
/// Trait that allows zero-copy read/write of value-references to/from slices in LE format.
|
||||
pub trait Codec: Decode + Encode {}
|
||||
|
||||
impl<S: Decode + Encode> Codec for S {}
|
||||
|
||||
impl<T: Encode, E: Encode> Encode for Result<T, E> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
match *self {
|
||||
Ok(ref t) => {
|
||||
dest.push_byte(0);
|
||||
t.encode_to(dest);
|
||||
}
|
||||
Err(ref e) => {
|
||||
dest.push_byte(1);
|
||||
e.encode_to(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode, E: Decode> Decode for Result<T, E> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
match input.read_byte()? {
|
||||
0 => Some(Ok(T::decode(input)?)),
|
||||
1 => Some(Err(E::decode(input)?)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shim type because we can't do a specialised implementation for `Option<bool>` directly.
|
||||
pub struct OptionBool(pub Option<bool>);
|
||||
|
||||
impl Encode for OptionBool {
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
f(&[match *self {
|
||||
OptionBool(None) => 0u8,
|
||||
OptionBool(Some(true)) => 1u8,
|
||||
OptionBool(Some(false)) => 2u8,
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for OptionBool {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
match input.read_byte()? {
|
||||
0 => Some(OptionBool(None)),
|
||||
1 => Some(OptionBool(Some(true))),
|
||||
2 => Some(OptionBool(Some(false))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode> Encode for Option<T> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
match *self {
|
||||
Some(ref t) => {
|
||||
dest.push_byte(1);
|
||||
t.encode_to(dest);
|
||||
}
|
||||
None => dest.push_byte(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for Option<T> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
match input.read_byte()? {
|
||||
0 => Some(None),
|
||||
1 => Some(Some(T::decode(input)?)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_array {
|
||||
( $( $n:expr )* ) => { $(
|
||||
impl<T: Encode> Encode for [T; $n] {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
for item in self.iter() {
|
||||
item.encode_to(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for [T; $n] {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let mut r = ArrayVec::new();
|
||||
for _ in 0..$n {
|
||||
r.push(T::decode(input)?);
|
||||
}
|
||||
r.into_inner().ok()
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
impl_array!(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
||||
40 48 56 64 72 96 128 160 192 224 256);
|
||||
|
||||
impl<T: Encode> Encode for Box<T> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_ref().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for Box<T> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Box::new(T::decode(input)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for [u8] {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
let len = self.len();
|
||||
assert!(len <= u32::max_value() as usize, "Attempted to serialize a collection with too many elements.");
|
||||
(len as u32).encode_to(dest);
|
||||
dest.write(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for Vec<u8> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_slice().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for Vec<u8> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
u32::decode(input).and_then(move |len| {
|
||||
let len = len as usize;
|
||||
let mut vec = vec![0; len];
|
||||
if input.read(&mut vec[..len]) != len {
|
||||
None
|
||||
} else {
|
||||
Some(vec)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encode for &'a str {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_bytes().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'a > Encode for ::std::borrow::Cow<'a, str> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_bytes().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'a> Decode for ::std::borrow::Cow<'a, str> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(::std::borrow::Cow::Owned(String::from_utf8_lossy(&Vec::decode(input)?).into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Encode for String {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_bytes().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Decode for String {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Self::from_utf8_lossy(&Vec::decode(input)?).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode> Encode for [T] {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
let len = self.len();
|
||||
assert!(len <= u32::max_value() as usize, "Attempted to serialize a collection with too many elements.");
|
||||
(len as u32).encode_to(dest);
|
||||
for item in self {
|
||||
item.encode_to(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode> Encode for Vec<T> {
|
||||
fn encode_to<W: Output>(&self, dest: &mut W) {
|
||||
self.as_slice().encode_to(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for Vec<T> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
u32::decode(input).and_then(move |len| {
|
||||
let mut r = Vec::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
r.push(T::decode(input)?);
|
||||
}
|
||||
Some(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for () {
|
||||
fn encode_to<T: Output>(&self, _dest: &mut T) {
|
||||
}
|
||||
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
f(&[])
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Encode + ?Sized> Encode for &'a T {
|
||||
fn encode_to<D: Output>(&self, dest: &mut D) {
|
||||
(&**self).encode_to(dest)
|
||||
}
|
||||
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
(&**self).using_encoded(f)
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
(&**self).encode()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for () {
|
||||
fn decode<I: Input>(_: &mut I) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple_impl {
|
||||
($one:ident,) => {
|
||||
impl<$one: Encode> Encode for ($one,) {
|
||||
fn encode_to<T: Output>(&self, dest: &mut T) {
|
||||
self.0.encode_to(dest);
|
||||
}
|
||||
}
|
||||
|
||||
impl<$one: Decode> Decode for ($one,) {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
match $one::decode(input) {
|
||||
None => None,
|
||||
Some($one) => Some(($one,)),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
($first:ident, $($rest:ident,)+) => {
|
||||
impl<$first: Encode, $($rest: Encode),+>
|
||||
Encode for
|
||||
($first, $($rest),+) {
|
||||
fn encode_to<T: Output>(&self, dest: &mut T) {
|
||||
let (
|
||||
ref $first,
|
||||
$(ref $rest),+
|
||||
) = *self;
|
||||
|
||||
$first.encode_to(dest);
|
||||
$($rest.encode_to(dest);)+
|
||||
}
|
||||
}
|
||||
|
||||
impl<$first: Decode, $($rest: Decode),+>
|
||||
Decode for
|
||||
($first, $($rest),+) {
|
||||
fn decode<INPUT: Input>(input: &mut INPUT) -> Option<Self> {
|
||||
Some((
|
||||
match $first::decode(input) {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
},
|
||||
$(match $rest::decode(input) {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
},)+
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
tuple_impl!($($rest,)+);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
mod inner_tuple_impl {
|
||||
use super::{Input, Output, Decode, Encode};
|
||||
tuple_impl!(A, B, C, D, E, F, G, H, I, J, K,);
|
||||
}
|
||||
|
||||
/// Trait to allow conversion to a know endian representation when sensitive.
|
||||
/// Types implementing this trait must have a size > 0.
|
||||
// note: the copy bound and static lifetimes are necessary for safety of `Codec` blanket
|
||||
// implementation.
|
||||
trait EndianSensitive: Copy + 'static {
|
||||
fn to_le(self) -> Self { self }
|
||||
fn to_be(self) -> Self { self }
|
||||
fn from_le(self) -> Self { self }
|
||||
fn from_be(self) -> Self { self }
|
||||
fn as_be_then<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T { f(&self) }
|
||||
fn as_le_then<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T { f(&self) }
|
||||
}
|
||||
|
||||
macro_rules! impl_endians {
|
||||
( $( $t:ty ),* ) => { $(
|
||||
impl EndianSensitive for $t {
|
||||
fn to_le(self) -> Self { <$t>::to_le(self) }
|
||||
fn to_be(self) -> Self { <$t>::to_be(self) }
|
||||
fn from_le(self) -> Self { <$t>::from_le(self) }
|
||||
fn from_be(self) -> Self { <$t>::from_be(self) }
|
||||
fn as_be_then<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T { let d = self.to_be(); f(&d) }
|
||||
fn as_le_then<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T { let d = self.to_le(); f(&d) }
|
||||
}
|
||||
|
||||
impl Encode for $t {
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.as_le_then(|le| {
|
||||
let size = mem::size_of::<$t>();
|
||||
let value_slice = unsafe {
|
||||
let ptr = le as *const _ as *const u8;
|
||||
if size != 0 {
|
||||
slice::from_raw_parts(ptr, size)
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
};
|
||||
|
||||
f(value_slice)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for $t {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let size = mem::size_of::<$t>();
|
||||
assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type.");
|
||||
let mut val: $t = unsafe { mem::zeroed() };
|
||||
|
||||
unsafe {
|
||||
let raw: &mut [u8] = slice::from_raw_parts_mut(
|
||||
&mut val as *mut $t as *mut u8,
|
||||
size
|
||||
);
|
||||
if input.read(raw) != size { return None }
|
||||
}
|
||||
Some(val.from_le())
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
macro_rules! impl_non_endians {
|
||||
( $( $t:ty ),* ) => { $(
|
||||
impl EndianSensitive for $t {}
|
||||
|
||||
impl Encode for $t {
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.as_le_then(|le| {
|
||||
let size = mem::size_of::<$t>();
|
||||
let value_slice = unsafe {
|
||||
let ptr = le as *const _ as *const u8;
|
||||
if size != 0 {
|
||||
slice::from_raw_parts(ptr, size)
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
};
|
||||
|
||||
f(value_slice)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for $t {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let size = mem::size_of::<$t>();
|
||||
assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type.");
|
||||
let mut val: $t = unsafe { mem::zeroed() };
|
||||
|
||||
unsafe {
|
||||
let raw: &mut [u8] = slice::from_raw_parts_mut(
|
||||
&mut val as *mut $t as *mut u8,
|
||||
size
|
||||
);
|
||||
if input.read(raw) != size { return None }
|
||||
}
|
||||
Some(val.from_le())
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
impl_endians!(u16, u32, u64, u128, usize, i16, i32, i64, i128, isize);
|
||||
impl_non_endians!(i8, [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8],
|
||||
[u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40],
|
||||
[u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128], bool);
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn vec_is_slicable() {
|
||||
let v = b"Hello world".to_vec();
|
||||
v.using_encoded(|ref slice|
|
||||
assert_eq!(slice, &b"\x0b\0\0\0Hello world")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_borrowed_tuple() {
|
||||
let x = vec![1u8, 2, 3, 4];
|
||||
let y = 128i64;
|
||||
|
||||
let encoded = (&x, &y).encode();
|
||||
|
||||
assert_eq!((x, y), Decode::decode(&mut &encoded[..]).unwrap());
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Trait
|
||||
|
||||
use core::iter::Extend;
|
||||
use super::Codec;
|
||||
|
||||
/// Trait to allow itself to be serialised into a value which can be extended
|
||||
/// by bytes.
|
||||
pub trait Joiner {
|
||||
fn and<V: Codec + Sized>(self, value: &V) -> Self;
|
||||
}
|
||||
|
||||
impl<T> Joiner for T where T: for<'a> Extend<&'a u8> {
|
||||
fn and<V: Codec + Sized>(mut self, value: &V) -> Self {
|
||||
value.using_encoded(|s| self.extend(s));
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Serialiser and prepender.
|
||||
|
||||
use Codec;
|
||||
use core::iter::Extend;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// Trait to allow itself to be serialised and prepended by a given slice.
|
||||
pub trait KeyedVec {
|
||||
fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl<T: Codec> KeyedVec for T {
|
||||
fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec<u8> {
|
||||
self.using_encoded(|slice| {
|
||||
let mut r = prepend_key.to_vec();
|
||||
r.extend(slice);
|
||||
r
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// tag::description[]
|
||||
//! Implements a serialization and deserialization codec for simple marshalling.
|
||||
// end::description[]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
extern crate arrayvec;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod alloc {
|
||||
pub use std::boxed;
|
||||
pub use std::vec;
|
||||
}
|
||||
|
||||
mod codec;
|
||||
mod joiner;
|
||||
mod keyedvec;
|
||||
|
||||
pub use self::codec::{Input, Output, Encode, Decode, Codec};
|
||||
pub use self::joiner::Joiner;
|
||||
pub use self::keyedvec::KeyedVec;
|
||||
@@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
futures = "0.1.17"
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
sr-primitives = { path = "../sr-primitives" }
|
||||
sr-version = { path = "../sr-version" }
|
||||
|
||||
@@ -14,7 +14,7 @@ futures = "0.1.17"
|
||||
slog = "^2"
|
||||
heapsize = "0.4"
|
||||
substrate-bft = { path = "../bft" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
sr-io = { path = "../sr-io" }
|
||||
|
||||
@@ -14,8 +14,8 @@ substrate-primitives = { path = "../../../core/primitives" }
|
||||
sr-primitives = { path = "../../../core/sr-primitives" }
|
||||
substrate-client = { path = "../../../core/client" }
|
||||
substrate-state-machine = { path = "../../../core/state-machine" }
|
||||
parity-codec = { path = "../../../codec" }
|
||||
parity-codec-derive = { path = "../../../codec/derive" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
substrate-executor = { path = "../../../core/executor" }
|
||||
substrate-state-db = { path = "../../../core/state-db" }
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.12"
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
sr-io = { path = "../sr-io" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
substrate-serializer = { path = "../serializer" }
|
||||
|
||||
Generated
+10
-6
@@ -33,14 +33,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "parity-codec"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-codec-derive"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -116,7 +118,7 @@ name = "sr-io"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hashdb 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec 0.1.0",
|
||||
"parity-codec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-std 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -126,7 +128,7 @@ dependencies = [
|
||||
name = "sr-sandbox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"parity-codec 0.1.0",
|
||||
"parity-codec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 0.1.0",
|
||||
"sr-std 0.1.0",
|
||||
@@ -148,8 +150,8 @@ dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashdb 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec 0.1.0",
|
||||
"parity-codec-derive 0.1.0",
|
||||
"parity-codec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec-derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -189,6 +191,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de"
|
||||
"checksum hashdb 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f1c71fc577cde89b3345d5f2880fecaf462a32e96c619f431279bdaf1ba5ddb1"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum parity-codec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9260216bbb7acdbb72dfb6bcb63245ef5bde9a8fb7706fe641e1caf1e7ae460f"
|
||||
"checksum parity-codec-derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eda64d782c342261aea4ca047a609f9bd92d5f9dafabe6b5a396caf5c7b8827"
|
||||
"checksum plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95fa6386b1d34aaf0adb9b7dd2885dbe7c34190e6263785e5a7ec2b19044a90f"
|
||||
"checksum proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "cccdc7557a98fe98453030f077df7f3a042052fae465bb61d2c2c41435cfd9b6"
|
||||
"checksum quote 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3372dc35766b36a99ce2352bd1b6ea0137c38d215cc0c8780bf6de6df7842ba9"
|
||||
|
||||
@@ -16,4 +16,4 @@ sr-primitives = { path = "../../core/sr-primitives" }
|
||||
[dev-dependencies]
|
||||
substrate-test-client = { path = "../../core/test-client" }
|
||||
substrate-keyring = { path = "../../core/keyring" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { path = "../../codec", default-features = false }
|
||||
parity-codec = { version = "~1.0", default-features = false }
|
||||
substrate-primitives = { path = "../primitives", default-features = false }
|
||||
sr-primitives = { path = "../sr-primitives", default-features = false }
|
||||
sr-io = { path = "../sr-io", default-features = false }
|
||||
|
||||
@@ -18,8 +18,8 @@ rustc-hex = "1.0"
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
substrate-client = { path = "../../core/client" }
|
||||
sr-primitives = { path = "../../core/sr-primitives" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec-derive = { path = "../../codec/derive" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
substrate-network-libp2p = { path = "../../core/network-libp2p" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -6,8 +6,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
crunchy = "0.1"
|
||||
sr-std = { path = "../sr-std", default_features = false }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
elastic-array = {version = "0.10", optional = true }
|
||||
fixed-hash = { version = "0.2.2", default_features = false }
|
||||
rustc-hex = { version = "2.0", default_features = false }
|
||||
|
||||
@@ -10,7 +10,7 @@ jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" }
|
||||
jsonrpc-pubsub = { git="https://github.com/paritytech/jsonrpc.git" }
|
||||
log = "0.3"
|
||||
parking_lot = "0.4"
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-client = { path = "../client" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
substrate-extrinsic-pool = { path = "../extrinsic-pool" }
|
||||
|
||||
@@ -23,7 +23,7 @@ substrate-primitives = { path = "../../core/primitives" }
|
||||
substrate-network = { path = "../../core/network" }
|
||||
substrate-client = { path = "../../core/client" }
|
||||
substrate-client-db = { path = "../../core/client/db" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-executor = { path = "../../core/executor" }
|
||||
substrate-extrinsic-pool = { path = "../../core/extrinsic-pool" }
|
||||
substrate-rpc = { path = "../../core/rpc" }
|
||||
|
||||
@@ -9,10 +9,10 @@ rustc_version = "0.2"
|
||||
|
||||
[dependencies]
|
||||
sr-std = { path = "../sr-std", default_features = false }
|
||||
environmental = { path = "../../environmental", optional = true }
|
||||
environmental = { version = "~1.0", optional = true }
|
||||
substrate-state-machine = { path = "../state-machine", optional = true }
|
||||
substrate-primitives = { path = "../primitives", default_features = false }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
triehash = { version = "0.2", optional = true }
|
||||
hashdb = { version = "0.2", default_features = false }
|
||||
rlp = { version = "0.2", optional = true, default_features = false }
|
||||
|
||||
@@ -8,8 +8,8 @@ num-traits = { version = "0.2", default_features = false }
|
||||
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../primitives", default_features = false }
|
||||
sr-std = { path = "../sr-std", default_features = false }
|
||||
sr-io = { path = "../sr-io", default_features = false }
|
||||
|
||||
@@ -12,7 +12,7 @@ wasmi = { version = "0.4", optional = true }
|
||||
substrate-primitives = { path = "../primitives", default_features = false }
|
||||
sr-std = { path = "../sr-std", default_features = false }
|
||||
sr-io = { path = "../sr-io", default_features = false }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
wabt = "0.4"
|
||||
|
||||
@@ -6,8 +6,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
sr-std = { path = "../sr-std", default_features = false }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -7,8 +7,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
parking_lot = "0.5"
|
||||
log = "0.4"
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec-derive = { path = "../../codec/derive" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.4"
|
||||
|
||||
@@ -17,5 +17,5 @@ triehash = "0.2"
|
||||
rlp = "0.2.4"
|
||||
|
||||
substrate-primitives = { path = "../primitives", version = "0.1.0" }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
rhododendron = "0.3"
|
||||
substrate-bft = { path = "../bft" }
|
||||
substrate-client = { path = "../client" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
substrate-keyring = { path = "../../core/keyring" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
|
||||
@@ -8,8 +8,8 @@ log = { version = "0.3", optional = true }
|
||||
hex-literal = { version = "0.1.0", optional = true }
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default-features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default-features = false }
|
||||
parity-codec = { version = "~1.0", default-features = false }
|
||||
parity-codec-derive = { version = "~1.0", default-features = false }
|
||||
substrate-keyring = { path = "../keyring", optional = true }
|
||||
substrate-primitives = { path = "../primitives", default-features = false }
|
||||
sr-std = { path = "../sr-std", default-features = false }
|
||||
|
||||
@@ -6,8 +6,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
log = { version = "0.3", optional = true }
|
||||
hex-literal = { version = "0.1.0", optional = true }
|
||||
parity-codec = { path = "../../../codec", default-features = false }
|
||||
parity-codec-derive = { path = "../../../codec/derive", default-features = false }
|
||||
parity-codec = { version = "~1.0", default-features = false }
|
||||
parity-codec-derive = { version = "~1.0", default-features = false }
|
||||
substrate-primitives = { path = "../../primitives", default-features = false }
|
||||
sr-std = { path = "../../sr-std", default-features = false }
|
||||
sr-io = { path = "../../sr-io", default-features = false }
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "environmental"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
= Environmental
|
||||
|
||||
.Summary
|
||||
[source, toml]
|
||||
----
|
||||
include::Cargo.toml[lines=2..5]
|
||||
----
|
||||
|
||||
.Description
|
||||
----
|
||||
include::src/lib.rs[tag=description]
|
||||
----
|
||||
@@ -1,383 +0,0 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// tag::description[]
|
||||
//! Safe global references to stack variables.
|
||||
//!
|
||||
//! Set up a global reference with environmental! macro giving it a name and type.
|
||||
//! Use the `using` function scoped under its name to name a reference and call a function that
|
||||
//! takes no parameters yet can access said reference through the similarly placed `with` function.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! #[macro_use] extern crate environmental;
|
||||
//! // create a place for the global reference to exist.
|
||||
//! environmental!(counter: u32);
|
||||
//! fn stuff() {
|
||||
//! // do some stuff, accessing the named reference as desired.
|
||||
//! counter::with(|i| *i += 1);
|
||||
//! }
|
||||
//! fn main() {
|
||||
//! // declare a stack variable of the same type as our global declaration.
|
||||
//! let mut counter_value = 41u32;
|
||||
//! // call stuff, setting up our `counter` environment as a reference to our counter_value var.
|
||||
//! counter::using(&mut counter_value, stuff);
|
||||
//! println!("The answer is {:?}", counter_value); // will print 42!
|
||||
//! stuff(); // safe! doesn't do anything.
|
||||
//! }
|
||||
//! ```
|
||||
// end::description[]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(const_fn))]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
include!("../with_std.rs");
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
include!("../without_std.rs");
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn using<T: ?Sized, R, F: FnOnce() -> R>(
|
||||
global: &'static imp::LocalKey<imp::RefCell<Option<*mut T>>>,
|
||||
protected: &mut T,
|
||||
f: F
|
||||
) -> R {
|
||||
// store the `protected` reference as a pointer so we can provide it to logic running within
|
||||
// `f`.
|
||||
// while we record this pointer (while it's non-zero) we guarantee:
|
||||
// - it will only be used once at any time (no reentrancy);
|
||||
// - that no other thread will use it; and
|
||||
// - that we do not use the original mutating reference while the pointer.
|
||||
// exists.
|
||||
global.with(|r| {
|
||||
let original = {
|
||||
let mut global = r.borrow_mut();
|
||||
imp::replace(&mut *global, Some(protected as _))
|
||||
};
|
||||
|
||||
// even if `f` panics the original will be replaced.
|
||||
struct ReplaceOriginal<'a, T: 'a + ?Sized> {
|
||||
original: Option<*mut T>,
|
||||
global: &'a imp::RefCell<Option<*mut T>>,
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + ?Sized> Drop for ReplaceOriginal<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
*self.global.borrow_mut() = self.original.take();
|
||||
}
|
||||
}
|
||||
|
||||
let _guard = ReplaceOriginal {
|
||||
original,
|
||||
global: r,
|
||||
};
|
||||
|
||||
f()
|
||||
})
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn with<T: ?Sized, R, F: FnOnce(&mut T) -> R>(
|
||||
global: &'static imp::LocalKey<imp::RefCell<Option<*mut T>>>,
|
||||
mutator: F,
|
||||
) -> Option<R> {
|
||||
global.with(|r| unsafe {
|
||||
let ptr = r.borrow_mut();
|
||||
match *ptr {
|
||||
Some(ptr) => {
|
||||
// safe because it's only non-zero when it's being called from using, which
|
||||
// is holding on to the underlying reference (and not using it itself) safely.
|
||||
Some(mutator(&mut *ptr))
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Declare a new global reference module whose underlying value does not contain references.
|
||||
///
|
||||
/// Will create a module of a given name that contains two functions:
|
||||
///
|
||||
/// * `pub fn using<R, F: FnOnce() -> R>(protected: &mut $t, f: F) -> R`
|
||||
/// This executes `f`, returning its value. During the call, the module's reference is set to
|
||||
/// be equal to `protected`.
|
||||
/// * `pub fn with<R, F: FnOnce(&mut $t) -> R>(f: F) -> Option<R>`
|
||||
/// This executes `f`, returning `Some` of its value if called from code that is being executed
|
||||
/// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the
|
||||
/// same reference as provided to the most recent `using` call.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Initializing the global context with a given value.
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate environmental;
|
||||
/// environmental!(counter: u32);
|
||||
/// fn main() {
|
||||
/// let mut counter_value = 41u32;
|
||||
/// counter::using(&mut counter_value, || {
|
||||
/// let odd = counter::with(|value|
|
||||
/// if *value % 2 == 1 {
|
||||
/// *value += 1; true
|
||||
/// } else {
|
||||
/// *value -= 3; false
|
||||
/// }).unwrap(); // safe because we're inside a counter::using
|
||||
/// println!("counter was {}", match odd { true => "odd", _ => "even" });
|
||||
/// });
|
||||
///
|
||||
/// println!("The answer is {:?}", counter_value); // 42
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Roughly the same, but with a trait object:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate environmental;
|
||||
///
|
||||
/// trait Increment { fn increment(&mut self); }
|
||||
///
|
||||
/// impl Increment for i32 {
|
||||
/// fn increment(&mut self) { *self += 1 }
|
||||
/// }
|
||||
///
|
||||
/// environmental!(val: Increment + 'static);
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut local = 0i32;
|
||||
/// val::using(&mut local, || {
|
||||
/// val::with(|v| for _ in 0..5 { v.increment() });
|
||||
/// });
|
||||
///
|
||||
/// assert_eq!(local, 5);
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! environmental {
|
||||
($name:ident : $t:ty) => {
|
||||
#[allow(non_camel_case_types)]
|
||||
struct $name { __private_field: () }
|
||||
|
||||
thread_local_impl!(static GLOBAL: ::std::cell::RefCell<Option<*mut $t>>
|
||||
= ::std::cell::RefCell::new(None));
|
||||
|
||||
impl $name {
|
||||
#[allow(unused_imports)]
|
||||
|
||||
pub fn using<R, F: FnOnce() -> R>(
|
||||
protected: &mut $t,
|
||||
f: F
|
||||
) -> R {
|
||||
$crate::using(&GLOBAL, protected, f)
|
||||
}
|
||||
|
||||
pub fn with<R, F: FnOnce(&mut $t) -> R>(
|
||||
f: F
|
||||
) -> Option<R> {
|
||||
$crate::with(&GLOBAL, |x| f(x))
|
||||
}
|
||||
}
|
||||
};
|
||||
($name:ident : trait @$t:ident [$($args:ty,)*]) => {
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
struct $name { __private_field: () }
|
||||
|
||||
thread_local_impl!(static GLOBAL: $crate::imp::RefCell<Option<*mut ($t<$($args),*> + 'static)>>
|
||||
= $crate::imp::RefCell::new(None));
|
||||
|
||||
impl $name {
|
||||
#[allow(unused_imports)]
|
||||
|
||||
pub fn using<R, F: FnOnce() -> R>(
|
||||
protected: &mut $t<$($args),*>,
|
||||
f: F
|
||||
) -> R {
|
||||
let lifetime_extended = unsafe {
|
||||
$crate::imp::transmute::<&mut $t<$($args),*>, &mut ($t<$($args),*> + 'static)>(protected)
|
||||
};
|
||||
$crate::using(&GLOBAL, lifetime_extended, f)
|
||||
}
|
||||
|
||||
pub fn with<R, F: for<'a> FnOnce(&'a mut ($t<$($args),*> + 'a)) -> R>(
|
||||
f: F
|
||||
) -> Option<R> {
|
||||
$crate::with(&GLOBAL, |x| f(x))
|
||||
}
|
||||
}
|
||||
};
|
||||
($name:ident<$traittype:ident> : trait $t:ident <$concretetype:ty>) => {
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
struct $name <H: $traittype> { _private_field: $crate::imp::PhantomData<H> }
|
||||
|
||||
thread_local_impl!(static GLOBAL: $crate::imp::RefCell<Option<*mut ($t<$concretetype> + 'static)>>
|
||||
= $crate::imp::RefCell::new(None));
|
||||
|
||||
impl<H: $traittype> $name<H> {
|
||||
#[allow(unused_imports)]
|
||||
pub fn using<R, F: FnOnce() -> R>(
|
||||
protected: &mut $t<H>,
|
||||
f: F
|
||||
) -> R {
|
||||
let lifetime_extended = unsafe {
|
||||
$crate::imp::transmute::<&mut $t<H>, &mut ($t<$concretetype> + 'static)>(protected)
|
||||
};
|
||||
$crate::using(&GLOBAL, lifetime_extended, f)
|
||||
}
|
||||
|
||||
pub fn with<R, F: for<'a> FnOnce(&'a mut ($t<$concretetype> + 'a)) -> R>(
|
||||
f: F
|
||||
) -> Option<R> {
|
||||
$crate::with(&GLOBAL, |x| f(x))
|
||||
}
|
||||
}
|
||||
};
|
||||
($name:ident : trait $t:ident <>) => { environmental! { $name : trait @$t [] } };
|
||||
($name:ident : trait $t:ident < $($args:ty),* $(,)* >) => { environmental! { $name : trait @$t [$($args,)*] } };
|
||||
($name:ident : trait $t:ident) => { environmental! { $name : trait @$t [] } };
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn simple_works() {
|
||||
environmental!(counter: u32);
|
||||
|
||||
fn stuff() { counter::with(|value| *value += 1); };
|
||||
|
||||
// declare a stack variable of the same type as our global declaration.
|
||||
let mut local = 41u32;
|
||||
|
||||
// call stuff, setting up our `counter` environment as a reference to our local counter var.
|
||||
counter::using(&mut local, stuff);
|
||||
assert_eq!(local, 42);
|
||||
stuff(); // safe! doesn't do anything.
|
||||
assert_eq!(local, 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overwrite_with_lesser_lifetime() {
|
||||
environmental!(items: Vec<u8>);
|
||||
|
||||
let mut local_items = vec![1, 2, 3];
|
||||
items::using(&mut local_items, || {
|
||||
let dies_at_end = vec![4, 5, 6];
|
||||
items::with(|items| *items = dies_at_end);
|
||||
});
|
||||
|
||||
assert_eq!(local_items, vec![4, 5, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn declare_with_trait_object() {
|
||||
trait Foo {
|
||||
fn get(&self) -> i32;
|
||||
fn set(&mut self, x: i32);
|
||||
}
|
||||
|
||||
impl Foo for i32 {
|
||||
fn get(&self) -> i32 { *self }
|
||||
fn set(&mut self, x: i32) { *self = x }
|
||||
}
|
||||
|
||||
environmental!(foo: Foo + 'static);
|
||||
|
||||
fn stuff() {
|
||||
foo::with(|value| {
|
||||
let new_val = value.get() + 1;
|
||||
value.set(new_val);
|
||||
});
|
||||
}
|
||||
|
||||
let mut local = 41i32;
|
||||
foo::using(&mut local, stuff);
|
||||
|
||||
assert_eq!(local, 42);
|
||||
|
||||
stuff(); // doesn't do anything.
|
||||
|
||||
assert_eq!(local, 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unwind_recursive() {
|
||||
use std::panic;
|
||||
|
||||
environmental!(items: Vec<u8>);
|
||||
|
||||
let panicked = panic::catch_unwind(|| {
|
||||
let mut local_outer = vec![1, 2, 3];
|
||||
|
||||
items::using(&mut local_outer, || {
|
||||
let mut local_inner = vec![4, 5, 6];
|
||||
items::using(&mut local_inner, || {
|
||||
panic!("are you unsafe?");
|
||||
})
|
||||
});
|
||||
}).is_err();
|
||||
|
||||
assert!(panicked);
|
||||
|
||||
let mut was_cleared = true;
|
||||
items::with(|_items| was_cleared = false);
|
||||
|
||||
assert!(was_cleared);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_non_static_trait() {
|
||||
trait Sum { fn sum(&self) -> usize; }
|
||||
impl<'a> Sum for &'a [usize] {
|
||||
fn sum(&self) -> usize {
|
||||
self.iter().fold(0, |a, c| a + c)
|
||||
}
|
||||
}
|
||||
|
||||
environmental!(sum: trait Sum);
|
||||
let numbers = vec![1, 2, 3, 4, 5];
|
||||
let mut numbers = &numbers[..];
|
||||
let got_sum = sum::using(&mut numbers, || {
|
||||
sum::with(|x| x.sum())
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(got_sum, 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_generic_trait() {
|
||||
trait Plus { fn plus42() -> usize; }
|
||||
struct ConcretePlus;
|
||||
impl Plus for ConcretePlus {
|
||||
fn plus42() -> usize { 42 }
|
||||
}
|
||||
trait Multiplier<T: Plus> { fn mul_and_add(&self) -> usize; }
|
||||
impl<'a, P: Plus> Multiplier<P> for &'a [usize] {
|
||||
fn mul_and_add(&self) -> usize {
|
||||
self.iter().fold(1, |a, c| a * c) + P::plus42()
|
||||
}
|
||||
}
|
||||
|
||||
let numbers = vec![1, 2, 3];
|
||||
let mut numbers = &numbers[..];
|
||||
let out = foo::<ConcretePlus>::using(&mut numbers, || {
|
||||
foo::<ConcretePlus>::with(|x| x.mul_and_add() )
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(out, 6 + 42);
|
||||
environmental!(foo<Plus>: trait Multiplier<ConcretePlus>);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod imp {
|
||||
pub use std::cell::RefCell;
|
||||
pub use std::thread::LocalKey;
|
||||
pub use std::mem::transmute;
|
||||
pub use std::mem::replace;
|
||||
pub use std::marker::PhantomData;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! thread_local_impl {
|
||||
($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr) => (
|
||||
thread_local!($(#[$attr])* static $name: $t = $init);
|
||||
);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod imp {
|
||||
pub use core::cell::RefCell;
|
||||
pub use core::mem::transmute;
|
||||
pub use core::mem::replace;
|
||||
pub use core::marker::PhantomData;
|
||||
|
||||
// This code is a simplified version of [`LocalKey`] and it's wasm32 specialization: [`statik::Key`].
|
||||
// [`LocalKey`]: https://github.com/alexcrichton/rust/blob/98931165a23a1c2860d99759385f45d6807c8982/src/libstd/thread/local.rs#L89
|
||||
// [`statik::Key`]: https://github.com/alexcrichton/rust/blob/98931165a23a1c2860d99759385f45d6807c8982/src/libstd/thread/local.rs#L310-L312
|
||||
|
||||
pub struct LocalKey<T: 'static> {
|
||||
pub init: fn() -> T,
|
||||
pub inner: RefCell<Option<T>>,
|
||||
}
|
||||
|
||||
// This is safe as long there is no threads in wasm32.
|
||||
unsafe impl<T: 'static> ::core::marker::Sync for LocalKey<T> { }
|
||||
|
||||
impl<T: 'static> LocalKey<T> {
|
||||
pub const fn new(init: fn() -> T) -> LocalKey<T> {
|
||||
LocalKey {
|
||||
init,
|
||||
inner: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with<F, R>(&'static self, f: F) -> R
|
||||
where F: FnOnce(&T) -> R
|
||||
{
|
||||
if self.inner.borrow().is_none() {
|
||||
let v = (self.init)();
|
||||
*self.inner.borrow_mut() = Some(v);
|
||||
}
|
||||
// This code can't panic because:
|
||||
// 1. `inner` can be borrowed mutably only once at the initialization time.
|
||||
// 2. After the initialization `inner` is always `Some`.
|
||||
f(&*self.inner.borrow().as_ref().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! thread_local_impl {
|
||||
($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr) => (
|
||||
$(#[$attr])*
|
||||
static $name: $crate::imp::LocalKey<$t> = {
|
||||
fn __init() -> $t { $init }
|
||||
|
||||
$crate::imp::LocalKey::new(__init)
|
||||
};
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ node-primitives = { path = "../primitives" }
|
||||
node-runtime = { path = "../runtime" }
|
||||
node-transaction-pool = { path = "../transaction-pool" }
|
||||
substrate-bft = { path = "../../core/bft" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
substrate-client = { path = "../../core/client" }
|
||||
sr-primitives = { path = "../../core/sr-primitives" }
|
||||
|
||||
@@ -7,7 +7,7 @@ description = "Substrate node implementation in Rust."
|
||||
[dependencies]
|
||||
hex-literal = "0.1"
|
||||
triehash = "0.2"
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
sr-io = { path = "../../core/sr-io" }
|
||||
substrate-state-machine = { path = "../../core/state-machine" }
|
||||
substrate-executor = { path = "../../core/executor" }
|
||||
|
||||
@@ -6,8 +6,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-primitives = { path = "../../core/sr-primitives", default_features = false }
|
||||
|
||||
@@ -10,8 +10,8 @@ log = { version = "0.3", optional = true }
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec-derive = { path = "../../codec/derive" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
sr-std = { path = "../../core/sr-std" }
|
||||
sr-io = { path = "../../core/sr-io" }
|
||||
srml-support = { path = "../../srml/support" }
|
||||
|
||||
@@ -9,8 +9,8 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec-derive = { path = "../../../codec/derive" }
|
||||
parity-codec = { path = "../../../codec", default-features = false }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
parity-codec = { version = "~1.0", default-features = false }
|
||||
substrate-primitives = { path = "../../../core/primitives", default-features = false }
|
||||
sr-std = { path = "../../../core/sr-std", default-features = false }
|
||||
sr-io = { path = "../../../core/sr-io", default-features = false }
|
||||
|
||||
@@ -11,7 +11,7 @@ node-api = { path = "../api" }
|
||||
node-primitives = { path = "../primitives" }
|
||||
node-runtime = { path = "../runtime" }
|
||||
substrate-client = { path = "../../core/client" }
|
||||
parity-codec = { path = "../../codec" }
|
||||
parity-codec = { version = "~1.0" }
|
||||
substrate-keyring = { path = "../../core/keyring" }
|
||||
substrate-extrinsic-pool = { path = "../../core/extrinsic-pool" }
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
|
||||
@@ -8,8 +8,8 @@ hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
|
||||
@@ -7,8 +7,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
pwasm-utils = { version = "0.3", default_features = false }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-wasm = { version = "0.31", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-primitives = { path = "../../core/sr-primitives", default_features = false }
|
||||
|
||||
@@ -9,8 +9,8 @@ integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", bran
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
|
||||
@@ -8,8 +8,8 @@ hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
@@ -7,8 +7,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
sr-primitives = { path = "../../core/sr-primitives", default_features = false }
|
||||
@@ -15,7 +15,7 @@ srml-support = { path = "../support", default_features = false }
|
||||
srml-system = { path = "../system", default_features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
parity-codec-derive = { path = "../../codec/derive" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
srml-balances = { path = "../balances" }
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
sr-primitives = { path = "../../core/sr-primitives", default_features = false }
|
||||
|
||||
@@ -8,8 +8,8 @@ hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = { version = "0.1.0", optional = true }
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
substrate-metadata = { path = "../../core/metadata", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
@@ -16,7 +16,7 @@ sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "0.5.1"
|
||||
serde_json = { version = "1.0" }
|
||||
parity-codec-derive = { path = "../../codec/derive" }
|
||||
parity-codec-derive = { version = "~1.0" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -8,8 +8,8 @@ hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
@@ -7,8 +7,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
parity-codec = { path = "../../codec", default_features = false }
|
||||
parity-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
parity-codec = { version = "~1.0", default_features = false }
|
||||
parity-codec-derive = { version = "~1.0", default_features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default_features = false }
|
||||
sr-std = { path = "../../core/sr-std", default_features = false }
|
||||
sr-io = { path = "../../core/sr-io", default_features = false }
|
||||
|
||||
Reference in New Issue
Block a user