diff --git a/substrate/runtime-codec/src/lib.rs b/substrate/runtime-codec/src/lib.rs index f31fa3cf945e7201d1fd3b670d9023ad54b9cc38..05999531568767e821931bee96b4a7fbbdd047d5 100644 --- a/substrate/runtime-codec/src/lib.rs +++ b/substrate/runtime-codec/src/lib.rs @@ -28,7 +28,6 @@ mod keyedvec; pub use self::endiansensitive::EndianSensitive; pub use self::slicable::{Slicable, NonTrivialSlicable}; -pub use self::streamreader::StreamReader; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; diff --git a/substrate/runtime-codec/src/slicable.rs b/substrate/runtime-codec/src/slicable.rs index 82b527c771883d190dfd97021cecc40649fe64f0..1d76fb851e3e4a37fc6e1bf4e8b0ea01846d4e23 100644 --- a/substrate/runtime-codec/src/slicable.rs +++ b/substrate/runtime-codec/src/slicable.rs @@ -23,115 +23,108 @@ use super::endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { - /// Attempt to deserialise the value from a slice. - fn from_slice(value: &[u8]) -> Option<Self> { - Self::set_as_slice(|out, offset| if value.len() >= out.len() + offset { - let value = &value[offset..]; - let len = out.len(); - out.copy_from_slice(&value[0..len]); - true - } else { - false - }) - } + /// Attempt to deserialise the value from a slice. Ignore trailing bytes and + /// set the slice's start to just after the last byte consumed. + /// + /// If `None` is returned, then the slice should be unmodified. + fn from_slice(value: &mut &[u8]) -> Option<Self>; + /// Convert self to an owned vector. fn to_vec(&self) -> Vec<u8> { self.as_slice_then(|s| s.to_vec()) } - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(fill_slice: F) -> Option<Self>; - fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { - f(&self.to_vec()) - } - fn size_of(_value: &[u8]) -> Option<usize>; + /// Convert self to a slice and then invoke the given closure with it. + fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R; } /// Trait to mark that a type is not trivially (essentially "in place") serialisable. pub trait NonTrivialSlicable: Slicable {} impl<T: EndianSensitive> Slicable for T { - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(fill_slice: F) -> Option<Self> { + fn from_slice(value: &mut &[u8]) -> Option<Self> { let size = mem::size_of::<T>(); assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); - let mut result: T = unsafe { mem::zeroed() }; - let result_slice = unsafe { - let ptr = &mut result as *mut _ as *mut u8; - slice::from_raw_parts_mut(ptr, size) - }; - if fill_slice(result_slice, 0) { - Some(result.from_le()) + if value.len() >= size { + let x: T = unsafe { ::std::ptr::read(value.as_ptr() as *const T) }; + *value = &value[size..]; + Some(x.from_le()) } else { None } } + fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { - let size = mem::size_of::<Self>(); - assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); self.as_le_then(|le| { + let size = mem::size_of::<T>(); let value_slice = unsafe { let ptr = le as *const _ as *const u8; - slice::from_raw_parts(ptr, size) + if size != 0 { + slice::from_raw_parts(ptr, size) + } else { + &[] + } }; + f(value_slice) }) } - fn size_of(_value: &[u8]) -> Option<usize> { - Some(mem::size_of::<Self>()) - } } impl Slicable for Vec<u8> { - fn from_slice(value: &[u8]) -> Option<Self> { - Some(value[4..].to_vec()) - } - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(fill_slice: F) -> Option<Self> { - u32::set_as_slice(&fill_slice).and_then(|len| { - let mut v = Vec::with_capacity(len as usize); - unsafe { v.set_len(len as usize); } - if fill_slice(&mut v, 4) { - Some(v) - } else { - None - } + fn from_slice(value: &mut &[u8]) -> Option<Self> { + u32::from_slice(value).map(move |len| { + let len = len as usize; + let res = value[..len].to_vec(); + *value = &value[len..]; + res }) } + fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { + f(&self.to_vec()) + } + fn to_vec(&self) -> Vec<u8> { - let mut r: Vec<u8> = Vec::new().join(&(self.len() as u32)); - r.extend_from_slice(&self); + let len = self.len(); + assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); + + let mut r: Vec<u8> = Vec::new().join(&(len as u32)); + r.extend_from_slice(self); r } - fn size_of(data: &[u8]) -> Option<usize> { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) - } } impl<T: Slicable> NonTrivialSlicable for Vec<T> where Vec<T>: Slicable {} impl<T: NonTrivialSlicable> Slicable for Vec<T> { - fn from_slice(value: &[u8]) -> Option<Self> { - let len = Self::size_of(&value[0..4])?; - let mut off = 4; - let mut r = Vec::new(); - while off < len { - let element_len = T::size_of(&value[off..])?; - r.push(T::from_slice(&value[off..off + element_len])?); - off += element_len; - } - Some(r) + fn from_slice(value: &mut &[u8]) -> Option<Self> { + u32::from_slice(value).and_then(move |len| { + let len = len as usize; + let mut r = Vec::with_capacity(len); + for _ in 0..len { + match T::from_slice(value) { + None => return None, + Some(v) => r.push(v), + } + } + + Some(r) + }) } - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: F) -> Option<Self> { - unimplemented!(); + fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { + f(&self.to_vec()) } fn to_vec(&self) -> Vec<u8> { - let vecs = self.iter().map(Slicable::to_vec).collect::<Vec<_>>(); - let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = Vec::new().join(&(len as u32)); - vecs.iter().for_each(|v| r.extend_from_slice(v)); - r - } + use std::iter::Extend; - fn size_of(data: &[u8]) -> Option<usize> { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + let len = self.len(); + assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); + + let mut r: Vec<u8> = Vec::new().join(&(len as u32)); + for item in self { + r.extend(item.to_vec()); + } + r } } diff --git a/substrate/runtime-codec/src/streamreader.rs b/substrate/runtime-codec/src/streamreader.rs deleted file mode 100644 index 33056a5ac391c2106214972fb1880cb3813f1418..0000000000000000000000000000000000000000 --- a/substrate/runtime-codec/src/streamreader.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. - -//! Deserialiser. - -use slicable::Slicable; - -/// Simple deserialiser. -pub struct StreamReader<'a> { - data: &'a [u8], - offset: usize, -} - -impl<'a> StreamReader<'a> { - /// Create a new deserialiser based on the `data`. - pub fn new(data: &'a [u8]) -> Self { - StreamReader { - data: data, - offset: 0, - } - } - - /// Deserialise a single item from the data stream. - pub fn read<T: Slicable>(&mut self) -> Option<T> { - let size = T::size_of(&self.data[self.offset..])?; - let new_offset = self.offset + size; - let slice = &self.data[self.offset..new_offset]; - self.offset = new_offset; - Slicable::from_slice(slice) - } -} -/* -// Not in use yet -// TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement -struct StreamWriter<'a> { - data: &'a mut[u8], - offset: usize, -} - -impl<'a> StreamWriter<'a> { - pub fn new(data: &'a mut[u8]) -> Self { - StreamWriter { - data: data, - offset: 0, - } - } - pub fn write<T: Slicable>(&mut self, value: &T) -> bool { - value.as_slice_then(|s| { - let new_offset = self.offset + s.len(); - if self.data.len() <= new_offset { - let slice = &mut self.data[self.offset..new_offset]; - self.offset = new_offset; - slice.copy_from_slice(s); - true - } else { - false - } - }) - } -} -*/