Merge pull request #4 from gavofyork/insert_slice

rlp uses insert_slice
This commit is contained in:
Arkadiy Paronyan 2015-11-26 19:11:48 +01:00
commit 04abfae6b5
3 changed files with 46 additions and 19 deletions

View File

@ -5,6 +5,7 @@ pub mod hash;
pub mod uint; pub mod uint;
pub mod bytes; pub mod bytes;
pub mod rlp; pub mod rlp;
pub mod vector;
#[test] #[test]
fn it_works() { fn it_works() {

View File

@ -48,6 +48,7 @@ use std::cell::Cell;
use std::collections::LinkedList; use std::collections::LinkedList;
use std::error::Error as StdError; use std::error::Error as StdError;
use bytes::{ToBytes, FromBytes, FromBytesError}; use bytes::{ToBytes, FromBytes, FromBytesError};
use vector::InsertSlice;
/// rlp container /// rlp container
#[derive(Debug)] #[derive(Debug)]
@ -455,27 +456,18 @@ impl BasicEncoder {
} }
/// inserts list prefix at given position /// 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) -> () { fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () {
// new bytes let mut res = vec![];
let mut res: Vec<u8> = vec![]; match len {
// reserve a space equal at least current space + space for length 0...55 => res.push(0xc0u8 + len as u8),
res.reserve(self.bytes.len() + 1); _ => {
{ res.push(0x7fu8 + len.to_bytes_len() as u8);
let (before_slice, after_slice) = self.bytes.split_at(pos); res.extend(len.to_bytes());
res.extend(before_slice); }
};
match len { self.bytes.insert_slice(pos, &res);
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;
} }
/// get encoded value /// get encoded value

34
src/vector.rs Normal file
View File

@ -0,0 +1,34 @@
use std::ptr;
pub trait InsertSlice<T> {
fn insert_slice(&mut self, index: usize, elements: &[T]);
}
/// based on `insert` function implementation from standard library
impl<T> InsertSlice<T> for Vec<T> {
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);
}
}
}