1use std::borrow::Borrow;
10use byteorder::{ByteOrder, BigEndian};
11use elastic_array::{ElasticArray16, ElasticArray1024};
12use traits::Encodable;
13
14#[derive(Debug, Copy, Clone)]
15struct ListInfo {
16 position: usize,
17 current: usize,
18 max: Option<usize>,
19}
20
21impl ListInfo {
22 fn new(position: usize, max: Option<usize>) -> ListInfo {
23 ListInfo {
24 position: position,
25 current: 0,
26 max: max,
27 }
28 }
29}
30
31pub struct RlpStream {
33 unfinished_lists: ElasticArray16<ListInfo>,
34 buffer: ElasticArray1024<u8>,
35 finished_list: bool,
36}
37
38impl Default for RlpStream {
39 fn default() -> Self {
40 RlpStream::new()
41 }
42}
43
44impl RlpStream {
45 pub fn new() -> Self {
47 RlpStream {
48 unfinished_lists: ElasticArray16::new(),
49 buffer: ElasticArray1024::new(),
50 finished_list: false,
51 }
52 }
53
54 pub fn new_list(len: usize) -> Self {
56 let mut stream = RlpStream::new();
57 stream.begin_list(len);
58 stream
59 }
60
61 pub fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
75 self.finished_list = false;
76 value.rlp_append(self);
77 if !self.finished_list {
78 self.note_appended(1);
79 }
80 self
81 }
82
83 pub fn append_list<'a, E, K>(&'a mut self, values: &[K]) -> &'a mut Self where E: Encodable, K: Borrow<E> {
85 self.begin_list(values.len());
86 for value in values {
87 self.append(value.borrow());
88 }
89 self
90 }
91
92 pub fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
95 value.rlp_append(self);
96 self
97 }
98
99 pub fn begin_list(&mut self, len: usize) -> &mut RlpStream {
114 self.finished_list = false;
115 match len {
116 0 => {
117 self.buffer.push(0xc0u8);
119 self.note_appended(1);
120 self.finished_list = true;
121 },
122 _ => {
123 self.buffer.push(0);
126
127 let position = self.buffer.len();
128 self.unfinished_lists.push(ListInfo::new(position, Some(len)));
129 },
130 }
131
132 self
134 }
135
136
137 pub fn begin_unbounded_list(&mut self) -> &mut RlpStream {
139 self.finished_list = false;
140 self.buffer.push(0);
143 let position = self.buffer.len();
144 self.unfinished_lists.push(ListInfo::new(position, None));
145 self
147 }
148
149 pub fn append_empty_data(&mut self) -> &mut RlpStream {
163 self.buffer.push(0x80);
165
166 self.note_appended(1);
168
169 self
171 }
172
173 pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream {
175 self.buffer.append_slice(bytes);
177
178 self.note_appended(item_count);
180
181 self
183 }
184
185 pub fn append_raw_checked<'a>(&'a mut self, bytes: &[u8], item_count: usize, max_size: usize) -> bool {
187 if self.estimate_size(bytes.len()) > max_size {
188 return false;
189 }
190 self.append_raw(bytes, item_count);
191 true
192 }
193
194 pub fn estimate_size<'a>(&'a self, add: usize) -> usize {
196 let total_size = self.buffer.len() + add;
197 let mut base_size = total_size;
198 for list in &self.unfinished_lists[..] {
199 let len = total_size - list.position;
200 if len > 55 {
201 let leading_empty_bytes = (len as u64).leading_zeros() as usize / 8;
202 let size_bytes = 8 - leading_empty_bytes;
203 base_size += size_bytes;
204 }
205 }
206 base_size
207 }
208
209
210 pub fn len<'a>(&'a self) -> usize {
212 self.estimate_size(0)
213 }
214
215 pub fn clear(&mut self) {
230 self.buffer.clear();
232
233 self.unfinished_lists.clear();
235 }
236
237 pub fn is_finished(&self) -> bool {
253 self.unfinished_lists.len() == 0
254 }
255
256 pub fn as_raw(&self) -> &[u8] {
258 &self.buffer
260 }
261
262 pub fn out(self) -> Vec<u8> {
266 match self.is_finished() {
267 true => self.buffer.to_vec(),
269 false => panic!()
270 }
271 }
272
273 fn note_appended(&mut self, inserted_items: usize) -> () {
275 if self.unfinished_lists.len() == 0 {
276 return;
277 }
278
279 let back = self.unfinished_lists.len() - 1;
280 let should_finish = match self.unfinished_lists.get_mut(back) {
281 None => false,
282 Some(ref mut x) => {
283 x.current += inserted_items;
284 match x.max {
285 Some(ref max) if x.current > *max => panic!("You cannot append more items then you expect!"),
286 Some(ref max) => x.current == *max,
287 _ => false,
288 }
289 }
290 };
291
292 if should_finish {
293 let x = self.unfinished_lists.pop().unwrap();
294 let len = self.buffer.len() - x.position;
295 self.encoder().insert_list_payload(len, x.position);
296 self.note_appended(1);
297 }
298 self.finished_list = should_finish;
299 }
300
301 pub fn encoder(&mut self) -> BasicEncoder {
302 BasicEncoder::new(self)
303 }
304
305 pub fn drain(self) -> ElasticArray1024<u8> {
307 match self.is_finished() {
308 true => self.buffer,
309 false => panic!()
310 }
311 }
312
313 pub fn complete_unbounded_list(&mut self) {
315 let list = self.unfinished_lists.pop().expect("No open list.");
316 if list.max.is_some() {
317 panic!("List type mismatch.");
318 }
319 let len = self.buffer.len() - list.position;
320 self.encoder().insert_list_payload(len, list.position);
321 self.note_appended(1);
322 }
323}
324
325pub struct BasicEncoder<'a> {
326 buffer: &'a mut ElasticArray1024<u8>,
327}
328
329impl<'a> BasicEncoder<'a> {
330 fn new(stream: &'a mut RlpStream) -> Self {
331 BasicEncoder {
332 buffer: &mut stream.buffer
333 }
334 }
335
336 fn insert_size(&mut self, size: usize, position: usize) -> u8 {
337 let size = size as u32;
338 let leading_empty_bytes = size.leading_zeros() as usize / 8;
339 let size_bytes = 4 - leading_empty_bytes as u8;
340 let mut buffer = [0u8; 4];
341 BigEndian::write_u32(&mut buffer, size);
342 self.buffer.insert_slice(position, &buffer[leading_empty_bytes..]);
343 size_bytes as u8
344 }
345
346 fn insert_list_payload(&mut self, len: usize, pos: usize) {
348 match len {
350 0...55 => {
351 self.buffer[pos - 1] = 0xc0u8 + len as u8;
352 },
353 _ => {
354 let inserted_bytes = self.insert_size(len, pos);
355 self.buffer[pos - 1] = 0xf7u8 + inserted_bytes;
356 }
357 };
358 }
359
360 pub fn encode_value(&mut self, value: &[u8]) {
362 match value.len() {
363 0 => self.buffer.push(0x80u8),
365 1 if value[0] < 0x80 => self.buffer.push(value[0]),
367 len @ 1 ... 55 => {
369 self.buffer.push(0x80u8 + len as u8);
370 self.buffer.append_slice(value);
371 }
372 len => {
374 self.buffer.push(0);
375 let position = self.buffer.len();
376 let inserted_bytes = self.insert_size(len, position);
377 self.buffer[position - 1] = 0xb7 + inserted_bytes;
378 self.buffer.append_slice(value);
379 }
380 }
381 }
382}