Skip to content
Snippets Groups Projects
Commit 3f964196 authored by Gav Wood's avatar Gav Wood Committed by GitHub
Browse files

Remove unneeded code (#737)

parent bd40f051
No related merge requests found
Showing
with 18 additions and 1257 deletions
[workspace]
members = [
"codec",
"codec/derive",
"environmental",
"core/bft",
"core/cli",
"core/client",
......
[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 = []
= Codec
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
[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 = []
// 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)
}
},
}
}
// 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]
}
// 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 })
)
}
// 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)));
}
// 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());
}
}
// 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
}
}
// 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
})
}
}
// 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" }
......
......@@ -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 }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment