]> git.proxmox.com Git - rustc.git/blame - src/librbml/lib.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / librbml / lib.rs
CommitLineData
c34b1796 1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
1a4d82fc
JJ
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
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.
10
c34b1796
AL
11//! Really Bad Markup Language (rbml) is an internal serialization format of rustc.
12//! This is not intended to be used by users.
1a4d82fc 13//!
c34b1796
AL
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.
17//!
18//! # Encoding
19//!
20//! RBML document consists of the tag, length and data.
21//! The encoded data can contain multiple RBML documents concatenated.
22//!
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`)
28//!
29//! **Lengths** encode the length of the following data.
30//! It is a variable-length unsigned isize, and one of the following forms:
31//!
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.
36//!
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").
44//!
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.
48//!
49//! # Predefined Tags
50//!
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.
55//!
56//! Predefined tags with an implicit length:
57//!
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.
65//!
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.
71//!
72//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true.
73//!
74//! - `Char` (`09`): 4-byte big endian Unicode scalar value.
75//! Surrogate pairs or out-of-bound values are invalid.
76//!
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.
81//!
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.
87//!
88//! Predefined tags with an explicit length:
89//!
90//! - `Str` (`10`): A UTF-8-encoded string.
91//!
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.
95//!
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.
100//!
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.
107//!
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.
111//!
112//! First 0x20 tags are reserved by RBML; custom tags start at 0x20.
1a4d82fc 113
c34b1796
AL
114// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
115#![cfg_attr(stage0, feature(custom_attribute))]
1a4d82fc 116#![crate_name = "rbml"]
85aaf69f 117#![unstable(feature = "rustc_private")]
1a4d82fc
JJ
118#![staged_api]
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",
62682a34 122 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
1a4d82fc
JJ
123 html_root_url = "http://doc.rust-lang.org/nightly/",
124 html_playground_url = "http://play.rust-lang.org/")]
85aaf69f 125
85aaf69f
SL
126#![feature(rustc_private)]
127#![feature(staged_api)]
62682a34 128#![feature(slice_bytes)]
1a4d82fc 129
c34b1796
AL
130#![cfg_attr(test, feature(test))]
131
1a4d82fc
JJ
132extern crate serialize;
133#[macro_use] extern crate log;
134
135#[cfg(test)] extern crate test;
136
137pub use self::EbmlEncoderTag::*;
138pub use self::Error::*;
139
140use std::str;
85aaf69f 141use std::fmt;
1a4d82fc 142
1a4d82fc
JJ
143/// Common data structures
144#[derive(Clone, Copy)]
145pub struct Doc<'a> {
146 pub data: &'a [u8],
c34b1796
AL
147 pub start: usize,
148 pub end: usize,
1a4d82fc
JJ
149}
150
151impl<'doc> Doc<'doc> {
152 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
85aaf69f 153 Doc { data: data, start: 0, end: data.len() }
1a4d82fc
JJ
154 }
155
c34b1796 156 pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
1a4d82fc
JJ
157 reader::get_doc(*self, tag)
158 }
159
c34b1796
AL
160 pub fn is_empty(&self) -> bool {
161 self.start == self.end
162 }
163
1a4d82fc
JJ
164 pub fn as_str_slice<'a>(&'a self) -> &'a str {
165 str::from_utf8(&self.data[self.start..self.end]).unwrap()
166 }
167
168 pub fn as_str(&self) -> String {
169 self.as_str_slice().to_string()
170 }
171}
172
173pub struct TaggedDoc<'a> {
c34b1796 174 tag: usize,
1a4d82fc
JJ
175 pub doc: Doc<'a>,
176}
177
c34b1796 178#[derive(Copy, Clone, Debug)]
1a4d82fc 179pub enum EbmlEncoderTag {
c34b1796
AL
180 // tags 00..1f are reserved for auto-serialization.
181 // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
182
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
198
199 EsStr = 0x10,
200 EsEnum = 0x11, // encodes the variant id as the first EsSub*
201 EsVec = 0x12, // encodes the # of elements as the first EsSub*
202 EsVecElt = 0x13,
203 EsMap = 0x14, // encodes the # of pairs as the first EsSub*
204 EsMapKey = 0x15,
205 EsMapVal = 0x16,
206 EsOpaque = 0x17,
1a4d82fc
JJ
207}
208
c34b1796
AL
209const NUM_TAGS: usize = 0x1000;
210const NUM_IMPLICIT_TAGS: usize = 0x0e;
211
212static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
213 1, 2, 4, 8, // EsU*
214 1, 2, 4, 8, // ESI*
215 1, // EsBool
216 4, // EsChar
217 4, 8, // EsF*
218 1, 4, // EsSub*
219];
220
85aaf69f 221#[derive(Debug)]
1a4d82fc 222pub enum Error {
c34b1796
AL
223 IntTooBig(usize),
224 InvalidTag(usize),
1a4d82fc 225 Expected(String),
c34b1796 226 IoError(std::io::Error),
1a4d82fc
JJ
227 ApplicationError(String)
228}
85aaf69f
SL
229
230impl 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)
234 }
235}
1a4d82fc
JJ
236// --------------------------------------
237
238pub mod reader {
239 use std::char;
240
85aaf69f 241 use std::isize;
1a4d82fc 242 use std::mem::transmute;
c34b1796 243 use std::slice::bytes;
1a4d82fc
JJ
244
245 use serialize;
246
c34b1796
AL
247 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
248 EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
1a4d82fc 249 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
c34b1796
AL
250 EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
251 Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
1a4d82fc
JJ
252
253 pub type DecodeResult<T> = Result<T, Error>;
254 // rbml reading
255
256 macro_rules! try_or {
257 ($e:expr, $r:expr) => (
258 match $e {
259 Ok(e) => e,
260 Err(e) => {
261 debug!("ignored error: {:?}", e);
262 return $r
263 }
264 }
265 )
266 }
267
c34b1796 268 #[derive(Copy, Clone)]
1a4d82fc 269 pub struct Res {
c34b1796
AL
270 pub val: usize,
271 pub next: usize
272 }
273
274 pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
275 let v = data[start] as usize;
276 if v < 0xf0 {
277 Ok(Res { val: v, next: start + 1 })
278 } else if v > 0xf0 {
279 Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as usize, next: start + 2 })
280 } else {
281 // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
282 Err(InvalidTag(v))
283 }
1a4d82fc
JJ
284 }
285
286 #[inline(never)]
c34b1796 287 fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
1a4d82fc 288 let a = data[start];
c34b1796
AL
289 if a & 0x80 != 0 {
290 return Ok(Res {val: (a & 0x7f) as usize, next: start + 1});
1a4d82fc 291 }
c34b1796
AL
292 if a & 0x40 != 0 {
293 return Ok(Res {val: ((a & 0x3f) as usize) << 8 |
294 (data[start + 1] as usize),
85aaf69f 295 next: start + 2});
1a4d82fc 296 }
c34b1796
AL
297 if a & 0x20 != 0 {
298 return Ok(Res {val: ((a & 0x1f) as usize) << 16 |
299 (data[start + 1] as usize) << 8 |
300 (data[start + 2] as usize),
85aaf69f 301 next: start + 3});
1a4d82fc 302 }
c34b1796
AL
303 if a & 0x10 != 0 {
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),
85aaf69f 308 next: start + 4});
1a4d82fc 309 }
c34b1796 310 Err(IntTooBig(a as usize))
1a4d82fc
JJ
311 }
312
c34b1796 313 pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
1a4d82fc
JJ
314 if data.len() - start < 4 {
315 return vuint_at_slow(data, start);
316 }
317
c34b1796
AL
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.
1a4d82fc 323 //
c34b1796
AL
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).
1a4d82fc 331 //
c34b1796
AL
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
1a4d82fc 336 // speedup of around 2x on x86_64.
c34b1796 337 static SHIFT_MASK_TABLE: [(usize, u32); 16] = [
1a4d82fc
JJ
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)
343 ];
344
345 unsafe {
c34b1796
AL
346 let ptr = data.as_ptr().offset(start as isize) as *const u32;
347 let val = u32::from_be(*ptr);
1a4d82fc 348
c34b1796 349 let i = (val >> 28) as usize;
1a4d82fc
JJ
350 let (shift, mask) = SHIFT_MASK_TABLE[i];
351 Ok(Res {
c34b1796
AL
352 val: ((val >> shift) & mask) as usize,
353 next: start + ((32 - shift) >> 3),
1a4d82fc
JJ
354 })
355 }
356 }
357
c34b1796
AL
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 })
361 } else {
362 vuint_at(data, tag.next)
363 }
364 }
365
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));
1a4d82fc
JJ
369 let end = elt_size.next + elt_size.val;
370 Ok(TaggedDoc {
371 tag: elt_tag.val,
372 doc: Doc { data: data, start: elt_size.next, end: end }
373 })
374 }
375
c34b1796 376 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
1a4d82fc
JJ
377 let mut pos = d.start;
378 while pos < d.end {
c34b1796
AL
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);
1a4d82fc
JJ
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,
384 end: pos });
385 }
386 }
387 None
388 }
389
c34b1796 390 pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
1a4d82fc
JJ
391 match maybe_get_doc(d, tg) {
392 Some(d) => d,
393 None => {
394 error!("failed to find block with tag {:?}", tg);
395 panic!();
396 }
397 }
398 }
399
62682a34
SL
400 pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
401 DocsIterator {
402 d: d
403 }
404 }
405
406 pub struct DocsIterator<'a> {
407 d: Doc<'a>,
408 }
409
410 impl<'a> Iterator for DocsIterator<'a> {
411 type Item = (usize, Doc<'a>);
412
413 fn next(&mut self) -> Option<(usize, Doc<'a>)> {
414 if self.d.start >= self.d.end {
415 return None;
1a4d82fc 416 }
62682a34
SL
417
418 let elt_tag = try_or!(tag_at(self.d.data, self.d.start), {
419 self.d.start = self.d.end;
420 None
421 });
422 let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), {
423 self.d.start = self.d.end;
424 None
425 });
426
427 let end = elt_size.next + elt_size.val;
428 let doc = Doc {
429 data: self.d.data,
430 start: elt_size.next,
431 end: end,
432 };
433
434 self.d.start = end;
435 return Some((elt_tag.val, doc));
1a4d82fc 436 }
1a4d82fc
JJ
437 }
438
62682a34
SL
439 pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> {
440 TaggedDocsIterator {
441 iter: docs(d),
442 tag: tag,
443 }
444 }
445
446 pub struct TaggedDocsIterator<'a> {
447 iter: DocsIterator<'a>,
448 tag: usize,
449 }
450
451 impl<'a> Iterator for TaggedDocsIterator<'a> {
452 type Item = Doc<'a>;
453
454 fn next(&mut self) -> Option<Doc<'a>> {
455 while let Some((tag, doc)) = self.iter.next() {
456 if tag == self.tag {
457 return Some(doc);
1a4d82fc
JJ
458 }
459 }
62682a34 460 None
1a4d82fc 461 }
1a4d82fc
JJ
462 }
463
464 pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
465 F: FnOnce(&[u8]) -> T,
466 {
467 f(&d.data[d.start..d.end])
468 }
469
470
471 pub fn doc_as_u8(d: Doc) -> u8 {
85aaf69f 472 assert_eq!(d.end, d.start + 1);
1a4d82fc
JJ
473 d.data[d.start]
474 }
475
476 pub fn doc_as_u16(d: Doc) -> u16 {
85aaf69f 477 assert_eq!(d.end, d.start + 2);
c34b1796
AL
478 let mut b = [0; 2];
479 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
480 unsafe { (*(b.as_ptr() as *const u16)).to_be() }
1a4d82fc
JJ
481 }
482
483 pub fn doc_as_u32(d: Doc) -> u32 {
85aaf69f 484 assert_eq!(d.end, d.start + 4);
c34b1796
AL
485 let mut b = [0; 4];
486 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
487 unsafe { (*(b.as_ptr() as *const u32)).to_be() }
1a4d82fc
JJ
488 }
489
490 pub fn doc_as_u64(d: Doc) -> u64 {
85aaf69f 491 assert_eq!(d.end, d.start + 8);
c34b1796
AL
492 let mut b = [0; 8];
493 bytes::copy_memory(&d.data[d.start..d.end], &mut b);
494 unsafe { (*(b.as_ptr() as *const u64)).to_be() }
1a4d82fc
JJ
495 }
496
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 }
501
502 pub struct Decoder<'a> {
503 parent: Doc<'a>,
c34b1796 504 pos: usize,
1a4d82fc
JJ
505 }
506
507 impl<'doc> Decoder<'doc> {
508 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
509 Decoder {
510 parent: d,
511 pos: d.start
512 }
513 }
514
1a4d82fc
JJ
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 \
519 current node!")));
520 }
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={:?}-{:?}",
524 self.parent.start,
525 self.parent.end,
526 self.pos,
527 r_tag,
528 r_doc.start,
529 r_doc.end);
c34b1796 530 if r_tag != (exp_tag as usize) {
1a4d82fc
JJ
531 return Err(Expected(format!("expected EBML doc with tag {:?} but \
532 found tag {:?}", exp_tag, r_tag)));
533 }
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)));
538 }
539 self.pos = r_doc.end;
540 Ok(r_doc)
541 }
542
543 fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
544 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
545 {
546 let d = try!(self.next_doc(exp_tag));
547 let old_parent = self.parent;
548 let old_pos = self.pos;
549 self.parent = d;
550 self.pos = d.start;
551 let r = try!(f(self));
552 self.parent = old_parent;
553 self.pos = old_pos;
554 Ok(r)
555 }
556
c34b1796
AL
557 fn _next_sub(&mut self) -> DecodeResult<usize> {
558 // empty vector/map optimization
559 if self.parent.is_empty() {
560 return Ok(0);
561 }
562
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
569 } else {
570 return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
571 found tag {:?}", EsSub8, EsSub32, r_tag)));
572 };
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)));
577 }
578 self.pos = r_doc.end;
579 debug!("_next_sub result={:?}", r);
580 Ok(r)
581 }
582
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 \
592 current node!")));
593 }
594
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),
603 _ => unreachable!(),
604 }
605 } else {
606 return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
607 found tag {:?}", first_tag, last_tag, r_tag)));
608 };
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)));
613 }
614 self.pos = r_doc.end;
615 debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
616 Ok(r)
1a4d82fc
JJ
617 }
618
619 pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
620 F: FnOnce(&mut Decoder, Doc) -> DecodeResult<R>,
621 {
622 let doc = try!(self.next_doc(EsOpaque));
623
624 let (old_parent, old_pos) = (self.parent, self.pos);
625 self.parent = doc;
626 self.pos = doc.start;
627
628 let result = try!(op(self, doc));
629
630 self.parent = old_parent;
631 self.pos = old_pos;
632 Ok(result)
633 }
634 }
635
636 impl<'doc> serialize::Decoder for Decoder<'doc> {
637 type Error = Error;
638 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
639
c34b1796
AL
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));
85aaf69f 646 if v > (::std::usize::MAX as u64) {
c34b1796 647 Err(IntTooBig(v as usize))
1a4d82fc 648 } else {
c34b1796 649 Ok(v as usize)
1a4d82fc
JJ
650 }
651 }
652
c34b1796
AL
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;
85aaf69f 659 if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
1a4d82fc 660 debug!("FIXME \\#6122: Removing this makes this function miscompile");
c34b1796 661 Err(IntTooBig(v as usize))
1a4d82fc 662 } else {
c34b1796 663 Ok(v as isize)
1a4d82fc
JJ
664 }
665 }
666
667 fn read_bool(&mut self) -> DecodeResult<bool> {
668 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
669 }
670
671 fn read_f64(&mut self) -> DecodeResult<f64> {
672 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
673 Ok(unsafe { transmute(bits) })
674 }
675 fn read_f32(&mut self) -> DecodeResult<f32> {
676 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
677 Ok(unsafe { transmute(bits) })
678 }
679 fn read_char(&mut self) -> DecodeResult<char> {
680 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
681 }
682 fn read_str(&mut self) -> DecodeResult<String> {
683 Ok(try!(self.next_doc(EsStr)).as_str())
684 }
685
686 // Compound types:
687 fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
688 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
689 {
690 debug!("read_enum({})", name);
1a4d82fc
JJ
691
692 let doc = try!(self.next_doc(EsEnum));
693
694 let (old_parent, old_pos) = (self.parent, self.pos);
695 self.parent = doc;
696 self.pos = self.parent.start;
697
698 let result = try!(f(self));
699
700 self.parent = old_parent;
701 self.pos = old_pos;
702 Ok(result)
703 }
704
705 fn read_enum_variant<T, F>(&mut self, _: &[&str],
706 mut f: F) -> DecodeResult<T>
c34b1796 707 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
1a4d82fc
JJ
708 {
709 debug!("read_enum_variant()");
c34b1796 710 let idx = try!(self._next_sub());
1a4d82fc
JJ
711 debug!(" idx={}", idx);
712
c34b1796 713 f(self, idx)
1a4d82fc
JJ
714 }
715
c34b1796 716 fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
717 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
718 {
719 debug!("read_enum_variant_arg(idx={})", idx);
720 f(self)
721 }
722
723 fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
724 mut f: F) -> DecodeResult<T>
c34b1796 725 where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
1a4d82fc
JJ
726 {
727 debug!("read_enum_struct_variant()");
c34b1796 728 let idx = try!(self._next_sub());
1a4d82fc
JJ
729 debug!(" idx={}", idx);
730
c34b1796 731 f(self, idx)
1a4d82fc
JJ
732 }
733
734 fn read_enum_struct_variant_field<T, F>(&mut self,
735 name: &str,
c34b1796 736 idx: usize,
1a4d82fc
JJ
737 f: F)
738 -> DecodeResult<T> where
739 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
740 {
741 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
742 f(self)
743 }
744
c34b1796 745 fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
746 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
747 {
748 debug!("read_struct(name={})", name);
749 f(self)
750 }
751
c34b1796 752 fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
753 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
754 {
755 debug!("read_struct_field(name={}, idx={})", name, idx);
1a4d82fc
JJ
756 f(self)
757 }
758
c34b1796 759 fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
760 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
761 {
762 debug!("read_tuple()");
763 self.read_seq(move |d, len| {
764 if len == tuple_len {
765 f(d)
766 } else {
767 Err(Expected(format!("Expected tuple of length `{}`, \
768 found tuple of length `{}`", tuple_len, len)))
769 }
770 })
771 }
772
c34b1796 773 fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
774 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
775 {
776 debug!("read_tuple_arg(idx={})", idx);
777 self.read_seq_elt(idx, f)
778 }
779
c34b1796 780 fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
781 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
782 {
783 debug!("read_tuple_struct(name={})", name);
784 self.read_tuple(len, f)
785 }
786
787 fn read_tuple_struct_arg<T, F>(&mut self,
c34b1796 788 idx: usize,
1a4d82fc
JJ
789 f: F)
790 -> DecodeResult<T> where
791 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
792 {
793 debug!("read_tuple_struct_arg(idx={})", idx);
794 self.read_tuple_arg(idx, f)
795 }
796
797 fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
798 F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
799 {
800 debug!("read_option()");
801 self.read_enum("Option", move |this| {
802 this.read_enum_variant(&["None", "Some"], move |this, idx| {
803 match idx {
804 0 => f(this, false),
805 1 => f(this, true),
806 _ => {
807 Err(Expected(format!("Expected None or Some")))
808 }
809 }
810 })
811 })
812 }
813
814 fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
c34b1796 815 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
1a4d82fc
JJ
816 {
817 debug!("read_seq()");
818 self.push_doc(EsVec, move |d| {
c34b1796 819 let len = try!(d._next_sub());
1a4d82fc
JJ
820 debug!(" len={}", len);
821 f(d, len)
822 })
823 }
824
c34b1796 825 fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
826 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
827 {
828 debug!("read_seq_elt(idx={})", idx);
829 self.push_doc(EsVecElt, f)
830 }
831
832 fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
c34b1796 833 F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
1a4d82fc
JJ
834 {
835 debug!("read_map()");
836 self.push_doc(EsMap, move |d| {
c34b1796 837 let len = try!(d._next_sub());
1a4d82fc
JJ
838 debug!(" len={}", len);
839 f(d, len)
840 })
841 }
842
c34b1796 843 fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
844 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
845 {
846 debug!("read_map_elt_key(idx={})", idx);
847 self.push_doc(EsMapKey, f)
848 }
849
c34b1796 850 fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
1a4d82fc
JJ
851 F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
852 {
853 debug!("read_map_elt_val(idx={})", idx);
854 self.push_doc(EsMapVal, f)
855 }
856
857 fn error(&mut self, err: &str) -> Error {
858 ApplicationError(err.to_string())
859 }
860 }
861}
862
863pub mod writer {
1a4d82fc 864 use std::mem;
c34b1796
AL
865 use std::io::prelude::*;
866 use std::io::{self, SeekFrom, Cursor};
867 use std::slice::bytes;
1a4d82fc 868
c34b1796
AL
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 };
1a4d82fc
JJ
873
874 use serialize;
875
876
c34b1796 877 pub type EncodeResult = io::Result<()>;
1a4d82fc
JJ
878
879 // rbml writing
c34b1796
AL
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
1a4d82fc
JJ
884 }
885
c34b1796
AL
886 fn write_tag<W: Write>(w: &mut W, n: usize) -> EncodeResult {
887 if n < 0xf0 {
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])
891 } else {
892 Err(io::Error::new(io::ErrorKind::Other,
893 &format!("invalid tag: {}", n)[..]))
894 }
895 }
896
897 fn write_sized_vuint<W: Write>(w: &mut W, n: usize, size: usize) -> EncodeResult {
1a4d82fc 898 match size {
c34b1796
AL
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,
1a4d82fc 902 n as u8]),
c34b1796 903 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
85aaf69f 904 (n >> 8) as u8, n as u8]),
c34b1796
AL
905 _ => Err(io::Error::new(io::ErrorKind::Other,
906 &format!("isize too big: {}", n)[..]))
1a4d82fc
JJ
907 }
908 }
909
c34b1796 910 fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
85aaf69f
SL
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); }
c34b1796
AL
915 Err(io::Error::new(io::ErrorKind::Other,
916 &format!("isize too big: {}", n)[..]))
1a4d82fc
JJ
917 }
918
c34b1796
AL
919 impl<'a> Encoder<'a> {
920 pub fn new(w: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
1a4d82fc
JJ
921 Encoder {
922 writer: w,
923 size_positions: vec!(),
c34b1796 924 relax_limit: 0,
1a4d82fc
JJ
925 }
926 }
927
928 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
c34b1796 929 pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
1a4d82fc
JJ
930 Encoder {
931 writer: mem::transmute_copy(&self.writer),
932 size_positions: self.size_positions.clone(),
c34b1796 933 relax_limit: self.relax_limit,
1a4d82fc
JJ
934 }
935 }
936
c34b1796 937 pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
1a4d82fc 938 debug!("Start tag {:?}", tag_id);
c34b1796 939 assert!(tag_id >= NUM_IMPLICIT_TAGS);
1a4d82fc
JJ
940
941 // Write the enum ID:
c34b1796 942 try!(write_tag(self.writer, tag_id));
1a4d82fc
JJ
943
944 // Write a placeholder four-byte size.
c34b1796
AL
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];
85aaf69f 948 self.writer.write_all(zeroes)
1a4d82fc
JJ
949 }
950
951 pub fn end_tag(&mut self) -> EncodeResult {
952 let last_size_pos = self.size_positions.pop().unwrap();
c34b1796
AL
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;
956
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];
963 {
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);
967 }
968
969 // overwrite the size and data and continue
970 try!(write_vuint(self.writer, size));
971 try!(self.writer.write_all(&buf[..size]));
972 } else {
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)));
976 }
1a4d82fc
JJ
977
978 debug!("End tag (size = {:?})", size);
c34b1796 979 Ok(())
1a4d82fc
JJ
980 }
981
c34b1796 982 pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult where
1a4d82fc
JJ
983 F: FnOnce() -> EncodeResult,
984 {
985 try!(self.start_tag(tag_id));
986 try!(blk());
987 self.end_tag()
988 }
989
c34b1796
AL
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));
1a4d82fc 993 try!(write_vuint(self.writer, b.len()));
85aaf69f 994 self.writer.write_all(b)
1a4d82fc
JJ
995 }
996
c34b1796
AL
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)
1a4d82fc
JJ
1000 }
1001
c34b1796
AL
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)
1a4d82fc
JJ
1005 }
1006
c34b1796
AL
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)
1a4d82fc
JJ
1010 }
1011
c34b1796 1012 pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1a4d82fc
JJ
1013 self.wr_tagged_bytes(tag_id, &[v])
1014 }
1015
c34b1796
AL
1016 pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
1017 self.wr_tagged_u64(tag_id, v as u64)
1a4d82fc
JJ
1018 }
1019
c34b1796
AL
1020 pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
1021 self.wr_tagged_u32(tag_id, v as u32)
1a4d82fc
JJ
1022 }
1023
c34b1796
AL
1024 pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
1025 self.wr_tagged_u16(tag_id, v as u16)
1a4d82fc
JJ
1026 }
1027
c34b1796 1028 pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
1a4d82fc
JJ
1029 self.wr_tagged_bytes(tag_id, &[v as u8])
1030 }
1031
c34b1796 1032 pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
1a4d82fc
JJ
1033 self.wr_tagged_bytes(tag_id, v.as_bytes())
1034 }
1035
c34b1796
AL
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)
1040 }
1041
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)
1045 }
1046
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)
1050 }
1051
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)
1055 }
1056
1057 fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
1058 self.wr_tagged_raw_bytes(tag_id, &[v])
1059 }
1060
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)
1063 }
1064
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)
1067 }
1068
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)
1071 }
1072
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])
1075 }
1076
1a4d82fc
JJ
1077 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
1078 debug!("Write {:?} bytes", b.len());
85aaf69f 1079 self.writer.write_all(b)
1a4d82fc
JJ
1080 }
1081
1082 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
1083 debug!("Write str: {:?}", s);
85aaf69f 1084 self.writer.write_all(s.as_bytes())
1a4d82fc 1085 }
1a4d82fc 1086
c34b1796
AL
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;
1093 }
1094 pos
1a4d82fc 1095 }
c34b1796 1096 }
1a4d82fc 1097
c34b1796
AL
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 {
9346a6ac
AL
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)
c34b1796
AL
1105 } else {
1106 Err(io::Error::new(io::ErrorKind::Other,
1107 &format!("length or variant id too big: {}",
1108 v)[..]))
1109 }
1a4d82fc
JJ
1110 }
1111
1112 pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
c34b1796 1113 F: FnOnce(&mut Encoder) -> EncodeResult,
1a4d82fc 1114 {
c34b1796 1115 try!(self.start_tag(EsOpaque as usize));
1a4d82fc
JJ
1116 try!(f(self));
1117 self.end_tag()
1118 }
1119 }
1120
c34b1796
AL
1121 impl<'a> serialize::Encoder for Encoder<'a> {
1122 type Error = io::Error;
1a4d82fc
JJ
1123
1124 fn emit_nil(&mut self) -> EncodeResult {
1125 Ok(())
1126 }
1127
c34b1796
AL
1128 fn emit_uint(&mut self, v: usize) -> EncodeResult {
1129 self.emit_u64(v as u64)
1a4d82fc
JJ
1130 }
1131 fn emit_u64(&mut self, v: u64) -> EncodeResult {
9346a6ac
AL
1132 if v as u32 as u64 == v {
1133 self.emit_u32(v as u32)
1134 } else {
1135 self.wr_tagged_raw_u64(EsU64 as usize, v)
c34b1796 1136 }
1a4d82fc
JJ
1137 }
1138 fn emit_u32(&mut self, v: u32) -> EncodeResult {
9346a6ac
AL
1139 if v as u16 as u32 == v {
1140 self.emit_u16(v as u16)
1141 } else {
1142 self.wr_tagged_raw_u32(EsU32 as usize, v)
c34b1796 1143 }
1a4d82fc
JJ
1144 }
1145 fn emit_u16(&mut self, v: u16) -> EncodeResult {
9346a6ac
AL
1146 if v as u8 as u16 == v {
1147 self.emit_u8(v as u8)
1148 } else {
1149 self.wr_tagged_raw_u16(EsU16 as usize, v)
c34b1796 1150 }
1a4d82fc
JJ
1151 }
1152 fn emit_u8(&mut self, v: u8) -> EncodeResult {
c34b1796 1153 self.wr_tagged_raw_u8(EsU8 as usize, v)
1a4d82fc
JJ
1154 }
1155
c34b1796
AL
1156 fn emit_int(&mut self, v: isize) -> EncodeResult {
1157 self.emit_i64(v as i64)
1a4d82fc
JJ
1158 }
1159 fn emit_i64(&mut self, v: i64) -> EncodeResult {
9346a6ac
AL
1160 if v as i32 as i64 == v {
1161 self.emit_i32(v as i32)
1162 } else {
1163 self.wr_tagged_raw_i64(EsI64 as usize, v)
c34b1796 1164 }
1a4d82fc
JJ
1165 }
1166 fn emit_i32(&mut self, v: i32) -> EncodeResult {
9346a6ac
AL
1167 if v as i16 as i32 == v {
1168 self.emit_i16(v as i16)
1169 } else {
1170 self.wr_tagged_raw_i32(EsI32 as usize, v)
c34b1796 1171 }
1a4d82fc
JJ
1172 }
1173 fn emit_i16(&mut self, v: i16) -> EncodeResult {
9346a6ac
AL
1174 if v as i8 as i16 == v {
1175 self.emit_i8(v as i8)
1176 } else {
1177 self.wr_tagged_raw_i16(EsI16 as usize, v)
c34b1796 1178 }
1a4d82fc
JJ
1179 }
1180 fn emit_i8(&mut self, v: i8) -> EncodeResult {
c34b1796 1181 self.wr_tagged_raw_i8(EsI8 as usize, v)
1a4d82fc
JJ
1182 }
1183
1184 fn emit_bool(&mut self, v: bool) -> EncodeResult {
c34b1796 1185 self.wr_tagged_raw_u8(EsBool as usize, v as u8)
1a4d82fc
JJ
1186 }
1187
1188 fn emit_f64(&mut self, v: f64) -> EncodeResult {
1189 let bits = unsafe { mem::transmute(v) };
c34b1796 1190 self.wr_tagged_raw_u64(EsF64 as usize, bits)
1a4d82fc
JJ
1191 }
1192 fn emit_f32(&mut self, v: f32) -> EncodeResult {
1193 let bits = unsafe { mem::transmute(v) };
c34b1796 1194 self.wr_tagged_raw_u32(EsF32 as usize, bits)
1a4d82fc
JJ
1195 }
1196 fn emit_char(&mut self, v: char) -> EncodeResult {
c34b1796 1197 self.wr_tagged_raw_u32(EsChar as usize, v as u32)
1a4d82fc
JJ
1198 }
1199
1200 fn emit_str(&mut self, v: &str) -> EncodeResult {
c34b1796 1201 self.wr_tagged_str(EsStr as usize, v)
1a4d82fc
JJ
1202 }
1203
c34b1796
AL
1204 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
1205 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1206 {
c34b1796 1207 try!(self.start_tag(EsEnum as usize));
1a4d82fc
JJ
1208 try!(f(self));
1209 self.end_tag()
1210 }
1211
1212 fn emit_enum_variant<F>(&mut self,
1213 _: &str,
c34b1796
AL
1214 v_id: usize,
1215 _: usize,
1a4d82fc 1216 f: F) -> EncodeResult where
c34b1796 1217 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1218 {
c34b1796
AL
1219 try!(self._emit_tagged_sub(v_id));
1220 f(self)
1a4d82fc
JJ
1221 }
1222
c34b1796
AL
1223 fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult where
1224 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1225 {
1226 f(self)
1227 }
1228
1229 fn emit_enum_struct_variant<F>(&mut self,
1230 v_name: &str,
c34b1796
AL
1231 v_id: usize,
1232 cnt: usize,
1a4d82fc 1233 f: F) -> EncodeResult where
c34b1796 1234 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1235 {
1236 self.emit_enum_variant(v_name, v_id, cnt, f)
1237 }
1238
1239 fn emit_enum_struct_variant_field<F>(&mut self,
1240 _: &str,
c34b1796 1241 idx: usize,
1a4d82fc 1242 f: F) -> EncodeResult where
c34b1796 1243 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1244 {
1245 self.emit_enum_variant_arg(idx, f)
1246 }
1247
c34b1796
AL
1248 fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where
1249 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1250 {
1251 f(self)
1252 }
1253
c34b1796
AL
1254 fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where
1255 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1256 {
1a4d82fc
JJ
1257 f(self)
1258 }
1259
c34b1796
AL
1260 fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
1261 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1262 {
1263 self.emit_seq(len, f)
1264 }
c34b1796
AL
1265 fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1266 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1267 {
1268 self.emit_seq_elt(idx, f)
1269 }
1270
c34b1796
AL
1271 fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
1272 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1273 {
1274 self.emit_seq(len, f)
1275 }
c34b1796
AL
1276 fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
1277 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1278 {
1279 self.emit_seq_elt(idx, f)
1280 }
1281
1282 fn emit_option<F>(&mut self, f: F) -> EncodeResult where
c34b1796 1283 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1284 {
1285 self.emit_enum("Option", f)
1286 }
1287 fn emit_option_none(&mut self) -> EncodeResult {
1288 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1289 }
1290 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
c34b1796 1291 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1292 {
1293
1294 self.emit_enum_variant("Some", 1, 1, f)
1295 }
1296
c34b1796
AL
1297 fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
1298 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1299 {
c34b1796
AL
1300 if len == 0 {
1301 // empty vector optimization
1302 return self.wr_tagged_bytes(EsVec as usize, &[]);
1303 }
1a4d82fc 1304
c34b1796
AL
1305 try!(self.start_tag(EsVec as usize));
1306 try!(self._emit_tagged_sub(len));
1a4d82fc
JJ
1307 try!(f(self));
1308 self.end_tag()
1309 }
1310
c34b1796
AL
1311 fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1312 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1313 {
1314
c34b1796 1315 try!(self.start_tag(EsVecElt as usize));
1a4d82fc
JJ
1316 try!(f(self));
1317 self.end_tag()
1318 }
1319
c34b1796
AL
1320 fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
1321 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1322 {
c34b1796
AL
1323 if len == 0 {
1324 // empty map optimization
1325 return self.wr_tagged_bytes(EsMap as usize, &[]);
1326 }
1a4d82fc 1327
c34b1796
AL
1328 try!(self.start_tag(EsMap as usize));
1329 try!(self._emit_tagged_sub(len));
1a4d82fc
JJ
1330 try!(f(self));
1331 self.end_tag()
1332 }
1333
c34b1796
AL
1334 fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1335 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc
JJ
1336 {
1337
c34b1796 1338 try!(self.start_tag(EsMapKey as usize));
1a4d82fc
JJ
1339 try!(f(self));
1340 self.end_tag()
1341 }
1342
c34b1796
AL
1343 fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
1344 F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
1a4d82fc 1345 {
c34b1796 1346 try!(self.start_tag(EsMapVal as usize));
1a4d82fc
JJ
1347 try!(f(self));
1348 self.end_tag()
1349 }
1350 }
1351}
1352
1353// ___________________________________________________________________________
1354// Testing
1355
1356#[cfg(test)]
1357mod tests {
1358 use super::{Doc, reader, writer};
1a4d82fc
JJ
1359
1360 use serialize::{Encodable, Decodable};
1361
c34b1796 1362 use std::io::Cursor;
1a4d82fc
JJ
1363
1364 #[test]
1365 fn test_vuint_at() {
1366 let data = &[
1367 0x80,
1368 0xff,
1369 0x40, 0x00,
1370 0x7f, 0xff,
1371 0x20, 0x00, 0x00,
1372 0x3f, 0xff, 0xff,
1373 0x10, 0x00, 0x00, 0x00,
1374 0x1f, 0xff, 0xff, 0xff
1375 ];
1376
1377 let mut res: reader::Res;
1378
1379 // Class A
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);
1386
1387 // Class B
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);
1394
1395 // Class C
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);
1402
1403 // Class D
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);
1410 }
1411
1412 #[test]
1413 fn test_option_int() {
c34b1796 1414 fn test_v(v: Option<isize>) {
1a4d82fc 1415 debug!("v == {:?}", v);
c34b1796 1416 let mut wr = Cursor::new(Vec::new());
1a4d82fc
JJ
1417 {
1418 let mut rbml_w = writer::Encoder::new(&mut wr);
1419 let _ = v.encode(&mut rbml_w);
1420 }
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);
1425 assert_eq!(v, v1);
1426 }
1427
1428 test_v(Some(22));
1429 test_v(None);
1430 test_v(Some(3));
1431 }
1432}
1433
1434#[cfg(test)]
1435mod bench {
1436 #![allow(non_snake_case)]
1437 use test::Bencher;
1438 use super::reader;
1439
1440 #[bench]
1441 pub fn vuint_at_A_aligned(b: &mut Bencher) {
c34b1796 1442 let data = (0..4*100).map(|i| {
1a4d82fc 1443 match i % 2 {
c34b1796 1444 0 => 0x80,
1a4d82fc
JJ
1445 _ => i as u8,
1446 }
1447 }).collect::<Vec<_>>();
85aaf69f 1448 let mut sum = 0;
1a4d82fc
JJ
1449 b.iter(|| {
1450 let mut i = 0;
1451 while i < data.len() {
85aaf69f 1452 sum += reader::vuint_at(&data, i).unwrap().val;
1a4d82fc
JJ
1453 i += 4;
1454 }
1455 });
1456 }
1457
1458 #[bench]
1459 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
c34b1796 1460 let data = (0..4*100+1).map(|i| {
1a4d82fc 1461 match i % 2 {
c34b1796 1462 1 => 0x80,
1a4d82fc
JJ
1463 _ => i as u8
1464 }
1465 }).collect::<Vec<_>>();
85aaf69f 1466 let mut sum = 0;
1a4d82fc
JJ
1467 b.iter(|| {
1468 let mut i = 1;
1469 while i < data.len() {
85aaf69f 1470 sum += reader::vuint_at(&data, i).unwrap().val;
1a4d82fc
JJ
1471 i += 4;
1472 }
1473 });
1474 }
1475
1476 #[bench]
1477 pub fn vuint_at_D_aligned(b: &mut Bencher) {
c34b1796 1478 let data = (0..4*100).map(|i| {
1a4d82fc 1479 match i % 4 {
c34b1796 1480 0 => 0x10,
1a4d82fc 1481 3 => i as u8,
c34b1796 1482 _ => 0
1a4d82fc
JJ
1483 }
1484 }).collect::<Vec<_>>();
85aaf69f 1485 let mut sum = 0;
1a4d82fc
JJ
1486 b.iter(|| {
1487 let mut i = 0;
1488 while i < data.len() {
85aaf69f 1489 sum += reader::vuint_at(&data, i).unwrap().val;
1a4d82fc
JJ
1490 i += 4;
1491 }
1492 });
1493 }
1494
1495 #[bench]
1496 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
c34b1796 1497 let data = (0..4*100+1).map(|i| {
1a4d82fc 1498 match i % 4 {
c34b1796 1499 1 => 0x10,
1a4d82fc 1500 0 => i as u8,
c34b1796 1501 _ => 0
1a4d82fc
JJ
1502 }
1503 }).collect::<Vec<_>>();
85aaf69f 1504 let mut sum = 0;
1a4d82fc
JJ
1505 b.iter(|| {
1506 let mut i = 1;
1507 while i < data.len() {
85aaf69f 1508 sum += reader::vuint_at(&data, i).unwrap().val;
1a4d82fc
JJ
1509 i += 4;
1510 }
1511 });
1512 }
1513}