1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Really Bad Markup Language (rbml) is an internal serialization format of rustc.
12 //! This is not intended to be used by users.
14 //! Originally based on the Extensible Binary Markup Language
15 //! (ebml; http://www.matroska.org/technical/specs/rfc/index.html),
16 //! it is now a separate format tuned for the rust object metadata.
20 //! RBML document consists of the tag, length and data.
21 //! The encoded data can contain multiple RBML documents concatenated.
23 //! **Tags** are a hint for the following data.
24 //! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved.
25 //! Tags less than 0xf0 are encoded in one literal byte.
26 //! Tags greater than 0xff are encoded in two big-endian bytes,
27 //! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`)
29 //! **Lengths** encode the length of the following data.
30 //! It is a variable-length unsigned isize, and one of the following forms:
32 //! - `80` through `fe` for lengths up to 0x7e;
33 //! - `40 ff` through `7f ff` for lengths up to 0x3fff;
34 //! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff;
35 //! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff.
37 //! The "overlong" form is allowed so that the length can be encoded
38 //! without the prior knowledge of the encoded data.
39 //! For example, the length 0 can be represented either by `80`, `40 00`,
40 //! `20 00 00` or `10 00 00 00`.
41 //! The encoder tries to minimize the length if possible.
42 //! Also, some predefined tags listed below are so commonly used that
43 //! their lengths are omitted ("implicit length").
45 //! **Data** can be either binary bytes or zero or more nested RBML documents.
46 //! Nested documents cannot overflow, and should be entirely contained
47 //! within a parent document.
51 //! Most RBML tags are defined by the application.
52 //! (For the rust object metadata, see also `rustc::metadata::common`.)
53 //! RBML itself does define a set of predefined tags however,
54 //! intended for the auto-serialization implementation.
56 //! Predefined tags with an implicit length:
58 //! - `U8` (`00`): 1-byte unsigned integer.
59 //! - `U16` (`01`): 2-byte big endian unsigned integer.
60 //! - `U32` (`02`): 4-byte big endian unsigned integer.
61 //! - `U64` (`03`): 8-byte big endian unsigned integer.
62 //! Any of `U*` tags can be used to encode primitive unsigned integer types,
63 //! as long as it is no greater than the actual size.
64 //! For example, `u8` can only be represented via the `U8` tag.
66 //! - `I8` (`04`): 1-byte signed integer.
67 //! - `I16` (`05`): 2-byte big endian signed integer.
68 //! - `I32` (`06`): 4-byte big endian signed integer.
69 //! - `I64` (`07`): 8-byte big endian signed integer.
70 //! Similar to `U*` tags. Always uses two's complement encoding.
72 //! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true.
74 //! - `Char` (`09`): 4-byte big endian Unicode scalar value.
75 //! Surrogate pairs or out-of-bound values are invalid.
77 //! - `F32` (`0a`): 4-byte big endian unsigned integer representing
78 //! IEEE 754 binary32 floating-point format.
79 //! - `F64` (`0b`): 8-byte big endian unsigned integer representing
80 //! IEEE 754 binary64 floating-point format.
82 //! - `Sub8` (`0c`): 1-byte unsigned integer for supplementary information.
83 //! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information.
84 //! Those two tags normally occur as the first subdocument of certain tags,
85 //! namely `Enum`, `Vec` and `Map`, to provide a variant or size information.
86 //! They can be used interchangeably.
88 //! Predefined tags with an explicit length:
90 //! - `Str` (`10`): A UTF-8-encoded string.
92 //! - `Enum` (`11`): An enum.
93 //! The first subdocument should be `Sub*` tags with a variant ID.
94 //! Subsequent subdocuments, if any, encode variant arguments.
96 //! - `Vec` (`12`): A vector (sequence).
97 //! - `VecElt` (`13`): A vector element.
98 //! The first subdocument should be `Sub*` tags with the number of elements.
99 //! Subsequent subdocuments should be `VecElt` tag per each element.
101 //! - `Map` (`14`): A map (associated array).
102 //! - `MapKey` (`15`): A key part of the map entry.
103 //! - `MapVal` (`16`): A value part of the map entry.
104 //! The first subdocument should be `Sub*` tags with the number of entries.
105 //! Subsequent subdocuments should be an alternating sequence of
106 //! `MapKey` and `MapVal` tags per each entry.
108 //! - `Opaque` (`17`): An opaque, custom-format tag.
109 //! Used to wrap ordinary custom tags or data in the auto-serialized context.
110 //! Rustc typically uses this to encode type informations.
112 //! First 0x20 tags are reserved by RBML; custom tags start at 0x20.
114 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
115 #![cfg_attr(stage0, feature(custom_attribute))]
116 #![crate_name = "rbml"]
117 #![unstable(feature = "rustc_private", issue = "27812")]
119 #![crate_type = "rlib"]
120 #![crate_type = "dylib"]
121 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
122 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
123 html_root_url = "https://doc.rust-lang.org/nightly/",
124 html_playground_url = "https://play.rust-lang.org/",
125 test(attr(deny(warnings))))]
127 #![feature(rustc_private)]
128 #![feature(staged_api)]
129 #![feature(slice_bytes)]
131 #![cfg_attr(test, feature(test))]
133 extern crate serialize;
134 #[macro_use] extern crate log;
136 #[cfg(test)] extern crate test;
138 pub use self::EbmlEncoderTag::*;
139 pub use self::Error::*;
144 /// Common data structures
145 #[derive(Clone, Copy)]
152 impl<'doc> Doc<'doc> {
153 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
154 Doc { data: data, start: 0, end: data.len() }
157 pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
158 reader::get_doc(*self, tag)
161 pub fn is_empty(&self) -> bool {
162 self.start == self.end
165 pub fn as_str_slice<'a>(&'a self) -> &'a str {
166 str::from_utf8(&self.data[self.start..self.end]).unwrap()
169 pub fn as_str(&self) -> String {
170 self.as_str_slice().to_string()
174 pub struct TaggedDoc<'a> {
179 #[derive(Copy, Clone, Debug)]
180 pub enum EbmlEncoderTag {
181 // tags 00..1f are reserved for auto-serialization.
182 // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
184 EsU8 = 0x00, // + 1 byte
185 EsU16 = 0x01, // + 2 bytes
186 EsU32 = 0x02, // + 4 bytes
187 EsU64 = 0x03, // + 8 bytes
188 EsI8 = 0x04, // + 1 byte
189 EsI16 = 0x05, // + 2 bytes
190 EsI32 = 0x06, // + 4 bytes
191 EsI64 = 0x07, // + 8 bytes
192 EsBool = 0x08, // + 1 byte
193 EsChar = 0x09, // + 4 bytes
194 EsF32 = 0x0a, // + 4 bytes
195 EsF64 = 0x0b, // + 8 bytes
196 EsSub8 = 0x0c, // + 1 byte
197 EsSub32 = 0x0d, // + 4 bytes
198 // 0x0e and 0x0f are reserved
201 EsEnum = 0x11, // encodes the variant id as the first EsSub*
202 EsVec = 0x12, // encodes the # of elements as the first EsSub*
204 EsMap = 0x14, // encodes the # of pairs as the first EsSub*
210 const NUM_TAGS: usize = 0x1000;
211 const NUM_IMPLICIT_TAGS: usize = 0x0e;
213 static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
227 IoError(std::io::Error),
228 ApplicationError(String)
231 impl fmt::Display for Error {
232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233 // FIXME: this should be a more useful display form
234 fmt::Debug::fmt(self, f)
237 // --------------------------------------
243 use std::mem::transmute;
244 use std::slice::bytes;
248 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
249 EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
250 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
251 EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
252 Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
254 pub type DecodeResult<T> = Result<T, Error>;
257 macro_rules! try_or {
258 ($e:expr, $r:expr) => (
262 debug!("ignored error: {:?}", e);
269 #[derive(Copy, Clone)]
275 pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
276 let v = data[start] as usize;
278 Ok(Res { val: v, next: start + 1 })
280 Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as usize, next: start + 2 })
282 // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
288 fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
291 return Ok(Res {val: (a & 0x7f) as usize, next: start + 1});
294 return Ok(Res {val: ((a & 0x3f) as usize) << 8 |
295 (data[start + 1] as usize),
299 return Ok(Res {val: ((a & 0x1f) as usize) << 16 |
300 (data[start + 1] as usize) << 8 |
301 (data[start + 2] as usize),
305 return Ok(Res {val: ((a & 0x0f) as usize) << 24 |
306 (data[start + 1] as usize) << 16 |
307 (data[start + 2] as usize) << 8 |
308 (data[start + 3] as usize),
311 Err(IntTooBig(a as usize))
314 pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
315 if data.len() - start < 4 {
316 return vuint_at_slow(data, start);
319 // Lookup table for parsing EBML Element IDs as per
320 // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by
321 // reading a big endian u32 positioned at data[start]. Using the four
322 // most significant bits of the u32 we lookup in the table below how
323 // the element ID should be derived from it.
325 // The table stores tuples (shift, mask) where shift is the number the
326 // u32 should be right shifted with and mask is the value the right
327 // shifted value should be masked with. If for example the most
328 // significant bit is set this means it's a class A ID and the u32
329 // should be right shifted with 24 and masked with 0x7f. Therefore we
330 // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most
331 // significant bit is set).
333 // By storing the number of shifts and masks in a table instead of
334 // checking in order if the most significant bit is set, the second
335 // most significant bit is set etc. we can replace up to three
336 // "and+branch" with a single table lookup which gives us a measured
337 // speedup of around 2x on x86_64.
338 static SHIFT_MASK_TABLE: [(usize, u32); 16] = [
339 (0, 0x0), (0, 0x0fffffff),
340 (8, 0x1fffff), (8, 0x1fffff),
341 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
342 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
343 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
347 let ptr = data.as_ptr().offset(start as isize) as *const u32;
348 let val = u32::from_be(*ptr);
350 let i = (val >> 28) as usize;
351 let (shift, mask) = SHIFT_MASK_TABLE[i];
353 val: ((val >> shift) & mask) as usize,
354 next: start + ((32 - shift) >> 3),
359 pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult<Res> {
360 if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 {
361 Ok(Res { val: TAG_IMPLICIT_LEN[tag.val] as usize, next: tag.next })
363 vuint_at(data, tag.next)
367 pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult<TaggedDoc<'a>> {
368 let elt_tag = try!(tag_at(data, start));
369 let elt_size = try!(tag_len_at(data, elt_tag));
370 let end = elt_size.next + elt_size.val;
373 doc: Doc { data: data, start: elt_size.next, end: end }
377 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
378 let mut pos = d.start;
380 let elt_tag = try_or!(tag_at(d.data, pos), None);
381 let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
382 pos = elt_size.next + elt_size.val;
383 if elt_tag.val == tg {
384 return Some(Doc { data: d.data, start: elt_size.next,
391 pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
392 match maybe_get_doc(d, tg) {
395 error!("failed to find block with tag {:?}", tg);
401 pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
407 pub struct DocsIterator<'a> {
411 impl<'a> Iterator for DocsIterator<'a> {
412 type Item = (usize, Doc<'a>);
414 fn next(&mut self) -> Option<(usize, Doc<'a>)> {
415 if self.d.start >= self.d.end {
419 let elt_tag = try_or!(tag_at(self.d.data, self.d.start), {
420 self.d.start = self.d.end;
423 let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), {
424 self.d.start = self.d.end;
428 let end = elt_size.next + elt_size.val;
431 start: elt_size.next,
436 return Some((elt_tag.val, doc));
440 pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> {
447 pub struct TaggedDocsIterator<'a> {
448 iter: DocsIterator<'a>,
452 impl<'a> Iterator for TaggedDocsIterator<'a> {
455 fn next(&mut self) -> Option<Doc<'a>> {
456 while let Some((tag, doc)) = self.iter.next() {
465 pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
466 F: FnOnce(&[u8]) -> T,
468 f(&d.data[d.start..d.end])
471 pub fn doc_as_u8(d: Doc) -> u8 {
472 assert_eq!(d.end, d.start + 1);
476 pub fn doc_as_u64(d: Doc) -> u64 {
478 // For performance, we read 8 big-endian bytes,
479 // and mask off the junk if there is any. This
480 // obviously won't work on the first 8 bytes
481 // of a file - we will fall of the start
482 // of the page and segfault.
485 bytes::copy_memory(&d.data[d.end-8..d.end], &mut b);
486 let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() };
487 let len = d.end - d.start;
489 data & ((1<<(len*8))-1)
495 for b in &d.data[d.start..d.end] {
496 result = (result<<8) + (*b as u64);
502 #[inline] pub fn doc_as_u16(d: Doc) -> u16 { doc_as_u64(d) as u16 }
503 #[inline] pub fn doc_as_u32(d: Doc) -> u32 { doc_as_u64(d) as u32 }
505 #[inline] pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
506 #[inline] pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
507 #[inline] pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
508 #[inline] pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
510 pub struct Decoder<'a> {
515 impl<'doc> Decoder<'doc> {
516 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
523 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
524 debug!(". next_doc(exp_tag={:?})", exp_tag);
525 if self.pos >= self.parent.end {
526 return Err(Expected(format!("no more documents in \
529 let TaggedDoc { tag: r_tag, doc: r_doc } =
530 try!(doc_at(self.parent.data, self.pos));
531 debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}",
538 if r_tag != (exp_tag as usize) {
539 return Err(Expected(format!("expected EBML doc with tag {:?} but \
540 found tag {:?}", exp_tag, r_tag)));
542 if r_doc.end > self.parent.end {
543 return Err(Expected(format!("invalid EBML, child extends to \
544 {:#x}, parent to {:#x}",
545 r_doc.end, self.parent.end)));
547 self.pos = r_doc.end;
551 fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
552 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
554 let d = try!(self.next_doc(exp_tag));
555 let old_parent = self.parent;
556 let old_pos = self.pos;
559 let r = try!(f(self));
560 self.parent = old_parent;
565 fn _next_sub(&mut self) -> DecodeResult<usize> {
566 // empty vector/map optimization
567 if self.parent.is_empty() {
571 let TaggedDoc { tag: r_tag, doc: r_doc } =
572 try!(doc_at(self.parent.data, self.pos));
573 let r = if r_tag == (EsSub8 as usize) {
574 doc_as_u8(r_doc) as usize
575 } else if r_tag == (EsSub32 as usize) {
576 doc_as_u32(r_doc) as usize
578 return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
579 found tag {:?}", EsSub8, EsSub32, r_tag)));
581 if r_doc.end > self.parent.end {
582 return Err(Expected(format!("invalid EBML, child extends to \
583 {:#x}, parent to {:#x}",
584 r_doc.end, self.parent.end)));
586 self.pos = r_doc.end;
587 debug!("_next_sub result={:?}", r);
591 // variable-length unsigned integer with different tags.
592 // `first_tag` should be a tag for u8 or i8.
593 // `last_tag` should be the largest allowed integer tag with the matching signedness.
594 // all tags between them should be valid, in the order of u8, u16, u32 and u64.
595 fn _next_int(&mut self,
596 first_tag: EbmlEncoderTag,
597 last_tag: EbmlEncoderTag) -> DecodeResult<u64> {
598 if self.pos >= self.parent.end {
599 return Err(Expected(format!("no more documents in \
603 let TaggedDoc { tag: r_tag, doc: r_doc } =
604 try!(doc_at(self.parent.data, self.pos));
605 let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize {
606 match r_tag - first_tag as usize {
607 0 => doc_as_u8(r_doc) as u64,
608 1 => doc_as_u16(r_doc) as u64,
609 2 => doc_as_u32(r_doc) as u64,
610 3 => doc_as_u64(r_doc),
614 return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
615 found tag {:?}", first_tag, last_tag, r_tag)));
617 if r_doc.end > self.parent.end {
618 return Err(Expected(format!("invalid EBML, child extends to \
619 {:#x}, parent to {:#x}",
620 r_doc.end, self.parent.end)));
622 self.pos = r_doc.end;
623 debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
627 pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
628 F: FnOnce(&mut Decoder, Doc) -> DecodeResult<R>,
630 let doc = try!(self.next_doc(EsOpaque));
632 let (old_parent, old_pos) = (self.parent, self.pos);
634 self.pos = doc.start;
636 let result = try!(op(self, doc));
638 self.parent = old_parent;
644 impl<'doc> serialize::Decoder for Decoder<'doc> {
646 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
648 fn read_u64(&mut self) -> DecodeResult<u64> { self._next_int(EsU8, EsU64) }
649 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(try!(self._next_int(EsU8, EsU32)) as u32) }
650 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(try!(self._next_int(EsU8, EsU16)) as u16) }
651 fn read_u8(&mut self) -> DecodeResult<u8> { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) }
652 fn read_uint(&mut self) -> DecodeResult<usize> {
653 let v = try!(self._next_int(EsU8, EsU64));
654 if v > (::std::usize::MAX as u64) {
655 Err(IntTooBig(v as usize))
661 fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self._next_int(EsI8, EsI64)) as i64) }
662 fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self._next_int(EsI8, EsI32)) as i32) }
663 fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self._next_int(EsI8, EsI16)) as i16) }
664 fn read_i8(&mut self) -> DecodeResult<i8> { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) }
665 fn read_int(&mut self) -> DecodeResult<isize> {
666 let v = try!(self._next_int(EsI8, EsI64)) as i64;
667 if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
668 debug!("FIXME \\#6122: Removing this makes this function miscompile");
669 Err(IntTooBig(v as usize))
675 fn read_bool(&mut self) -> DecodeResult<bool> {
676 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
679 fn read_f64(&mut self) -> DecodeResult<f64> {
680 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
681 Ok(unsafe { transmute(bits) })
683 fn read_f32(&mut self) -> DecodeResult<f32> {
684 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
685 Ok(unsafe { transmute(bits) })
687 fn read_char(&mut self) -> DecodeResult<char> {
688 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
690 fn read_str(&mut self) -> DecodeResult<String> {
691 Ok(try!(self.next_doc(EsStr)).as_str())
695 fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
696 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
698 debug!("read_enum({})", name);
700 let doc = try!(self.next_doc(EsEnum));
702 let (old_parent, old_pos) = (self.parent, self.pos);
704 self.pos = self.parent.start;
706 let result = try!(f(self));
708 self.parent = old_parent;
713 fn read_enum_variant<T, F>(&mut self, _: &[&str],
714 mut f: F) -> DecodeResult<T>
715 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
717 debug!("read_enum_variant()");
718 let idx = try!(self._next_sub());
719 debug!(" idx={}", idx);
724 fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
725 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
727 debug!("read_enum_variant_arg(idx={})", idx);
731 fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
732 mut f: F) -> DecodeResult<T>
733 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
735 debug!("read_enum_struct_variant()");
736 let idx = try!(self._next_sub());
737 debug!(" idx={}", idx);
742 fn read_enum_struct_variant_field<T, F>(&mut self,
746 -> DecodeResult<T> where
747 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
749 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
753 fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T> where
754 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
756 debug!("read_struct(name={})", name);
760 fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T> where
761 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
763 debug!("read_struct_field(name={}, idx={})", name, idx);
767 fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T> where
768 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
770 debug!("read_tuple()");
771 self.read_seq(move |d, len| {
772 if len == tuple_len {
775 Err(Expected(format!("Expected tuple of length `{}`, \
776 found tuple of length `{}`", tuple_len, len)))
781 fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
782 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
784 debug!("read_tuple_arg(idx={})", idx);
785 self.read_seq_elt(idx, f)
788 fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T> where
789 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
791 debug!("read_tuple_struct(name={})", name);
792 self.read_tuple(len, f)
795 fn read_tuple_struct_arg<T, F>(&mut self,
798 -> DecodeResult<T> where
799 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
801 debug!("read_tuple_struct_arg(idx={})", idx);
802 self.read_tuple_arg(idx, f)
805 fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
806 F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
808 debug!("read_option()");
809 self.read_enum("Option", move |this| {
810 this.read_enum_variant(&["None", "Some"], move |this, idx| {
815 Err(Expected(format!("Expected None or Some")))
822 fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
823 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
825 debug!("read_seq()");
826 self.push_doc(EsVec, move |d| {
827 let len = try!(d._next_sub());
828 debug!(" len={}", len);
833 fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
834 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
836 debug!("read_seq_elt(idx={})", idx);
837 self.push_doc(EsVecElt, f)
840 fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
841 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
843 debug!("read_map()");
844 self.push_doc(EsMap, move |d| {
845 let len = try!(d._next_sub());
846 debug!(" len={}", len);
851 fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
852 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
854 debug!("read_map_elt_key(idx={})", idx);
855 self.push_doc(EsMapKey, f)
858 fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
859 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
861 debug!("read_map_elt_val(idx={})", idx);
862 self.push_doc(EsMapVal, f)
865 fn error(&mut self, err: &str) -> Error {
866 ApplicationError(err.to_string())
873 use std::io::prelude::*;
874 use std::io::{self, SeekFrom, Cursor};
875 use std::slice::bytes;
877 use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
878 EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
879 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
880 EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
885 pub type EncodeResult = io::Result<()>;
888 pub struct Encoder<'a> {
889 pub writer: &'a mut Cursor<Vec<u8>>,
890 size_positions: Vec<u64>,
891 relax_limit: u64, // do not move encoded bytes before this position
894 fn write_tag<W: Write>(w: &mut W, n: usize) -> EncodeResult {
896 w.write_all(&[n as u8])
897 } else if 0x100 <= n && n < NUM_TAGS {
898 w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
900 Err(io::Error::new(io::ErrorKind::Other,
901 &format!("invalid tag: {}", n)[..]))
905 fn write_sized_vuint<W: Write>(w: &mut W, n: usize, size: usize) -> EncodeResult {
907 1 => w.write_all(&[0x80 | (n as u8)]),
908 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]),
909 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8,
911 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
912 (n >> 8) as u8, n as u8]),
913 _ => Err(io::Error::new(io::ErrorKind::Other,
914 &format!("isize too big: {}", n)[..]))
918 pub fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
919 if n < 0x7f { return write_sized_vuint(w, n, 1); }
920 if n < 0x4000 { return write_sized_vuint(w, n, 2); }
921 if n < 0x200000 { return write_sized_vuint(w, n, 3); }
922 if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
923 Err(io::Error::new(io::ErrorKind::Other,
924 &format!("isize too big: {}", n)[..]))
927 impl<'a> Encoder<'a> {
928 pub fn new(w: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
931 size_positions: vec!(),
936 pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
937 debug!("Start tag {:?}", tag_id);
938 assert!(tag_id >= NUM_IMPLICIT_TAGS);
940 // Write the enum ID:
941 try!(write_tag(self.writer, tag_id));
943 // Write a placeholder four-byte size.
944 let cur_pos = try!(self.writer.seek(SeekFrom::Current(0)));
945 self.size_positions.push(cur_pos);
946 let zeroes: &[u8] = &[0, 0, 0, 0];
947 self.writer.write_all(zeroes)
950 pub fn end_tag(&mut self) -> EncodeResult {
951 let last_size_pos = self.size_positions.pop().unwrap();
952 let cur_pos = try!(self.writer.seek(SeekFrom::Current(0)));
953 try!(self.writer.seek(SeekFrom::Start(last_size_pos)));
954 let size = (cur_pos - last_size_pos - 4) as usize;
956 // relax the size encoding for small tags (bigger tags are costly to move).
957 // we should never try to move the stable positions, however.
958 const RELAX_MAX_SIZE: usize = 0x100;
959 if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit {
960 // we can't alter the buffer in place, so have a temporary buffer
961 let mut buf = [0u8; RELAX_MAX_SIZE];
963 let last_size_pos = last_size_pos as usize;
964 let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as usize];
965 bytes::copy_memory(data, &mut buf);
968 // overwrite the size and data and continue
969 try!(write_vuint(self.writer, size));
970 try!(self.writer.write_all(&buf[..size]));
972 // overwrite the size with an overlong encoding and skip past the data
973 try!(write_sized_vuint(self.writer, size, 4));
974 try!(self.writer.seek(SeekFrom::Start(cur_pos)));
977 debug!("End tag (size = {:?})", size);
981 pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult where
982 F: FnOnce() -> EncodeResult,
984 try!(self.start_tag(tag_id));
989 pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
990 assert!(tag_id >= NUM_IMPLICIT_TAGS);
991 try!(write_tag(self.writer, tag_id));
992 try!(write_vuint(self.writer, b.len()));
993 self.writer.write_all(b)
996 pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
997 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
998 // tagged integers are emitted in big-endian, with no
1000 let leading_zero_bytes = v.leading_zeros()/8;
1001 self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..])
1005 pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult {
1006 self.wr_tagged_u64(tag_id, v as u64)
1010 pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
1011 self.wr_tagged_u64(tag_id, v as u64)
1015 pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1016 self.wr_tagged_bytes(tag_id, &[v])
1020 pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
1021 self.wr_tagged_u64(tag_id, v as u64)
1025 pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
1026 self.wr_tagged_u32(tag_id, v as u32)
1030 pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
1031 self.wr_tagged_u16(tag_id, v as u16)
1035 pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
1036 self.wr_tagged_bytes(tag_id, &[v as u8])
1039 pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
1040 self.wr_tagged_bytes(tag_id, v.as_bytes())
1043 // for auto-serialization
1044 fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
1045 try!(write_tag(self.writer, tag_id));
1046 self.writer.write_all(b)
1049 fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
1050 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
1051 self.wr_tagged_raw_bytes(tag_id, &bytes)
1054 fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult{
1055 let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
1056 self.wr_tagged_raw_bytes(tag_id, &bytes)
1059 fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
1060 let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
1061 self.wr_tagged_raw_bytes(tag_id, &bytes)
1064 fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1065 self.wr_tagged_raw_bytes(tag_id, &[v])
1068 fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
1069 self.wr_tagged_raw_u64(tag_id, v as u64)
1072 fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
1073 self.wr_tagged_raw_u32(tag_id, v as u32)
1076 fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
1077 self.wr_tagged_raw_u16(tag_id, v as u16)
1080 fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
1081 self.wr_tagged_raw_bytes(tag_id, &[v as u8])
1084 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
1085 debug!("Write {:?} bytes", b.len());
1086 self.writer.write_all(b)
1089 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
1090 debug!("Write str: {:?}", s);
1091 self.writer.write_all(s.as_bytes())
1094 /// Returns the current position while marking it stable, i.e.
1095 /// generated bytes so far wouldn't be affected by relaxation.
1096 pub fn mark_stable_position(&mut self) -> u64 {
1097 let pos = self.writer.seek(SeekFrom::Current(0)).unwrap();
1098 if self.relax_limit < pos {
1099 self.relax_limit = pos;
1105 impl<'a> Encoder<'a> {
1106 // used internally to emit things like the vector length and so on
1107 fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
1108 if v as u8 as usize == v {
1109 self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
1110 } else if v as u32 as usize == v {
1111 self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
1113 Err(io::Error::new(io::ErrorKind::Other,
1114 &format!("length or variant id too big: {}",
1119 pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
1120 F: FnOnce(&mut Encoder) -> EncodeResult,
1122 try!(self.start_tag(EsOpaque as usize));
1128 impl<'a> serialize::Encoder for Encoder<'a> {
1129 type Error = io::Error;
1131 fn emit_nil(&mut self) -> EncodeResult {
1135 fn emit_uint(&mut self, v: usize) -> EncodeResult {
1136 self.emit_u64(v as u64)
1138 fn emit_u64(&mut self, v: u64) -> EncodeResult {
1139 if v as u32 as u64 == v {
1140 self.emit_u32(v as u32)
1142 self.wr_tagged_raw_u64(EsU64 as usize, v)
1145 fn emit_u32(&mut self, v: u32) -> EncodeResult {
1146 if v as u16 as u32 == v {
1147 self.emit_u16(v as u16)
1149 self.wr_tagged_raw_u32(EsU32 as usize, v)
1152 fn emit_u16(&mut self, v: u16) -> EncodeResult {
1153 if v as u8 as u16 == v {
1154 self.emit_u8(v as u8)
1156 self.wr_tagged_raw_u16(EsU16 as usize, v)
1159 fn emit_u8(&mut self, v: u8) -> EncodeResult {
1160 self.wr_tagged_raw_u8(EsU8 as usize, v)
1163 fn emit_int(&mut self, v: isize) -> EncodeResult {
1164 self.emit_i64(v as i64)
1166 fn emit_i64(&mut self, v: i64) -> EncodeResult {
1167 if v as i32 as i64 == v {
1168 self.emit_i32(v as i32)
1170 self.wr_tagged_raw_i64(EsI64 as usize, v)
1173 fn emit_i32(&mut self, v: i32) -> EncodeResult {
1174 if v as i16 as i32 == v {
1175 self.emit_i16(v as i16)
1177 self.wr_tagged_raw_i32(EsI32 as usize, v)
1180 fn emit_i16(&mut self, v: i16) -> EncodeResult {
1181 if v as i8 as i16 == v {
1182 self.emit_i8(v as i8)
1184 self.wr_tagged_raw_i16(EsI16 as usize, v)
1187 fn emit_i8(&mut self, v: i8) -> EncodeResult {
1188 self.wr_tagged_raw_i8(EsI8 as usize, v)
1191 fn emit_bool(&mut self, v: bool) -> EncodeResult {
1192 self.wr_tagged_raw_u8(EsBool as usize, v as u8)
1195 fn emit_f64(&mut self, v: f64) -> EncodeResult {
1196 let bits = unsafe { mem::transmute(v) };
1197 self.wr_tagged_raw_u64(EsF64 as usize, bits)
1199 fn emit_f32(&mut self, v: f32) -> EncodeResult {
1200 let bits = unsafe { mem::transmute(v) };
1201 self.wr_tagged_raw_u32(EsF32 as usize, bits)
1203 fn emit_char(&mut self, v: char) -> EncodeResult {
1204 self.wr_tagged_raw_u32(EsChar as usize, v as u32)
1207 fn emit_str(&mut self, v: &str) -> EncodeResult {
1208 self.wr_tagged_str(EsStr as usize, v)
1211 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
1212 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1214 try!(self.start_tag(EsEnum as usize));
1219 fn emit_enum_variant<F>(&mut self,
1223 f: F) -> EncodeResult where
1224 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1226 try!(self._emit_tagged_sub(v_id));
1230 fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult where
1231 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1236 fn emit_enum_struct_variant<F>(&mut self,
1240 f: F) -> EncodeResult where
1241 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1243 self.emit_enum_variant(v_name, v_id, cnt, f)
1246 fn emit_enum_struct_variant_field<F>(&mut self,
1249 f: F) -> EncodeResult where
1250 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1252 self.emit_enum_variant_arg(idx, f)
1255 fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where
1256 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1261 fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where
1262 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1267 fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
1268 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1270 self.emit_seq(len, f)
1272 fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1273 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1275 self.emit_seq_elt(idx, f)
1278 fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
1279 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1281 self.emit_seq(len, f)
1283 fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1284 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1286 self.emit_seq_elt(idx, f)
1289 fn emit_option<F>(&mut self, f: F) -> EncodeResult where
1290 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1292 self.emit_enum("Option", f)
1294 fn emit_option_none(&mut self) -> EncodeResult {
1295 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1297 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
1298 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1301 self.emit_enum_variant("Some", 1, 1, f)
1304 fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
1305 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1308 // empty vector optimization
1309 return self.wr_tagged_bytes(EsVec as usize, &[]);
1312 try!(self.start_tag(EsVec as usize));
1313 try!(self._emit_tagged_sub(len));
1318 fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1319 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1322 try!(self.start_tag(EsVecElt as usize));
1327 fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
1328 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1331 // empty map optimization
1332 return self.wr_tagged_bytes(EsMap as usize, &[]);
1335 try!(self.start_tag(EsMap as usize));
1336 try!(self._emit_tagged_sub(len));
1341 fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1342 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1345 try!(self.start_tag(EsMapKey as usize));
1350 fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1351 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1353 try!(self.start_tag(EsMapVal as usize));
1360 // ___________________________________________________________________________
1365 use super::{Doc, reader, writer};
1367 use serialize::{Encodable, Decodable};
1369 use std::io::Cursor;
1372 fn test_vuint_at() {
1380 0x10, 0x00, 0x00, 0x00,
1381 0x1f, 0xff, 0xff, 0xff
1384 let mut res: reader::Res;
1387 res = reader::vuint_at(data, 0).unwrap();
1388 assert_eq!(res.val, 0);
1389 assert_eq!(res.next, 1);
1390 res = reader::vuint_at(data, res.next).unwrap();
1391 assert_eq!(res.val, (1 << 7) - 1);
1392 assert_eq!(res.next, 2);
1395 res = reader::vuint_at(data, res.next).unwrap();
1396 assert_eq!(res.val, 0);
1397 assert_eq!(res.next, 4);
1398 res = reader::vuint_at(data, res.next).unwrap();
1399 assert_eq!(res.val, (1 << 14) - 1);
1400 assert_eq!(res.next, 6);
1403 res = reader::vuint_at(data, res.next).unwrap();
1404 assert_eq!(res.val, 0);
1405 assert_eq!(res.next, 9);
1406 res = reader::vuint_at(data, res.next).unwrap();
1407 assert_eq!(res.val, (1 << 21) - 1);
1408 assert_eq!(res.next, 12);
1411 res = reader::vuint_at(data, res.next).unwrap();
1412 assert_eq!(res.val, 0);
1413 assert_eq!(res.next, 16);
1414 res = reader::vuint_at(data, res.next).unwrap();
1415 assert_eq!(res.val, (1 << 28) - 1);
1416 assert_eq!(res.next, 20);
1420 fn test_option_int() {
1421 fn test_v(v: Option<isize>) {
1422 debug!("v == {:?}", v);
1423 let mut wr = Cursor::new(Vec::new());
1425 let mut rbml_w = writer::Encoder::new(&mut wr);
1426 let _ = v.encode(&mut rbml_w);
1428 let rbml_doc = Doc::new(wr.get_ref());
1429 let mut deser = reader::Decoder::new(rbml_doc);
1430 let v1 = Decodable::decode(&mut deser).unwrap();
1431 debug!("v1 == {:?}", v1);
1443 #![allow(non_snake_case)]
1448 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1449 let data = (0..4*100).map(|i| {
1454 }).collect::<Vec<_>>();
1458 while i < data.len() {
1459 sum += reader::vuint_at(&data, i).unwrap().val;
1466 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1467 let data = (0..4*100+1).map(|i| {
1472 }).collect::<Vec<_>>();
1476 while i < data.len() {
1477 sum += reader::vuint_at(&data, i).unwrap().val;
1484 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1485 let data = (0..4*100).map(|i| {
1491 }).collect::<Vec<_>>();
1495 while i < data.len() {
1496 sum += reader::vuint_at(&data, i).unwrap().val;
1503 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
1504 let data = (0..4*100+1).map(|i| {
1510 }).collect::<Vec<_>>();
1514 while i < data.len() {
1515 sum += reader::vuint_at(&data, i).unwrap().val;