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 int, 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 interchangably.
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")]
119 #![crate_type = "rlib"]
120 #![crate_type = "dylib"]
121 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
122 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
123 html_root_url = "http://doc.rust-lang.org/nightly/",
124 html_playground_url = "http://play.rust-lang.org/")]
126 #![feature(collections)]
128 #![feature(int_uint)]
130 #![feature(rustc_private)]
131 #![feature(staged_api)]
133 #![cfg_attr(test, feature(test))]
135 extern crate serialize;
136 #[macro_use] extern crate log;
138 #[cfg(test)] extern crate test;
140 pub use self::EbmlEncoderTag::*;
141 pub use self::Error::*;
148 /// Common data structures
149 #[derive(Clone, Copy)]
156 impl<'doc> Doc<'doc> {
157 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
158 Doc { data: data, start: 0, end: data.len() }
161 pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
162 reader::get_doc(*self, tag)
165 pub fn is_empty(&self) -> bool {
166 self.start == self.end
169 pub fn as_str_slice<'a>(&'a self) -> &'a str {
170 str::from_utf8(&self.data[self.start..self.end]).unwrap()
173 pub fn as_str(&self) -> String {
174 self.as_str_slice().to_string()
178 pub struct TaggedDoc<'a> {
183 #[derive(Copy, Debug)]
184 pub enum EbmlEncoderTag {
185 // tags 00..1f are reserved for auto-serialization.
186 // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
188 EsU8 = 0x00, // + 1 byte
189 EsU16 = 0x01, // + 2 bytes
190 EsU32 = 0x02, // + 4 bytes
191 EsU64 = 0x03, // + 8 bytes
192 EsI8 = 0x04, // + 1 byte
193 EsI16 = 0x05, // + 2 bytes
194 EsI32 = 0x06, // + 4 bytes
195 EsI64 = 0x07, // + 8 bytes
196 EsBool = 0x08, // + 1 byte
197 EsChar = 0x09, // + 4 bytes
198 EsF32 = 0x0a, // + 4 bytes
199 EsF64 = 0x0b, // + 8 bytes
200 EsSub8 = 0x0c, // + 1 byte
201 EsSub32 = 0x0d, // + 4 bytes
202 // 0x0e and 0x0f are reserved
205 EsEnum = 0x11, // encodes the variant id as the first EsSub*
206 EsVec = 0x12, // encodes the # of elements as the first EsSub*
208 EsMap = 0x14, // encodes the # of pairs as the first EsSub*
214 const NUM_TAGS: uint = 0x1000;
215 const NUM_IMPLICIT_TAGS: uint = 0x0e;
217 static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
231 IoError(std::old_io::IoError),
232 ApplicationError(String)
235 impl fmt::Display for Error {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 // FIXME: this should be a more useful display form
238 fmt::Debug::fmt(self, f)
241 // --------------------------------------
247 use std::mem::transmute;
249 use std::slice::bytes;
253 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
254 EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
255 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
256 EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
257 Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
259 pub type DecodeResult<T> = Result<T, Error>;
262 macro_rules! try_or {
263 ($e:expr, $r:expr) => (
267 debug!("ignored error: {:?}", e);
280 pub fn tag_at(data: &[u8], start: uint) -> DecodeResult<Res> {
281 let v = data[start] as uint;
283 Ok(Res { val: v, next: start + 1 })
285 Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as uint, next: start + 2 })
287 // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
293 fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
296 return Ok(Res {val: (a & 0x7f) as uint, next: start + 1});
299 return Ok(Res {val: ((a & 0x3f) as uint) << 8 |
300 (data[start + 1] as uint),
304 return Ok(Res {val: ((a & 0x1f) as uint) << 16 |
305 (data[start + 1] as uint) << 8 |
306 (data[start + 2] as uint),
310 return Ok(Res {val: ((a & 0x0f) as uint) << 24 |
311 (data[start + 1] as uint) << 16 |
312 (data[start + 2] as uint) << 8 |
313 (data[start + 3] as uint),
316 Err(IntTooBig(a as uint))
319 pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
320 if data.len() - start < 4 {
321 return vuint_at_slow(data, start);
324 // Lookup table for parsing EBML Element IDs as per
325 // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by
326 // reading a big endian u32 positioned at data[start]. Using the four
327 // most significant bits of the u32 we lookup in the table below how
328 // the element ID should be derived from it.
330 // The table stores tuples (shift, mask) where shift is the number the
331 // u32 should be right shifted with and mask is the value the right
332 // shifted value should be masked with. If for example the most
333 // significant bit is set this means it's a class A ID and the u32
334 // should be right shifted with 24 and masked with 0x7f. Therefore we
335 // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most
336 // significant bit is set).
338 // By storing the number of shifts and masks in a table instead of
339 // checking in order if the most significant bit is set, the second
340 // most significant bit is set etc. we can replace up to three
341 // "and+branch" with a single table lookup which gives us a measured
342 // speedup of around 2x on x86_64.
343 static SHIFT_MASK_TABLE: [(uint, u32); 16] = [
344 (0, 0x0), (0, 0x0fffffff),
345 (8, 0x1fffff), (8, 0x1fffff),
346 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
347 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
348 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
352 let ptr = data.as_ptr().offset(start as int) as *const u32;
353 let val = Int::from_be(*ptr);
355 let i = (val >> 28) as uint;
356 let (shift, mask) = SHIFT_MASK_TABLE[i];
358 val: ((val >> shift) & mask) as uint,
359 next: start + (((32 - shift) >> 3) as uint)
364 pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult<Res> {
365 if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 {
366 Ok(Res { val: TAG_IMPLICIT_LEN[tag.val] as uint, next: tag.next })
368 vuint_at(data, tag.next)
372 pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
373 let elt_tag = try!(tag_at(data, start));
374 let elt_size = try!(tag_len_at(data, elt_tag));
375 let end = elt_size.next + elt_size.val;
378 doc: Doc { data: data, start: elt_size.next, end: end }
382 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
383 let mut pos = d.start;
385 let elt_tag = try_or!(tag_at(d.data, pos), None);
386 let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
387 pos = elt_size.next + elt_size.val;
388 if elt_tag.val == tg {
389 return Some(Doc { data: d.data, start: elt_size.next,
396 pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
397 match maybe_get_doc(d, tg) {
400 error!("failed to find block with tag {:?}", tg);
406 pub fn docs<F>(d: Doc, mut it: F) -> bool where
407 F: FnMut(uint, Doc) -> bool,
409 let mut pos = d.start;
411 let elt_tag = try_or!(tag_at(d.data, pos), false);
412 let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
413 pos = elt_size.next + elt_size.val;
414 let doc = Doc { data: d.data, start: elt_size.next, end: pos };
415 if !it(elt_tag.val, doc) {
422 pub fn tagged_docs<F>(d: Doc, tg: uint, mut it: F) -> bool where
423 F: FnMut(Doc) -> bool,
425 let mut pos = d.start;
427 let elt_tag = try_or!(tag_at(d.data, pos), false);
428 let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
429 pos = elt_size.next + elt_size.val;
430 if elt_tag.val == tg {
431 let doc = Doc { data: d.data, start: elt_size.next,
441 pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
442 F: FnOnce(&[u8]) -> T,
444 f(&d.data[d.start..d.end])
448 pub fn doc_as_u8(d: Doc) -> u8 {
449 assert_eq!(d.end, d.start + 1);
453 pub fn doc_as_u16(d: Doc) -> u16 {
454 assert_eq!(d.end, d.start + 2);
456 bytes::copy_memory(&mut b, &d.data[d.start..d.end]);
457 unsafe { (*(b.as_ptr() as *const u16)).to_be() }
460 pub fn doc_as_u32(d: Doc) -> u32 {
461 assert_eq!(d.end, d.start + 4);
463 bytes::copy_memory(&mut b, &d.data[d.start..d.end]);
464 unsafe { (*(b.as_ptr() as *const u32)).to_be() }
467 pub fn doc_as_u64(d: Doc) -> u64 {
468 assert_eq!(d.end, d.start + 8);
470 bytes::copy_memory(&mut b, &d.data[d.start..d.end]);
471 unsafe { (*(b.as_ptr() as *const u64)).to_be() }
474 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
475 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
476 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
477 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
479 pub struct Decoder<'a> {
484 impl<'doc> Decoder<'doc> {
485 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
492 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
493 debug!(". next_doc(exp_tag={:?})", exp_tag);
494 if self.pos >= self.parent.end {
495 return Err(Expected(format!("no more documents in \
498 let TaggedDoc { tag: r_tag, doc: r_doc } =
499 try!(doc_at(self.parent.data, self.pos));
500 debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}",
507 if r_tag != (exp_tag as uint) {
508 return Err(Expected(format!("expected EBML doc with tag {:?} but \
509 found tag {:?}", exp_tag, r_tag)));
511 if r_doc.end > self.parent.end {
512 return Err(Expected(format!("invalid EBML, child extends to \
513 {:#x}, parent to {:#x}",
514 r_doc.end, self.parent.end)));
516 self.pos = r_doc.end;
520 fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
521 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
523 let d = try!(self.next_doc(exp_tag));
524 let old_parent = self.parent;
525 let old_pos = self.pos;
528 let r = try!(f(self));
529 self.parent = old_parent;
534 fn _next_sub(&mut self) -> DecodeResult<uint> {
535 // empty vector/map optimization
536 if self.parent.is_empty() {
540 let TaggedDoc { tag: r_tag, doc: r_doc } =
541 try!(doc_at(self.parent.data, self.pos));
542 let r = if r_tag == (EsSub8 as uint) {
543 doc_as_u8(r_doc) as uint
544 } else if r_tag == (EsSub32 as uint) {
545 doc_as_u32(r_doc) as uint
547 return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
548 found tag {:?}", EsSub8, EsSub32, r_tag)));
550 if r_doc.end > self.parent.end {
551 return Err(Expected(format!("invalid EBML, child extends to \
552 {:#x}, parent to {:#x}",
553 r_doc.end, self.parent.end)));
555 self.pos = r_doc.end;
556 debug!("_next_sub result={:?}", r);
560 // variable-length unsigned integer with different tags.
561 // `first_tag` should be a tag for u8 or i8.
562 // `last_tag` should be the largest allowed integer tag with the matching signedness.
563 // all tags between them should be valid, in the order of u8, u16, u32 and u64.
564 fn _next_int(&mut self,
565 first_tag: EbmlEncoderTag,
566 last_tag: EbmlEncoderTag) -> DecodeResult<u64> {
567 if self.pos >= self.parent.end {
568 return Err(Expected(format!("no more documents in \
572 let TaggedDoc { tag: r_tag, doc: r_doc } =
573 try!(doc_at(self.parent.data, self.pos));
574 let r = if first_tag as uint <= r_tag && r_tag <= last_tag as uint {
575 match r_tag - first_tag as uint {
576 0 => doc_as_u8(r_doc) as u64,
577 1 => doc_as_u16(r_doc) as u64,
578 2 => doc_as_u32(r_doc) as u64,
579 3 => doc_as_u64(r_doc) as u64,
583 return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
584 found tag {:?}", first_tag, last_tag, r_tag)));
586 if r_doc.end > self.parent.end {
587 return Err(Expected(format!("invalid EBML, child extends to \
588 {:#x}, parent to {:#x}",
589 r_doc.end, self.parent.end)));
591 self.pos = r_doc.end;
592 debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
596 pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
597 F: FnOnce(&mut Decoder, Doc) -> DecodeResult<R>,
599 let doc = try!(self.next_doc(EsOpaque));
601 let (old_parent, old_pos) = (self.parent, self.pos);
603 self.pos = doc.start;
605 let result = try!(op(self, doc));
607 self.parent = old_parent;
613 impl<'doc> serialize::Decoder for Decoder<'doc> {
615 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
617 fn read_u64(&mut self) -> DecodeResult<u64> { self._next_int(EsU8, EsU64) }
618 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(try!(self._next_int(EsU8, EsU32)) as u32) }
619 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(try!(self._next_int(EsU8, EsU16)) as u16) }
620 fn read_u8(&mut self) -> DecodeResult<u8> { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) }
621 fn read_uint(&mut self) -> DecodeResult<uint> {
622 let v = try!(self._next_int(EsU8, EsU64));
623 if v > (::std::usize::MAX as u64) {
624 Err(IntTooBig(v as uint))
630 fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self._next_int(EsI8, EsI64)) as i64) }
631 fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self._next_int(EsI8, EsI32)) as i32) }
632 fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self._next_int(EsI8, EsI16)) as i16) }
633 fn read_i8(&mut self) -> DecodeResult<i8> { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) }
634 fn read_int(&mut self) -> DecodeResult<int> {
635 let v = try!(self._next_int(EsI8, EsI64)) as i64;
636 if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
637 debug!("FIXME \\#6122: Removing this makes this function miscompile");
638 Err(IntTooBig(v as uint))
644 fn read_bool(&mut self) -> DecodeResult<bool> {
645 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
648 fn read_f64(&mut self) -> DecodeResult<f64> {
649 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
650 Ok(unsafe { transmute(bits) })
652 fn read_f32(&mut self) -> DecodeResult<f32> {
653 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
654 Ok(unsafe { transmute(bits) })
656 fn read_char(&mut self) -> DecodeResult<char> {
657 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
659 fn read_str(&mut self) -> DecodeResult<String> {
660 Ok(try!(self.next_doc(EsStr)).as_str())
664 fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
665 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
667 debug!("read_enum({})", name);
669 let doc = try!(self.next_doc(EsEnum));
671 let (old_parent, old_pos) = (self.parent, self.pos);
673 self.pos = self.parent.start;
675 let result = try!(f(self));
677 self.parent = old_parent;
682 fn read_enum_variant<T, F>(&mut self, _: &[&str],
683 mut f: F) -> DecodeResult<T>
684 where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
686 debug!("read_enum_variant()");
687 let idx = try!(self._next_sub());
688 debug!(" idx={}", idx);
693 fn read_enum_variant_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
694 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
696 debug!("read_enum_variant_arg(idx={})", idx);
700 fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
701 mut f: F) -> DecodeResult<T>
702 where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
704 debug!("read_enum_struct_variant()");
705 let idx = try!(self._next_sub());
706 debug!(" idx={}", idx);
711 fn read_enum_struct_variant_field<T, F>(&mut self,
715 -> DecodeResult<T> where
716 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
718 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
722 fn read_struct<T, F>(&mut self, name: &str, _: uint, f: F) -> DecodeResult<T> where
723 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
725 debug!("read_struct(name={})", name);
729 fn read_struct_field<T, F>(&mut self, name: &str, idx: uint, f: F) -> DecodeResult<T> where
730 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
732 debug!("read_struct_field(name={}, idx={})", name, idx);
736 fn read_tuple<T, F>(&mut self, tuple_len: uint, f: F) -> DecodeResult<T> where
737 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
739 debug!("read_tuple()");
740 self.read_seq(move |d, len| {
741 if len == tuple_len {
744 Err(Expected(format!("Expected tuple of length `{}`, \
745 found tuple of length `{}`", tuple_len, len)))
750 fn read_tuple_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
751 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
753 debug!("read_tuple_arg(idx={})", idx);
754 self.read_seq_elt(idx, f)
757 fn read_tuple_struct<T, F>(&mut self, name: &str, len: uint, f: F) -> DecodeResult<T> where
758 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
760 debug!("read_tuple_struct(name={})", name);
761 self.read_tuple(len, f)
764 fn read_tuple_struct_arg<T, F>(&mut self,
767 -> DecodeResult<T> where
768 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
770 debug!("read_tuple_struct_arg(idx={})", idx);
771 self.read_tuple_arg(idx, f)
774 fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
775 F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
777 debug!("read_option()");
778 self.read_enum("Option", move |this| {
779 this.read_enum_variant(&["None", "Some"], move |this, idx| {
784 Err(Expected(format!("Expected None or Some")))
791 fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
792 F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
794 debug!("read_seq()");
795 self.push_doc(EsVec, move |d| {
796 let len = try!(d._next_sub());
797 debug!(" len={}", len);
802 fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
803 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
805 debug!("read_seq_elt(idx={})", idx);
806 self.push_doc(EsVecElt, f)
809 fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
810 F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
812 debug!("read_map()");
813 self.push_doc(EsMap, move |d| {
814 let len = try!(d._next_sub());
815 debug!(" len={}", len);
820 fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
821 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
823 debug!("read_map_elt_key(idx={})", idx);
824 self.push_doc(EsMapKey, f)
827 fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
828 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
830 debug!("read_map_elt_val(idx={})", idx);
831 self.push_doc(EsMapVal, f)
834 fn error(&mut self, err: &str) -> Error {
835 ApplicationError(err.to_string())
843 use std::old_io::{Writer, Seek};
845 use std::slice::bytes;
846 use std::num::ToPrimitive;
848 use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
849 EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
850 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
851 EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
852 use super::io::SeekableMemWriter;
857 pub type EncodeResult = old_io::IoResult<()>;
860 pub struct Encoder<'a> {
861 pub writer: &'a mut SeekableMemWriter,
862 size_positions: Vec<uint>,
863 relax_limit: u64, // do not move encoded bytes before this position
866 fn write_tag<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
868 w.write_all(&[n as u8])
869 } else if 0x100 <= n && n < NUM_TAGS {
870 w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
872 Err(old_io::IoError {
873 kind: old_io::OtherIoError,
875 detail: Some(format!("{}", n))
880 fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
882 1 => w.write_all(&[0x80 | (n as u8)]),
883 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]),
884 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8,
886 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
887 (n >> 8) as u8, n as u8]),
888 _ => Err(old_io::IoError {
889 kind: old_io::OtherIoError,
891 detail: Some(format!("{}", n))
896 fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
897 if n < 0x7f { return write_sized_vuint(w, n, 1); }
898 if n < 0x4000 { return write_sized_vuint(w, n, 2); }
899 if n < 0x200000 { return write_sized_vuint(w, n, 3); }
900 if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
901 Err(old_io::IoError {
902 kind: old_io::OtherIoError,
904 detail: Some(format!("{}", n))
908 impl<'a> Encoder<'a> {
909 pub fn new(w: &'a mut SeekableMemWriter) -> Encoder<'a> {
912 size_positions: vec!(),
917 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
918 pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
920 writer: mem::transmute_copy(&self.writer),
921 size_positions: self.size_positions.clone(),
922 relax_limit: self.relax_limit,
926 pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
927 debug!("Start tag {:?}", tag_id);
928 assert!(tag_id >= NUM_IMPLICIT_TAGS);
930 // Write the enum ID:
931 try!(write_tag(self.writer, tag_id));
933 // Write a placeholder four-byte size.
934 self.size_positions.push(try!(self.writer.tell()) as uint);
935 let zeroes: &[u8] = &[0, 0, 0, 0];
936 self.writer.write_all(zeroes)
939 pub fn end_tag(&mut self) -> EncodeResult {
940 let last_size_pos = self.size_positions.pop().unwrap();
941 let cur_pos = try!(self.writer.tell());
942 try!(self.writer.seek(last_size_pos as i64, old_io::SeekSet));
943 let size = cur_pos as uint - last_size_pos - 4;
945 // relax the size encoding for small tags (bigger tags are costly to move).
946 // we should never try to move the stable positions, however.
947 const RELAX_MAX_SIZE: uint = 0x100;
948 if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit as uint {
949 // we can't alter the buffer in place, so have a temporary buffer
950 let mut buf = [0u8; RELAX_MAX_SIZE];
952 let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as uint];
953 bytes::copy_memory(&mut buf, data);
956 // overwrite the size and data and continue
957 try!(write_vuint(self.writer, size));
958 try!(self.writer.write_all(&buf[..size]));
960 // overwrite the size with an overlong encoding and skip past the data
961 try!(write_sized_vuint(self.writer, size, 4));
962 try!(self.writer.seek(cur_pos as i64, old_io::SeekSet));
965 debug!("End tag (size = {:?})", size);
969 pub fn wr_tag<F>(&mut self, tag_id: uint, blk: F) -> EncodeResult where
970 F: FnOnce() -> EncodeResult,
972 try!(self.start_tag(tag_id));
977 pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
978 assert!(tag_id >= NUM_IMPLICIT_TAGS);
979 try!(write_tag(self.writer, tag_id));
980 try!(write_vuint(self.writer, b.len()));
981 self.writer.write_all(b)
984 pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
985 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
986 self.wr_tagged_bytes(tag_id, &bytes)
989 pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
990 let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
991 self.wr_tagged_bytes(tag_id, &bytes)
994 pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
995 let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
996 self.wr_tagged_bytes(tag_id, &bytes)
999 pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
1000 self.wr_tagged_bytes(tag_id, &[v])
1003 pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
1004 self.wr_tagged_u64(tag_id, v as u64)
1007 pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
1008 self.wr_tagged_u32(tag_id, v as u32)
1011 pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
1012 self.wr_tagged_u16(tag_id, v as u16)
1015 pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
1016 self.wr_tagged_bytes(tag_id, &[v as u8])
1019 pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
1020 self.wr_tagged_bytes(tag_id, v.as_bytes())
1023 // for auto-serialization
1024 fn wr_tagged_raw_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
1025 try!(write_tag(self.writer, tag_id));
1026 self.writer.write_all(b)
1029 fn wr_tagged_raw_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
1030 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
1031 self.wr_tagged_raw_bytes(tag_id, &bytes)
1034 fn wr_tagged_raw_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
1035 let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
1036 self.wr_tagged_raw_bytes(tag_id, &bytes)
1039 fn wr_tagged_raw_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
1040 let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
1041 self.wr_tagged_raw_bytes(tag_id, &bytes)
1044 fn wr_tagged_raw_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
1045 self.wr_tagged_raw_bytes(tag_id, &[v])
1048 fn wr_tagged_raw_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
1049 self.wr_tagged_raw_u64(tag_id, v as u64)
1052 fn wr_tagged_raw_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
1053 self.wr_tagged_raw_u32(tag_id, v as u32)
1056 fn wr_tagged_raw_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
1057 self.wr_tagged_raw_u16(tag_id, v as u16)
1060 fn wr_tagged_raw_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
1061 self.wr_tagged_raw_bytes(tag_id, &[v as u8])
1064 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
1065 debug!("Write {:?} bytes", b.len());
1066 self.writer.write_all(b)
1069 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
1070 debug!("Write str: {:?}", s);
1071 self.writer.write_all(s.as_bytes())
1074 /// Returns the current position while marking it stable, i.e.
1075 /// generated bytes so far woundn't be affected by relaxation.
1076 pub fn mark_stable_position(&mut self) -> u64 {
1077 let pos = self.writer.tell().unwrap();
1078 if self.relax_limit < pos {
1079 self.relax_limit = pos;
1085 impl<'a> Encoder<'a> {
1086 // used internally to emit things like the vector length and so on
1087 fn _emit_tagged_sub(&mut self, v: uint) -> EncodeResult {
1088 if let Some(v) = v.to_u8() {
1089 self.wr_tagged_raw_u8(EsSub8 as uint, v)
1090 } else if let Some(v) = v.to_u32() {
1091 self.wr_tagged_raw_u32(EsSub32 as uint, v)
1093 Err(old_io::IoError {
1094 kind: old_io::OtherIoError,
1095 desc: "length or variant id too big",
1096 detail: Some(format!("{}", v))
1101 pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
1102 F: FnOnce(&mut Encoder) -> EncodeResult,
1104 try!(self.start_tag(EsOpaque as uint));
1110 impl<'a> serialize::Encoder for Encoder<'a> {
1111 type Error = old_io::IoError;
1113 fn emit_nil(&mut self) -> EncodeResult {
1117 fn emit_uint(&mut self, v: uint) -> EncodeResult {
1118 self.emit_u64(v as u64)
1120 fn emit_u64(&mut self, v: u64) -> EncodeResult {
1122 Some(v) => self.emit_u32(v),
1123 None => self.wr_tagged_raw_u64(EsU64 as uint, v)
1126 fn emit_u32(&mut self, v: u32) -> EncodeResult {
1128 Some(v) => self.emit_u16(v),
1129 None => self.wr_tagged_raw_u32(EsU32 as uint, v)
1132 fn emit_u16(&mut self, v: u16) -> EncodeResult {
1134 Some(v) => self.emit_u8(v),
1135 None => self.wr_tagged_raw_u16(EsU16 as uint, v)
1138 fn emit_u8(&mut self, v: u8) -> EncodeResult {
1139 self.wr_tagged_raw_u8(EsU8 as uint, v)
1142 fn emit_int(&mut self, v: int) -> EncodeResult {
1143 self.emit_i64(v as i64)
1145 fn emit_i64(&mut self, v: i64) -> EncodeResult {
1147 Some(v) => self.emit_i32(v),
1148 None => self.wr_tagged_raw_i64(EsI64 as uint, v)
1151 fn emit_i32(&mut self, v: i32) -> EncodeResult {
1153 Some(v) => self.emit_i16(v),
1154 None => self.wr_tagged_raw_i32(EsI32 as uint, v)
1157 fn emit_i16(&mut self, v: i16) -> EncodeResult {
1159 Some(v) => self.emit_i8(v),
1160 None => self.wr_tagged_raw_i16(EsI16 as uint, v)
1163 fn emit_i8(&mut self, v: i8) -> EncodeResult {
1164 self.wr_tagged_raw_i8(EsI8 as uint, v)
1167 fn emit_bool(&mut self, v: bool) -> EncodeResult {
1168 self.wr_tagged_raw_u8(EsBool as uint, v as u8)
1171 fn emit_f64(&mut self, v: f64) -> EncodeResult {
1172 let bits = unsafe { mem::transmute(v) };
1173 self.wr_tagged_raw_u64(EsF64 as uint, bits)
1175 fn emit_f32(&mut self, v: f32) -> EncodeResult {
1176 let bits = unsafe { mem::transmute(v) };
1177 self.wr_tagged_raw_u32(EsF32 as uint, bits)
1179 fn emit_char(&mut self, v: char) -> EncodeResult {
1180 self.wr_tagged_raw_u32(EsChar as uint, v as u32)
1183 fn emit_str(&mut self, v: &str) -> EncodeResult {
1184 self.wr_tagged_str(EsStr as uint, v)
1187 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
1188 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1190 try!(self.start_tag(EsEnum as uint));
1195 fn emit_enum_variant<F>(&mut self,
1199 f: F) -> EncodeResult where
1200 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1202 try!(self._emit_tagged_sub(v_id));
1206 fn emit_enum_variant_arg<F>(&mut self, _: uint, f: F) -> EncodeResult where
1207 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1212 fn emit_enum_struct_variant<F>(&mut self,
1216 f: F) -> EncodeResult where
1217 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1219 self.emit_enum_variant(v_name, v_id, cnt, f)
1222 fn emit_enum_struct_variant_field<F>(&mut self,
1225 f: F) -> EncodeResult where
1226 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1228 self.emit_enum_variant_arg(idx, f)
1231 fn emit_struct<F>(&mut self, _: &str, _len: uint, f: F) -> EncodeResult where
1232 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1237 fn emit_struct_field<F>(&mut self, _name: &str, _: uint, f: F) -> EncodeResult where
1238 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1243 fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
1244 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1246 self.emit_seq(len, f)
1248 fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
1249 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1251 self.emit_seq_elt(idx, f)
1254 fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
1255 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1257 self.emit_seq(len, f)
1259 fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
1260 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1262 self.emit_seq_elt(idx, f)
1265 fn emit_option<F>(&mut self, f: F) -> EncodeResult where
1266 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1268 self.emit_enum("Option", f)
1270 fn emit_option_none(&mut self) -> EncodeResult {
1271 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1273 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
1274 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1277 self.emit_enum_variant("Some", 1, 1, f)
1280 fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
1281 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1284 // empty vector optimization
1285 return self.wr_tagged_bytes(EsVec as uint, &[]);
1288 try!(self.start_tag(EsVec as uint));
1289 try!(self._emit_tagged_sub(len));
1294 fn emit_seq_elt<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
1295 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1298 try!(self.start_tag(EsVecElt as uint));
1303 fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
1304 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1307 // empty map optimization
1308 return self.wr_tagged_bytes(EsMap as uint, &[]);
1311 try!(self.start_tag(EsMap as uint));
1312 try!(self._emit_tagged_sub(len));
1317 fn emit_map_elt_key<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
1318 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1321 try!(self.start_tag(EsMapKey as uint));
1326 fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
1327 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1329 try!(self.start_tag(EsMapVal as uint));
1336 // ___________________________________________________________________________
1341 use super::{Doc, reader, writer};
1342 use super::io::SeekableMemWriter;
1344 use serialize::{Encodable, Decodable};
1346 use std::option::Option;
1347 use std::option::Option::{None, Some};
1350 fn test_vuint_at() {
1358 0x10, 0x00, 0x00, 0x00,
1359 0x1f, 0xff, 0xff, 0xff
1362 let mut res: reader::Res;
1365 res = reader::vuint_at(data, 0).unwrap();
1366 assert_eq!(res.val, 0);
1367 assert_eq!(res.next, 1);
1368 res = reader::vuint_at(data, res.next).unwrap();
1369 assert_eq!(res.val, (1 << 7) - 1);
1370 assert_eq!(res.next, 2);
1373 res = reader::vuint_at(data, res.next).unwrap();
1374 assert_eq!(res.val, 0);
1375 assert_eq!(res.next, 4);
1376 res = reader::vuint_at(data, res.next).unwrap();
1377 assert_eq!(res.val, (1 << 14) - 1);
1378 assert_eq!(res.next, 6);
1381 res = reader::vuint_at(data, res.next).unwrap();
1382 assert_eq!(res.val, 0);
1383 assert_eq!(res.next, 9);
1384 res = reader::vuint_at(data, res.next).unwrap();
1385 assert_eq!(res.val, (1 << 21) - 1);
1386 assert_eq!(res.next, 12);
1389 res = reader::vuint_at(data, res.next).unwrap();
1390 assert_eq!(res.val, 0);
1391 assert_eq!(res.next, 16);
1392 res = reader::vuint_at(data, res.next).unwrap();
1393 assert_eq!(res.val, (1 << 28) - 1);
1394 assert_eq!(res.next, 20);
1398 fn test_option_int() {
1399 fn test_v(v: Option<int>) {
1400 debug!("v == {:?}", v);
1401 let mut wr = SeekableMemWriter::new();
1403 let mut rbml_w = writer::Encoder::new(&mut wr);
1404 let _ = v.encode(&mut rbml_w);
1406 let rbml_doc = Doc::new(wr.get_ref());
1407 let mut deser = reader::Decoder::new(rbml_doc);
1408 let v1 = Decodable::decode(&mut deser).unwrap();
1409 debug!("v1 == {:?}", v1);
1421 #![allow(non_snake_case)]
1426 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1427 let data = (0..4*100).map(|i| {
1432 }).collect::<Vec<_>>();
1436 while i < data.len() {
1437 sum += reader::vuint_at(&data, i).unwrap().val;
1444 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1445 let data = (0..4*100+1).map(|i| {
1450 }).collect::<Vec<_>>();
1454 while i < data.len() {
1455 sum += reader::vuint_at(&data, i).unwrap().val;
1462 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1463 let data = (0..4*100).map(|i| {
1469 }).collect::<Vec<_>>();
1473 while i < data.len() {
1474 sum += reader::vuint_at(&data, i).unwrap().val;
1481 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
1482 let data = (0..4*100+1).map(|i| {
1488 }).collect::<Vec<_>>();
1492 while i < data.len() {
1493 sum += reader::vuint_at(&data, i).unwrap().val;