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")]
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 = "https://doc.rust-lang.org/favicon.ico",
123 html_root_url = "http://doc.rust-lang.org/nightly/",
124 html_playground_url = "http://play.rust-lang.org/")]
127 #![feature(rustc_private)]
128 #![feature(staged_api)]
130 #![cfg_attr(test, feature(test))]
132 extern crate serialize;
133 #[macro_use] extern crate log;
135 #[cfg(test)] extern crate test;
137 pub use self::EbmlEncoderTag::*;
138 pub use self::Error::*;
143 /// Common data structures
144 #[derive(Clone, Copy)]
151 impl<'doc> Doc<'doc> {
152 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
153 Doc { data: data, start: 0, end: data.len() }
156 pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
157 reader::get_doc(*self, tag)
160 pub fn is_empty(&self) -> bool {
161 self.start == self.end
164 pub fn as_str_slice<'a>(&'a self) -> &'a str {
165 str::from_utf8(&self.data[self.start..self.end]).unwrap()
168 pub fn as_str(&self) -> String {
169 self.as_str_slice().to_string()
173 pub struct TaggedDoc<'a> {
178 #[derive(Copy, Clone, Debug)]
179 pub enum EbmlEncoderTag {
180 // tags 00..1f are reserved for auto-serialization.
181 // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
183 EsU8 = 0x00, // + 1 byte
184 EsU16 = 0x01, // + 2 bytes
185 EsU32 = 0x02, // + 4 bytes
186 EsU64 = 0x03, // + 8 bytes
187 EsI8 = 0x04, // + 1 byte
188 EsI16 = 0x05, // + 2 bytes
189 EsI32 = 0x06, // + 4 bytes
190 EsI64 = 0x07, // + 8 bytes
191 EsBool = 0x08, // + 1 byte
192 EsChar = 0x09, // + 4 bytes
193 EsF32 = 0x0a, // + 4 bytes
194 EsF64 = 0x0b, // + 8 bytes
195 EsSub8 = 0x0c, // + 1 byte
196 EsSub32 = 0x0d, // + 4 bytes
197 // 0x0e and 0x0f are reserved
200 EsEnum = 0x11, // encodes the variant id as the first EsSub*
201 EsVec = 0x12, // encodes the # of elements as the first EsSub*
203 EsMap = 0x14, // encodes the # of pairs as the first EsSub*
209 const NUM_TAGS: usize = 0x1000;
210 const NUM_IMPLICIT_TAGS: usize = 0x0e;
212 static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
226 IoError(std::io::Error),
227 ApplicationError(String)
230 impl fmt::Display for Error {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 // FIXME: this should be a more useful display form
233 fmt::Debug::fmt(self, f)
236 // --------------------------------------
242 use std::mem::transmute;
243 use std::slice::bytes;
247 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
248 EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
249 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
250 EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
251 Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
253 pub type DecodeResult<T> = Result<T, Error>;
256 macro_rules! try_or {
257 ($e:expr, $r:expr) => (
261 debug!("ignored error: {:?}", e);
268 #[derive(Copy, Clone)]
274 pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
275 let v = data[start] as usize;
277 Ok(Res { val: v, next: start + 1 })
279 Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as usize, next: start + 2 })
281 // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
287 fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
290 return Ok(Res {val: (a & 0x7f) as usize, next: start + 1});
293 return Ok(Res {val: ((a & 0x3f) as usize) << 8 |
294 (data[start + 1] as usize),
298 return Ok(Res {val: ((a & 0x1f) as usize) << 16 |
299 (data[start + 1] as usize) << 8 |
300 (data[start + 2] as usize),
304 return Ok(Res {val: ((a & 0x0f) as usize) << 24 |
305 (data[start + 1] as usize) << 16 |
306 (data[start + 2] as usize) << 8 |
307 (data[start + 3] as usize),
310 Err(IntTooBig(a as usize))
313 pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
314 if data.len() - start < 4 {
315 return vuint_at_slow(data, start);
318 // Lookup table for parsing EBML Element IDs as per
319 // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by
320 // reading a big endian u32 positioned at data[start]. Using the four
321 // most significant bits of the u32 we lookup in the table below how
322 // the element ID should be derived from it.
324 // The table stores tuples (shift, mask) where shift is the number the
325 // u32 should be right shifted with and mask is the value the right
326 // shifted value should be masked with. If for example the most
327 // significant bit is set this means it's a class A ID and the u32
328 // should be right shifted with 24 and masked with 0x7f. Therefore we
329 // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most
330 // significant bit is set).
332 // By storing the number of shifts and masks in a table instead of
333 // checking in order if the most significant bit is set, the second
334 // most significant bit is set etc. we can replace up to three
335 // "and+branch" with a single table lookup which gives us a measured
336 // speedup of around 2x on x86_64.
337 static SHIFT_MASK_TABLE: [(usize, u32); 16] = [
338 (0, 0x0), (0, 0x0fffffff),
339 (8, 0x1fffff), (8, 0x1fffff),
340 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
341 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
342 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
346 let ptr = data.as_ptr().offset(start as isize) as *const u32;
347 let val = u32::from_be(*ptr);
349 let i = (val >> 28) as usize;
350 let (shift, mask) = SHIFT_MASK_TABLE[i];
352 val: ((val >> shift) & mask) as usize,
353 next: start + ((32 - shift) >> 3),
358 pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult<Res> {
359 if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 {
360 Ok(Res { val: TAG_IMPLICIT_LEN[tag.val] as usize, next: tag.next })
362 vuint_at(data, tag.next)
366 pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult<TaggedDoc<'a>> {
367 let elt_tag = try!(tag_at(data, start));
368 let elt_size = try!(tag_len_at(data, elt_tag));
369 let end = elt_size.next + elt_size.val;
372 doc: Doc { data: data, start: elt_size.next, end: end }
376 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
377 let mut pos = d.start;
379 let elt_tag = try_or!(tag_at(d.data, pos), None);
380 let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
381 pos = elt_size.next + elt_size.val;
382 if elt_tag.val == tg {
383 return Some(Doc { data: d.data, start: elt_size.next,
390 pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
391 match maybe_get_doc(d, tg) {
394 error!("failed to find block with tag {:?}", tg);
400 pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
406 pub struct DocsIterator<'a> {
410 impl<'a> Iterator for DocsIterator<'a> {
411 type Item = (usize, Doc<'a>);
413 fn next(&mut self) -> Option<(usize, Doc<'a>)> {
414 if self.d.start >= self.d.end {
418 let elt_tag = try_or!(tag_at(self.d.data, self.d.start), {
419 self.d.start = self.d.end;
422 let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), {
423 self.d.start = self.d.end;
427 let end = elt_size.next + elt_size.val;
430 start: elt_size.next,
435 return Some((elt_tag.val, doc));
439 pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> {
446 pub struct TaggedDocsIterator<'a> {
447 iter: DocsIterator<'a>,
451 impl<'a> Iterator for TaggedDocsIterator<'a> {
454 fn next(&mut self) -> Option<Doc<'a>> {
455 while let Some((tag, doc)) = self.iter.next() {
464 pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
465 F: FnOnce(&[u8]) -> T,
467 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_u16(d: Doc) -> u16 {
477 assert_eq!(d.end, d.start + 2);
479 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
480 unsafe { (*(b.as_ptr() as *const u16)).to_be() }
483 pub fn doc_as_u32(d: Doc) -> u32 {
484 assert_eq!(d.end, d.start + 4);
486 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
487 unsafe { (*(b.as_ptr() as *const u32)).to_be() }
490 pub fn doc_as_u64(d: Doc) -> u64 {
491 assert_eq!(d.end, d.start + 8);
493 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
494 unsafe { (*(b.as_ptr() as *const u64)).to_be() }
497 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
498 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
499 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
500 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
502 pub struct Decoder<'a> {
507 impl<'doc> Decoder<'doc> {
508 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
515 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
516 debug!(". next_doc(exp_tag={:?})", exp_tag);
517 if self.pos >= self.parent.end {
518 return Err(Expected(format!("no more documents in \
521 let TaggedDoc { tag: r_tag, doc: r_doc } =
522 try!(doc_at(self.parent.data, self.pos));
523 debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}",
530 if r_tag != (exp_tag as usize) {
531 return Err(Expected(format!("expected EBML doc with tag {:?} but \
532 found tag {:?}", exp_tag, r_tag)));
534 if r_doc.end > self.parent.end {
535 return Err(Expected(format!("invalid EBML, child extends to \
536 {:#x}, parent to {:#x}",
537 r_doc.end, self.parent.end)));
539 self.pos = r_doc.end;
543 fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
544 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
546 let d = try!(self.next_doc(exp_tag));
547 let old_parent = self.parent;
548 let old_pos = self.pos;
551 let r = try!(f(self));
552 self.parent = old_parent;
557 fn _next_sub(&mut self) -> DecodeResult<usize> {
558 // empty vector/map optimization
559 if self.parent.is_empty() {
563 let TaggedDoc { tag: r_tag, doc: r_doc } =
564 try!(doc_at(self.parent.data, self.pos));
565 let r = if r_tag == (EsSub8 as usize) {
566 doc_as_u8(r_doc) as usize
567 } else if r_tag == (EsSub32 as usize) {
568 doc_as_u32(r_doc) as usize
570 return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
571 found tag {:?}", EsSub8, EsSub32, r_tag)));
573 if r_doc.end > self.parent.end {
574 return Err(Expected(format!("invalid EBML, child extends to \
575 {:#x}, parent to {:#x}",
576 r_doc.end, self.parent.end)));
578 self.pos = r_doc.end;
579 debug!("_next_sub result={:?}", r);
583 // variable-length unsigned integer with different tags.
584 // `first_tag` should be a tag for u8 or i8.
585 // `last_tag` should be the largest allowed integer tag with the matching signedness.
586 // all tags between them should be valid, in the order of u8, u16, u32 and u64.
587 fn _next_int(&mut self,
588 first_tag: EbmlEncoderTag,
589 last_tag: EbmlEncoderTag) -> DecodeResult<u64> {
590 if self.pos >= self.parent.end {
591 return Err(Expected(format!("no more documents in \
595 let TaggedDoc { tag: r_tag, doc: r_doc } =
596 try!(doc_at(self.parent.data, self.pos));
597 let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize {
598 match r_tag - first_tag as usize {
599 0 => doc_as_u8(r_doc) as u64,
600 1 => doc_as_u16(r_doc) as u64,
601 2 => doc_as_u32(r_doc) as u64,
602 3 => doc_as_u64(r_doc),
606 return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
607 found tag {:?}", first_tag, last_tag, r_tag)));
609 if r_doc.end > self.parent.end {
610 return Err(Expected(format!("invalid EBML, child extends to \
611 {:#x}, parent to {:#x}",
612 r_doc.end, self.parent.end)));
614 self.pos = r_doc.end;
615 debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
619 pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
620 F: FnOnce(&mut Decoder, Doc) -> DecodeResult<R>,
622 let doc = try!(self.next_doc(EsOpaque));
624 let (old_parent, old_pos) = (self.parent, self.pos);
626 self.pos = doc.start;
628 let result = try!(op(self, doc));
630 self.parent = old_parent;
636 impl<'doc> serialize::Decoder for Decoder<'doc> {
638 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
640 fn read_u64(&mut self) -> DecodeResult<u64> { self._next_int(EsU8, EsU64) }
641 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(try!(self._next_int(EsU8, EsU32)) as u32) }
642 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(try!(self._next_int(EsU8, EsU16)) as u16) }
643 fn read_u8(&mut self) -> DecodeResult<u8> { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) }
644 fn read_uint(&mut self) -> DecodeResult<usize> {
645 let v = try!(self._next_int(EsU8, EsU64));
646 if v > (::std::usize::MAX as u64) {
647 Err(IntTooBig(v as usize))
653 fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self._next_int(EsI8, EsI64)) as i64) }
654 fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self._next_int(EsI8, EsI32)) as i32) }
655 fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self._next_int(EsI8, EsI16)) as i16) }
656 fn read_i8(&mut self) -> DecodeResult<i8> { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) }
657 fn read_int(&mut self) -> DecodeResult<isize> {
658 let v = try!(self._next_int(EsI8, EsI64)) as i64;
659 if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
660 debug!("FIXME \\#6122: Removing this makes this function miscompile");
661 Err(IntTooBig(v as usize))
667 fn read_bool(&mut self) -> DecodeResult<bool> {
668 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
671 fn read_f64(&mut self) -> DecodeResult<f64> {
672 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
673 Ok(unsafe { transmute(bits) })
675 fn read_f32(&mut self) -> DecodeResult<f32> {
676 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
677 Ok(unsafe { transmute(bits) })
679 fn read_char(&mut self) -> DecodeResult<char> {
680 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
682 fn read_str(&mut self) -> DecodeResult<String> {
683 Ok(try!(self.next_doc(EsStr)).as_str())
687 fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
688 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
690 debug!("read_enum({})", name);
692 let doc = try!(self.next_doc(EsEnum));
694 let (old_parent, old_pos) = (self.parent, self.pos);
696 self.pos = self.parent.start;
698 let result = try!(f(self));
700 self.parent = old_parent;
705 fn read_enum_variant<T, F>(&mut self, _: &[&str],
706 mut f: F) -> DecodeResult<T>
707 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
709 debug!("read_enum_variant()");
710 let idx = try!(self._next_sub());
711 debug!(" idx={}", idx);
716 fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
717 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
719 debug!("read_enum_variant_arg(idx={})", idx);
723 fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
724 mut f: F) -> DecodeResult<T>
725 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
727 debug!("read_enum_struct_variant()");
728 let idx = try!(self._next_sub());
729 debug!(" idx={}", idx);
734 fn read_enum_struct_variant_field<T, F>(&mut self,
738 -> DecodeResult<T> where
739 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
741 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
745 fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T> where
746 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
748 debug!("read_struct(name={})", name);
752 fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T> where
753 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
755 debug!("read_struct_field(name={}, idx={})", name, idx);
759 fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T> where
760 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
762 debug!("read_tuple()");
763 self.read_seq(move |d, len| {
764 if len == tuple_len {
767 Err(Expected(format!("Expected tuple of length `{}`, \
768 found tuple of length `{}`", tuple_len, len)))
773 fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
774 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
776 debug!("read_tuple_arg(idx={})", idx);
777 self.read_seq_elt(idx, f)
780 fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T> where
781 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
783 debug!("read_tuple_struct(name={})", name);
784 self.read_tuple(len, f)
787 fn read_tuple_struct_arg<T, F>(&mut self,
790 -> DecodeResult<T> where
791 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
793 debug!("read_tuple_struct_arg(idx={})", idx);
794 self.read_tuple_arg(idx, f)
797 fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
798 F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
800 debug!("read_option()");
801 self.read_enum("Option", move |this| {
802 this.read_enum_variant(&["None", "Some"], move |this, idx| {
807 Err(Expected(format!("Expected None or Some")))
814 fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
815 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
817 debug!("read_seq()");
818 self.push_doc(EsVec, move |d| {
819 let len = try!(d._next_sub());
820 debug!(" len={}", len);
825 fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
826 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
828 debug!("read_seq_elt(idx={})", idx);
829 self.push_doc(EsVecElt, f)
832 fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
833 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
835 debug!("read_map()");
836 self.push_doc(EsMap, move |d| {
837 let len = try!(d._next_sub());
838 debug!(" len={}", len);
843 fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
844 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
846 debug!("read_map_elt_key(idx={})", idx);
847 self.push_doc(EsMapKey, f)
850 fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
851 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
853 debug!("read_map_elt_val(idx={})", idx);
854 self.push_doc(EsMapVal, f)
857 fn error(&mut self, err: &str) -> Error {
858 ApplicationError(err.to_string())
865 use std::io::prelude::*;
866 use std::io::{self, SeekFrom, Cursor};
867 use std::slice::bytes;
869 use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
870 EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
871 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
872 EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
877 pub type EncodeResult = io::Result<()>;
880 pub struct Encoder<'a> {
881 pub writer: &'a mut Cursor<Vec<u8>>,
882 size_positions: Vec<u64>,
883 relax_limit: u64, // do not move encoded bytes before this position
886 fn write_tag<W: Write>(w: &mut W, n: usize) -> EncodeResult {
888 w.write_all(&[n as u8])
889 } else if 0x100 <= n && n < NUM_TAGS {
890 w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
892 Err(io::Error::new(io::ErrorKind::Other,
893 &format!("invalid tag: {}", n)[..]))
897 fn write_sized_vuint<W: Write>(w: &mut W, n: usize, size: usize) -> EncodeResult {
899 1 => w.write_all(&[0x80 | (n as u8)]),
900 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]),
901 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8,
903 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
904 (n >> 8) as u8, n as u8]),
905 _ => Err(io::Error::new(io::ErrorKind::Other,
906 &format!("isize too big: {}", n)[..]))
910 fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
911 if n < 0x7f { return write_sized_vuint(w, n, 1); }
912 if n < 0x4000 { return write_sized_vuint(w, n, 2); }
913 if n < 0x200000 { return write_sized_vuint(w, n, 3); }
914 if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
915 Err(io::Error::new(io::ErrorKind::Other,
916 &format!("isize too big: {}", n)[..]))
919 impl<'a> Encoder<'a> {
920 pub fn new(w: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
923 size_positions: vec!(),
928 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
929 pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
931 writer: mem::transmute_copy(&self.writer),
932 size_positions: self.size_positions.clone(),
933 relax_limit: self.relax_limit,
937 pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
938 debug!("Start tag {:?}", tag_id);
939 assert!(tag_id >= NUM_IMPLICIT_TAGS);
941 // Write the enum ID:
942 try!(write_tag(self.writer, tag_id));
944 // Write a placeholder four-byte size.
945 let cur_pos = try!(self.writer.seek(SeekFrom::Current(0)));
946 self.size_positions.push(cur_pos);
947 let zeroes: &[u8] = &[0, 0, 0, 0];
948 self.writer.write_all(zeroes)
951 pub fn end_tag(&mut self) -> EncodeResult {
952 let last_size_pos = self.size_positions.pop().unwrap();
953 let cur_pos = try!(self.writer.seek(SeekFrom::Current(0)));
954 try!(self.writer.seek(SeekFrom::Start(last_size_pos)));
955 let size = (cur_pos - last_size_pos - 4) as usize;
957 // relax the size encoding for small tags (bigger tags are costly to move).
958 // we should never try to move the stable positions, however.
959 const RELAX_MAX_SIZE: usize = 0x100;
960 if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit {
961 // we can't alter the buffer in place, so have a temporary buffer
962 let mut buf = [0u8; RELAX_MAX_SIZE];
964 let last_size_pos = last_size_pos as usize;
965 let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as usize];
966 bytes::copy_memory(data, &mut buf);
969 // overwrite the size and data and continue
970 try!(write_vuint(self.writer, size));
971 try!(self.writer.write_all(&buf[..size]));
973 // overwrite the size with an overlong encoding and skip past the data
974 try!(write_sized_vuint(self.writer, size, 4));
975 try!(self.writer.seek(SeekFrom::Start(cur_pos)));
978 debug!("End tag (size = {:?})", size);
982 pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult where
983 F: FnOnce() -> EncodeResult,
985 try!(self.start_tag(tag_id));
990 pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
991 assert!(tag_id >= NUM_IMPLICIT_TAGS);
992 try!(write_tag(self.writer, tag_id));
993 try!(write_vuint(self.writer, b.len()));
994 self.writer.write_all(b)
997 pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
998 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
999 self.wr_tagged_bytes(tag_id, &bytes)
1002 pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult{
1003 let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
1004 self.wr_tagged_bytes(tag_id, &bytes)
1007 pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
1008 let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
1009 self.wr_tagged_bytes(tag_id, &bytes)
1012 pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1013 self.wr_tagged_bytes(tag_id, &[v])
1016 pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
1017 self.wr_tagged_u64(tag_id, v as u64)
1020 pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
1021 self.wr_tagged_u32(tag_id, v as u32)
1024 pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
1025 self.wr_tagged_u16(tag_id, v as u16)
1028 pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
1029 self.wr_tagged_bytes(tag_id, &[v as u8])
1032 pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
1033 self.wr_tagged_bytes(tag_id, v.as_bytes())
1036 // for auto-serialization
1037 fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
1038 try!(write_tag(self.writer, tag_id));
1039 self.writer.write_all(b)
1042 fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
1043 let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
1044 self.wr_tagged_raw_bytes(tag_id, &bytes)
1047 fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult{
1048 let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
1049 self.wr_tagged_raw_bytes(tag_id, &bytes)
1052 fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
1053 let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
1054 self.wr_tagged_raw_bytes(tag_id, &bytes)
1057 fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1058 self.wr_tagged_raw_bytes(tag_id, &[v])
1061 fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
1062 self.wr_tagged_raw_u64(tag_id, v as u64)
1065 fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
1066 self.wr_tagged_raw_u32(tag_id, v as u32)
1069 fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
1070 self.wr_tagged_raw_u16(tag_id, v as u16)
1073 fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
1074 self.wr_tagged_raw_bytes(tag_id, &[v as u8])
1077 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
1078 debug!("Write {:?} bytes", b.len());
1079 self.writer.write_all(b)
1082 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
1083 debug!("Write str: {:?}", s);
1084 self.writer.write_all(s.as_bytes())
1087 /// Returns the current position while marking it stable, i.e.
1088 /// generated bytes so far wouldn't be affected by relaxation.
1089 pub fn mark_stable_position(&mut self) -> u64 {
1090 let pos = self.writer.seek(SeekFrom::Current(0)).unwrap();
1091 if self.relax_limit < pos {
1092 self.relax_limit = pos;
1098 impl<'a> Encoder<'a> {
1099 // used internally to emit things like the vector length and so on
1100 fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
1101 if v as u8 as usize == v {
1102 self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
1103 } else if v as u32 as usize == v {
1104 self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
1106 Err(io::Error::new(io::ErrorKind::Other,
1107 &format!("length or variant id too big: {}",
1112 pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
1113 F: FnOnce(&mut Encoder) -> EncodeResult,
1115 try!(self.start_tag(EsOpaque as usize));
1121 impl<'a> serialize::Encoder for Encoder<'a> {
1122 type Error = io::Error;
1124 fn emit_nil(&mut self) -> EncodeResult {
1128 fn emit_uint(&mut self, v: usize) -> EncodeResult {
1129 self.emit_u64(v as u64)
1131 fn emit_u64(&mut self, v: u64) -> EncodeResult {
1132 if v as u32 as u64 == v {
1133 self.emit_u32(v as u32)
1135 self.wr_tagged_raw_u64(EsU64 as usize, v)
1138 fn emit_u32(&mut self, v: u32) -> EncodeResult {
1139 if v as u16 as u32 == v {
1140 self.emit_u16(v as u16)
1142 self.wr_tagged_raw_u32(EsU32 as usize, v)
1145 fn emit_u16(&mut self, v: u16) -> EncodeResult {
1146 if v as u8 as u16 == v {
1147 self.emit_u8(v as u8)
1149 self.wr_tagged_raw_u16(EsU16 as usize, v)
1152 fn emit_u8(&mut self, v: u8) -> EncodeResult {
1153 self.wr_tagged_raw_u8(EsU8 as usize, v)
1156 fn emit_int(&mut self, v: isize) -> EncodeResult {
1157 self.emit_i64(v as i64)
1159 fn emit_i64(&mut self, v: i64) -> EncodeResult {
1160 if v as i32 as i64 == v {
1161 self.emit_i32(v as i32)
1163 self.wr_tagged_raw_i64(EsI64 as usize, v)
1166 fn emit_i32(&mut self, v: i32) -> EncodeResult {
1167 if v as i16 as i32 == v {
1168 self.emit_i16(v as i16)
1170 self.wr_tagged_raw_i32(EsI32 as usize, v)
1173 fn emit_i16(&mut self, v: i16) -> EncodeResult {
1174 if v as i8 as i16 == v {
1175 self.emit_i8(v as i8)
1177 self.wr_tagged_raw_i16(EsI16 as usize, v)
1180 fn emit_i8(&mut self, v: i8) -> EncodeResult {
1181 self.wr_tagged_raw_i8(EsI8 as usize, v)
1184 fn emit_bool(&mut self, v: bool) -> EncodeResult {
1185 self.wr_tagged_raw_u8(EsBool as usize, v as u8)
1188 fn emit_f64(&mut self, v: f64) -> EncodeResult {
1189 let bits = unsafe { mem::transmute(v) };
1190 self.wr_tagged_raw_u64(EsF64 as usize, bits)
1192 fn emit_f32(&mut self, v: f32) -> EncodeResult {
1193 let bits = unsafe { mem::transmute(v) };
1194 self.wr_tagged_raw_u32(EsF32 as usize, bits)
1196 fn emit_char(&mut self, v: char) -> EncodeResult {
1197 self.wr_tagged_raw_u32(EsChar as usize, v as u32)
1200 fn emit_str(&mut self, v: &str) -> EncodeResult {
1201 self.wr_tagged_str(EsStr as usize, v)
1204 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
1205 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1207 try!(self.start_tag(EsEnum as usize));
1212 fn emit_enum_variant<F>(&mut self,
1216 f: F) -> EncodeResult where
1217 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1219 try!(self._emit_tagged_sub(v_id));
1223 fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult where
1224 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1229 fn emit_enum_struct_variant<F>(&mut self,
1233 f: F) -> EncodeResult where
1234 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1236 self.emit_enum_variant(v_name, v_id, cnt, f)
1239 fn emit_enum_struct_variant_field<F>(&mut self,
1242 f: F) -> EncodeResult where
1243 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1245 self.emit_enum_variant_arg(idx, f)
1248 fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where
1249 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1254 fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where
1255 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1260 fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
1261 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1263 self.emit_seq(len, f)
1265 fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1266 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1268 self.emit_seq_elt(idx, f)
1271 fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
1272 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1274 self.emit_seq(len, f)
1276 fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1277 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1279 self.emit_seq_elt(idx, f)
1282 fn emit_option<F>(&mut self, f: F) -> EncodeResult where
1283 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1285 self.emit_enum("Option", f)
1287 fn emit_option_none(&mut self) -> EncodeResult {
1288 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1290 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
1291 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1294 self.emit_enum_variant("Some", 1, 1, f)
1297 fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
1298 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1301 // empty vector optimization
1302 return self.wr_tagged_bytes(EsVec as usize, &[]);
1305 try!(self.start_tag(EsVec as usize));
1306 try!(self._emit_tagged_sub(len));
1311 fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1312 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1315 try!(self.start_tag(EsVecElt as usize));
1320 fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
1321 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1324 // empty map optimization
1325 return self.wr_tagged_bytes(EsMap as usize, &[]);
1328 try!(self.start_tag(EsMap as usize));
1329 try!(self._emit_tagged_sub(len));
1334 fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1335 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1338 try!(self.start_tag(EsMapKey as usize));
1343 fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1344 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1346 try!(self.start_tag(EsMapVal as usize));
1353 // ___________________________________________________________________________
1358 use super::{Doc, reader, writer};
1360 use serialize::{Encodable, Decodable};
1362 use std::io::Cursor;
1365 fn test_vuint_at() {
1373 0x10, 0x00, 0x00, 0x00,
1374 0x1f, 0xff, 0xff, 0xff
1377 let mut res: reader::Res;
1380 res = reader::vuint_at(data, 0).unwrap();
1381 assert_eq!(res.val, 0);
1382 assert_eq!(res.next, 1);
1383 res = reader::vuint_at(data, res.next).unwrap();
1384 assert_eq!(res.val, (1 << 7) - 1);
1385 assert_eq!(res.next, 2);
1388 res = reader::vuint_at(data, res.next).unwrap();
1389 assert_eq!(res.val, 0);
1390 assert_eq!(res.next, 4);
1391 res = reader::vuint_at(data, res.next).unwrap();
1392 assert_eq!(res.val, (1 << 14) - 1);
1393 assert_eq!(res.next, 6);
1396 res = reader::vuint_at(data, res.next).unwrap();
1397 assert_eq!(res.val, 0);
1398 assert_eq!(res.next, 9);
1399 res = reader::vuint_at(data, res.next).unwrap();
1400 assert_eq!(res.val, (1 << 21) - 1);
1401 assert_eq!(res.next, 12);
1404 res = reader::vuint_at(data, res.next).unwrap();
1405 assert_eq!(res.val, 0);
1406 assert_eq!(res.next, 16);
1407 res = reader::vuint_at(data, res.next).unwrap();
1408 assert_eq!(res.val, (1 << 28) - 1);
1409 assert_eq!(res.next, 20);
1413 fn test_option_int() {
1414 fn test_v(v: Option<isize>) {
1415 debug!("v == {:?}", v);
1416 let mut wr = Cursor::new(Vec::new());
1418 let mut rbml_w = writer::Encoder::new(&mut wr);
1419 let _ = v.encode(&mut rbml_w);
1421 let rbml_doc = Doc::new(wr.get_ref());
1422 let mut deser = reader::Decoder::new(rbml_doc);
1423 let v1 = Decodable::decode(&mut deser).unwrap();
1424 debug!("v1 == {:?}", v1);
1436 #![allow(non_snake_case)]
1441 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1442 let data = (0..4*100).map(|i| {
1447 }).collect::<Vec<_>>();
1451 while i < data.len() {
1452 sum += reader::vuint_at(&data, i).unwrap().val;
1459 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1460 let data = (0..4*100+1).map(|i| {
1465 }).collect::<Vec<_>>();
1469 while i < data.len() {
1470 sum += reader::vuint_at(&data, i).unwrap().val;
1477 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1478 let data = (0..4*100).map(|i| {
1484 }).collect::<Vec<_>>();
1488 while i < data.len() {
1489 sum += reader::vuint_at(&data, i).unwrap().val;
1496 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
1497 let data = (0..4*100+1).map(|i| {
1503 }).collect::<Vec<_>>();
1507 while i < data.len() {
1508 sum += reader::vuint_at(&data, i).unwrap().val;