From 0b9620f3ec6580150501e9e93da66f3689264643 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 26 Nov 2015 19:09:14 +0100 Subject: [PATCH] rlp uses insert_slice --- src/lib.rs | 1 + src/rlp.rs | 30 +++++++++++------------------- src/vector.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 src/vector.rs diff --git a/src/lib.rs b/src/lib.rs index ab8cac701..863f5d74c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ pub mod hash; pub mod uint; pub mod bytes; pub mod rlp; +pub mod vector; #[test] fn it_works() { diff --git a/src/rlp.rs b/src/rlp.rs index 3e29b783b..f70062457 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -48,6 +48,7 @@ use std::cell::Cell; use std::collections::LinkedList; use std::error::Error as StdError; use bytes::{ToBytes, FromBytes, FromBytesError}; +use vector::InsertSlice; /// rlp container #[derive(Debug)] @@ -455,27 +456,18 @@ impl BasicEncoder { } /// inserts list prefix at given position - /// TODO: optimise it, so it does not copy an array + /// TODO: optimise it further? fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () { - // new bytes - let mut res: Vec = vec![]; - // reserve a space equal at least current space + space for length - res.reserve(self.bytes.len() + 1); - { - let (before_slice, after_slice) = self.bytes.split_at(pos); - res.extend(before_slice); + let mut res = vec![]; + match len { + 0...55 => res.push(0xc0u8 + len as u8), + _ => { + res.push(0x7fu8 + len.to_bytes_len() as u8); + res.extend(len.to_bytes()); + } + }; - match len { - 0...55 => res.push(0xc0u8 + len as u8), - _ => { - res.push(0x7fu8 + len.to_bytes_len() as u8); - res.extend(len.to_bytes()); - } - }; - - res.extend(after_slice); - } - self.bytes = res; + self.bytes.insert_slice(pos, &res); } /// get encoded value diff --git a/src/vector.rs b/src/vector.rs new file mode 100644 index 000000000..ce891beba --- /dev/null +++ b/src/vector.rs @@ -0,0 +1,34 @@ + +use std::ptr; + +pub trait InsertSlice { + fn insert_slice(&mut self, index: usize, elements: &[T]); +} + +/// based on `insert` function implementation from standard library +impl InsertSlice for Vec { + fn insert_slice(&mut self, index: usize, elements: &[T]) { + let e_len = elements.len(); + if e_len == 0 { + return; + } + + let len = self.len(); + assert!(index <= len); + + // space for the new element + self.reserve(e_len); + + unsafe { + { + let p = self.as_mut_ptr().offset(index as isize); + let ep = elements.as_ptr().offset(0); + // shift everything by e_len, to make space + ptr::copy(p, p.offset(e_len as isize), len - index); + // write new element + ptr::copy(ep, p, e_len); + } + self.set_len(len + e_len); + } + } +}