1 // Copyright 2012-2014 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 a temporary measure until we migrate
12 //! the rust object metadata to a better serialization format. It is not
13 //! intended to be used by users.
15 //! It is loosely based on the Extensible Binary Markup Language (ebml):
16 //! http://www.matroska.org/technical/specs/rfc/index.html
18 #![crate_name = "rbml"]
20 #![crate_type = "rlib"]
21 #![crate_type = "dylib"]
22 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
23 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
24 html_root_url = "http://doc.rust-lang.org/nightly/",
25 html_playground_url = "http://play.rust-lang.org/")]
26 #![allow(unknown_features)]
27 #![feature(macro_rules, phase, slicing_syntax, globs)]
28 #![allow(missing_docs)]
30 extern crate serialize;
32 #[phase(plugin, link)] extern crate log;
33 #[cfg(test)] extern crate test;
35 pub use self::EbmlEncoderTag::*;
36 pub use self::Error::*;
42 /// Common data structures
50 impl<'doc> Copy for Doc<'doc> {}
52 impl<'doc> Doc<'doc> {
53 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
54 Doc { data: data, start: 0u, end: data.len() }
57 pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
58 reader::get_doc(*self, tag)
61 pub fn as_str_slice<'a>(&'a self) -> &'a str {
62 str::from_utf8(self.data[self.start..self.end]).unwrap()
65 pub fn as_str(&self) -> String {
66 self.as_str_slice().to_string()
70 pub struct TaggedDoc<'a> {
76 pub enum EbmlEncoderTag {
106 EsLabel, // Used only when debugging
109 impl Copy for EbmlEncoderTag {}
115 IoError(std::io::IoError),
116 ApplicationError(String)
118 // --------------------------------------
124 use std::io::extensions::u64_from_be_bytes;
125 use std::mem::transmute;
127 use std::option::Option;
128 use std::option::Option::{None, Some};
132 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt,
133 EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
134 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
135 EsEnumBody, EsUint, EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc,
136 Error, IntTooBig, Expected };
138 pub type DecodeResult<T> = Result<T, Error>;
142 ($e:expr, $r:expr) => (
146 debug!("ignored error: {}", e);
161 fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
163 if a & 0x80u8 != 0u8 {
164 return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
166 if a & 0x40u8 != 0u8 {
167 return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
168 (data[start + 1u] as uint),
171 if a & 0x20u8 != 0u8 {
172 return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
173 (data[start + 1u] as uint) << 8u |
174 (data[start + 2u] as uint),
177 if a & 0x10u8 != 0u8 {
178 return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
179 (data[start + 1u] as uint) << 16u |
180 (data[start + 2u] as uint) << 8u |
181 (data[start + 3u] as uint),
184 Err(IntTooBig(a as uint))
187 pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
188 if data.len() - start < 4 {
189 return vuint_at_slow(data, start);
192 // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
193 // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
194 // Using the four most significant bits of the u32 we lookup in the table below how the
195 // element ID should be derived from it.
197 // The table stores tuples (shift, mask) where shift is the number the u32 should be right
198 // shifted with and mask is the value the right shifted value should be masked with.
199 // If for example the most significant bit is set this means it's a class A ID and the u32
200 // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
201 // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
203 // By storing the number of shifts and masks in a table instead of checking in order if
204 // the most significant bit is set, the second most significant bit is set etc. we can
205 // replace up to three "and+branch" with a single table lookup which gives us a measured
206 // speedup of around 2x on x86_64.
207 static SHIFT_MASK_TABLE: [(uint, u32), ..16] = [
208 (0, 0x0), (0, 0x0fffffff),
209 (8, 0x1fffff), (8, 0x1fffff),
210 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
211 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
212 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
216 let ptr = data.as_ptr().offset(start as int) as *const u32;
217 let val = Int::from_be(*ptr);
219 let i = (val >> 28u) as uint;
220 let (shift, mask) = SHIFT_MASK_TABLE[i];
222 val: ((val >> shift) & mask) as uint,
223 next: start + (((32 - shift) >> 3) as uint)
228 pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
229 let elt_tag = try!(vuint_at(data, start));
230 let elt_size = try!(vuint_at(data, elt_tag.next));
231 let end = elt_size.next + elt_size.val;
234 doc: Doc { data: data, start: elt_size.next, end: end }
238 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
239 let mut pos = d.start;
241 let elt_tag = try_or!(vuint_at(d.data, pos), None);
242 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
243 pos = elt_size.next + elt_size.val;
244 if elt_tag.val == tg {
245 return Some(Doc { data: d.data, start: elt_size.next,
252 pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
253 match maybe_get_doc(d, tg) {
256 error!("failed to find block with tag {}", tg);
262 pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
263 let mut pos = d.start;
265 let elt_tag = try_or!(vuint_at(d.data, pos), false);
266 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
267 pos = elt_size.next + elt_size.val;
268 let doc = Doc { data: d.data, start: elt_size.next, end: pos };
269 if !it(elt_tag.val, doc) {
276 pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
277 let mut pos = d.start;
279 let elt_tag = try_or!(vuint_at(d.data, pos), false);
280 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
281 pos = elt_size.next + elt_size.val;
282 if elt_tag.val == tg {
283 let doc = Doc { data: d.data, start: elt_size.next,
293 pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
294 f(d.data[d.start..d.end])
298 pub fn doc_as_u8(d: Doc) -> u8 {
299 assert_eq!(d.end, d.start + 1u);
303 pub fn doc_as_u16(d: Doc) -> u16 {
304 assert_eq!(d.end, d.start + 2u);
305 u64_from_be_bytes(d.data, d.start, 2u) as u16
308 pub fn doc_as_u32(d: Doc) -> u32 {
309 assert_eq!(d.end, d.start + 4u);
310 u64_from_be_bytes(d.data, d.start, 4u) as u32
313 pub fn doc_as_u64(d: Doc) -> u64 {
314 assert_eq!(d.end, d.start + 8u);
315 u64_from_be_bytes(d.data, d.start, 8u)
318 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
319 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
320 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
321 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
323 pub struct Decoder<'a> {
328 impl<'doc> Decoder<'doc> {
329 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
336 fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
337 if self.pos < self.parent.end {
338 let TaggedDoc { tag: r_tag, doc: r_doc } =
339 try!(doc_at(self.parent.data, self.pos));
341 if r_tag == (EsLabel as uint) {
342 self.pos = r_doc.end;
343 let str = r_doc.as_str_slice();
345 return Err(Expected(format!("Expected label {} but \
346 found {}", lbl, str)));
353 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
354 debug!(". next_doc(exp_tag={})", exp_tag);
355 if self.pos >= self.parent.end {
356 return Err(Expected(format!("no more documents in \
359 let TaggedDoc { tag: r_tag, doc: r_doc } =
360 try!(doc_at(self.parent.data, self.pos));
361 debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
368 if r_tag != (exp_tag as uint) {
369 return Err(Expected(format!("expected EBML doc with tag {} but \
370 found tag {}", exp_tag, r_tag)));
372 if r_doc.end > self.parent.end {
373 return Err(Expected(format!("invalid EBML, child extends to \
374 {:#x}, parent to {:#x}",
375 r_doc.end, self.parent.end)));
377 self.pos = r_doc.end;
381 fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
382 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
383 let d = try!(self.next_doc(exp_tag));
384 let old_parent = self.parent;
385 let old_pos = self.pos;
388 let r = try!(f(self));
389 self.parent = old_parent;
394 fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
395 let r = doc_as_u32(try!(self.next_doc(exp_tag)));
396 debug!("_next_uint exp_tag={} result={}", exp_tag, r);
400 pub fn read_opaque<R>(&mut self,
401 op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
402 let doc = try!(self.next_doc(EsOpaque));
404 let (old_parent, old_pos) = (self.parent, self.pos);
406 self.pos = doc.start;
408 let result = try!(op(self, doc));
410 self.parent = old_parent;
416 impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
417 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
419 fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
420 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
421 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
422 fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
423 fn read_uint(&mut self) -> DecodeResult<uint> {
424 let v = doc_as_u64(try!(self.next_doc(EsUint)));
425 if v > (::std::uint::MAX as u64) {
426 Err(IntTooBig(v as uint))
432 fn read_i64(&mut self) -> DecodeResult<i64> {
433 Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
435 fn read_i32(&mut self) -> DecodeResult<i32> {
436 Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
438 fn read_i16(&mut self) -> DecodeResult<i16> {
439 Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
441 fn read_i8 (&mut self) -> DecodeResult<i8> {
442 Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
444 fn read_int(&mut self) -> DecodeResult<int> {
445 let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
446 if v > (int::MAX as i64) || v < (int::MIN as i64) {
447 debug!("FIXME \\#6122: Removing this makes this function miscompile");
448 Err(IntTooBig(v as uint))
454 fn read_bool(&mut self) -> DecodeResult<bool> {
455 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
458 fn read_f64(&mut self) -> DecodeResult<f64> {
459 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
460 Ok(unsafe { transmute(bits) })
462 fn read_f32(&mut self) -> DecodeResult<f32> {
463 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
464 Ok(unsafe { transmute(bits) })
466 fn read_char(&mut self) -> DecodeResult<char> {
467 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
469 fn read_str(&mut self) -> DecodeResult<String> {
470 Ok(try!(self.next_doc(EsStr)).as_str())
474 fn read_enum<T>(&mut self,
476 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
477 debug!("read_enum({})", name);
478 try!(self._check_label(name));
480 let doc = try!(self.next_doc(EsEnum));
482 let (old_parent, old_pos) = (self.parent, self.pos);
484 self.pos = self.parent.start;
486 let result = try!(f(self));
488 self.parent = old_parent;
493 fn read_enum_variant<T>(&mut self,
495 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
497 debug!("read_enum_variant()");
498 let idx = try!(self._next_uint(EsEnumVid));
499 debug!(" idx={}", idx);
501 let doc = try!(self.next_doc(EsEnumBody));
503 let (old_parent, old_pos) = (self.parent, self.pos);
505 self.pos = self.parent.start;
507 let result = try!(f(self, idx));
509 self.parent = old_parent;
514 fn read_enum_variant_arg<T>(&mut self,
516 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
517 debug!("read_enum_variant_arg(idx={})", idx);
521 fn read_enum_struct_variant<T>(&mut self,
523 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
525 debug!("read_enum_struct_variant()");
526 let idx = try!(self._next_uint(EsEnumVid));
527 debug!(" idx={}", idx);
529 let doc = try!(self.next_doc(EsEnumBody));
531 let (old_parent, old_pos) = (self.parent, self.pos);
533 self.pos = self.parent.start;
535 let result = try!(f(self, idx));
537 self.parent = old_parent;
542 fn read_enum_struct_variant_field<T>(&mut self,
545 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
547 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
551 fn read_struct<T>(&mut self,
554 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
556 debug!("read_struct(name={})", name);
560 fn read_struct_field<T>(&mut self,
563 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
565 debug!("read_struct_field(name={}, idx={})", name, idx);
566 try!(self._check_label(name));
570 fn read_tuple<T>(&mut self,
572 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
573 debug!("read_tuple()");
574 self.read_seq(|d, len| {
575 if len == tuple_len {
578 Err(Expected(format!("Expected tuple of length `{}`, \
579 found tuple of length `{}`", tuple_len, len)))
584 fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
586 debug!("read_tuple_arg(idx={})", idx);
587 self.read_seq_elt(idx, f)
590 fn read_tuple_struct<T>(&mut self,
593 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
595 debug!("read_tuple_struct(name={})", name);
596 self.read_tuple(len, f)
599 fn read_tuple_struct_arg<T>(&mut self,
601 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
603 debug!("read_tuple_struct_arg(idx={})", idx);
604 self.read_tuple_arg(idx, f)
607 fn read_option<T>(&mut self,
608 f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
609 debug!("read_option()");
610 self.read_enum("Option", |this| {
611 this.read_enum_variant(&["None", "Some"], |this, idx| {
616 Err(Expected(format!("Expected None or Some")))
623 fn read_seq<T>(&mut self,
624 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
625 debug!("read_seq()");
626 self.push_doc(EsVec, |d| {
627 let len = try!(d._next_uint(EsVecLen));
628 debug!(" len={}", len);
633 fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
635 debug!("read_seq_elt(idx={})", idx);
636 self.push_doc(EsVecElt, f)
639 fn read_map<T>(&mut self,
640 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
641 debug!("read_map()");
642 self.push_doc(EsMap, |d| {
643 let len = try!(d._next_uint(EsMapLen));
644 debug!(" len={}", len);
649 fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
651 debug!("read_map_elt_key(idx={})", idx);
652 self.push_doc(EsMapKey, f)
655 fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
657 debug!("read_map_elt_val(idx={})", idx);
658 self.push_doc(EsMapVal, f)
661 fn error(&mut self, err: &str) -> Error {
662 ApplicationError(err.to_string())
668 use std::clone::Clone;
669 use std::io::extensions::u64_to_be_bytes;
670 use std::io::{Writer, Seek};
674 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
675 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
676 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
677 EsOpaque, EsLabel, EbmlEncoderTag };
682 pub type EncodeResult = io::IoResult<()>;
685 pub struct Encoder<'a, W:'a> {
686 pub writer: &'a mut W,
687 size_positions: Vec<uint>,
690 fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
692 1u => w.write(&[0x80u8 | (n as u8)]),
693 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
694 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
696 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
697 (n >> 8_u) as u8, n as u8]),
698 _ => Err(io::IoError {
699 kind: io::OtherIoError,
701 detail: Some(format!("{}", n))
706 fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
707 if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
708 if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
709 if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
710 if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
712 kind: io::OtherIoError,
714 detail: Some(format!("{}", n))
718 // FIXME (#2741): Provide a function to write the standard rbml header.
719 impl<'a, W: Writer + Seek> Encoder<'a, W> {
720 pub fn new(w: &'a mut W) -> Encoder<'a, W> {
723 size_positions: vec!(),
727 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
728 pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
730 writer: mem::transmute_copy(&self.writer),
731 size_positions: self.size_positions.clone(),
735 pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
736 debug!("Start tag {}", tag_id);
738 // Write the enum ID:
739 try!(write_vuint(self.writer, tag_id));
741 // Write a placeholder four-byte size.
742 self.size_positions.push(try!(self.writer.tell()) as uint);
743 let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
744 self.writer.write(zeroes)
747 pub fn end_tag(&mut self) -> EncodeResult {
748 let last_size_pos = self.size_positions.pop().unwrap();
749 let cur_pos = try!(self.writer.tell());
750 try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
751 let size = cur_pos as uint - last_size_pos - 4;
752 try!(write_sized_vuint(self.writer, size, 4u));
753 let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
755 debug!("End tag (size = {})", size);
759 pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
760 try!(self.start_tag(tag_id));
765 pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
766 try!(write_vuint(self.writer, tag_id));
767 try!(write_vuint(self.writer, b.len()));
771 pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
772 u64_to_be_bytes(v, 8u, |v| {
773 self.wr_tagged_bytes(tag_id, v)
777 pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
778 u64_to_be_bytes(v as u64, 4u, |v| {
779 self.wr_tagged_bytes(tag_id, v)
783 pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
784 u64_to_be_bytes(v as u64, 2u, |v| {
785 self.wr_tagged_bytes(tag_id, v)
789 pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
790 self.wr_tagged_bytes(tag_id, &[v])
793 pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
794 u64_to_be_bytes(v as u64, 8u, |v| {
795 self.wr_tagged_bytes(tag_id, v)
799 pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
800 u64_to_be_bytes(v as u64, 4u, |v| {
801 self.wr_tagged_bytes(tag_id, v)
805 pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
806 u64_to_be_bytes(v as u64, 2u, |v| {
807 self.wr_tagged_bytes(tag_id, v)
811 pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
812 self.wr_tagged_bytes(tag_id, &[v as u8])
815 pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
816 self.wr_tagged_bytes(tag_id, v.as_bytes())
819 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
820 debug!("Write {} bytes", b.len());
824 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
825 debug!("Write str: {}", s);
826 self.writer.write(s.as_bytes())
830 // FIXME (#2743): optionally perform "relaxations" on end_tag to more
831 // efficiently encode sizes; this is a fixed point iteration
833 // Set to true to generate more debugging in EBML code.
834 // Totally lame approach.
835 static DEBUG: bool = true;
837 impl<'a, W: Writer + Seek> Encoder<'a, W> {
838 // used internally to emit things like the vector length and so on
839 fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
840 assert!(v <= 0xFFFF_FFFF_u);
841 self.wr_tagged_u32(t as uint, v as u32)
844 fn _emit_label(&mut self, label: &str) -> EncodeResult {
845 // There are various strings that we have access to, such as
846 // the name of a record field, which do not actually appear in
847 // the encoded EBML (normally). This is just for
848 // efficiency. When debugging, though, we can emit such
849 // labels and then they will be checked by decoder to
850 // try and check panics more quickly.
851 if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
855 pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
856 try!(self.start_tag(EsOpaque as uint));
862 impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
863 fn emit_nil(&mut self) -> EncodeResult {
867 fn emit_uint(&mut self, v: uint) -> EncodeResult {
868 self.wr_tagged_u64(EsUint as uint, v as u64)
870 fn emit_u64(&mut self, v: u64) -> EncodeResult {
871 self.wr_tagged_u64(EsU64 as uint, v)
873 fn emit_u32(&mut self, v: u32) -> EncodeResult {
874 self.wr_tagged_u32(EsU32 as uint, v)
876 fn emit_u16(&mut self, v: u16) -> EncodeResult {
877 self.wr_tagged_u16(EsU16 as uint, v)
879 fn emit_u8(&mut self, v: u8) -> EncodeResult {
880 self.wr_tagged_u8(EsU8 as uint, v)
883 fn emit_int(&mut self, v: int) -> EncodeResult {
884 self.wr_tagged_i64(EsInt as uint, v as i64)
886 fn emit_i64(&mut self, v: i64) -> EncodeResult {
887 self.wr_tagged_i64(EsI64 as uint, v)
889 fn emit_i32(&mut self, v: i32) -> EncodeResult {
890 self.wr_tagged_i32(EsI32 as uint, v)
892 fn emit_i16(&mut self, v: i16) -> EncodeResult {
893 self.wr_tagged_i16(EsI16 as uint, v)
895 fn emit_i8(&mut self, v: i8) -> EncodeResult {
896 self.wr_tagged_i8(EsI8 as uint, v)
899 fn emit_bool(&mut self, v: bool) -> EncodeResult {
900 self.wr_tagged_u8(EsBool as uint, v as u8)
903 fn emit_f64(&mut self, v: f64) -> EncodeResult {
904 let bits = unsafe { mem::transmute(v) };
905 self.wr_tagged_u64(EsF64 as uint, bits)
907 fn emit_f32(&mut self, v: f32) -> EncodeResult {
908 let bits = unsafe { mem::transmute(v) };
909 self.wr_tagged_u32(EsF32 as uint, bits)
911 fn emit_char(&mut self, v: char) -> EncodeResult {
912 self.wr_tagged_u32(EsChar as uint, v as u32)
915 fn emit_str(&mut self, v: &str) -> EncodeResult {
916 self.wr_tagged_str(EsStr as uint, v)
919 fn emit_enum(&mut self,
921 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
922 try!(self._emit_label(name));
923 try!(self.start_tag(EsEnum as uint));
928 fn emit_enum_variant(&mut self,
932 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
933 try!(self._emit_tagged_uint(EsEnumVid, v_id));
934 try!(self.start_tag(EsEnumBody as uint));
939 fn emit_enum_variant_arg(&mut self,
941 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
945 fn emit_enum_struct_variant(&mut self,
949 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
950 self.emit_enum_variant(v_name, v_id, cnt, f)
953 fn emit_enum_struct_variant_field(&mut self,
956 f: |&mut Encoder<'a, W>| -> EncodeResult)
958 self.emit_enum_variant_arg(idx, f)
961 fn emit_struct(&mut self,
964 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
968 fn emit_struct_field(&mut self,
971 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
972 try!(self._emit_label(name));
976 fn emit_tuple(&mut self,
978 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
979 self.emit_seq(len, f)
981 fn emit_tuple_arg(&mut self,
983 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
984 self.emit_seq_elt(idx, f)
987 fn emit_tuple_struct(&mut self,
990 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
991 self.emit_seq(len, f)
993 fn emit_tuple_struct_arg(&mut self,
995 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
996 self.emit_seq_elt(idx, f)
999 fn emit_option(&mut self,
1000 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1001 self.emit_enum("Option", f)
1003 fn emit_option_none(&mut self) -> EncodeResult {
1004 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1006 fn emit_option_some(&mut self,
1007 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1009 self.emit_enum_variant("Some", 1, 1, f)
1012 fn emit_seq(&mut self,
1014 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1016 try!(self.start_tag(EsVec as uint));
1017 try!(self._emit_tagged_uint(EsVecLen, len));
1022 fn emit_seq_elt(&mut self,
1024 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1026 try!(self.start_tag(EsVecElt as uint));
1031 fn emit_map(&mut self,
1033 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1035 try!(self.start_tag(EsMap as uint));
1036 try!(self._emit_tagged_uint(EsMapLen, len));
1041 fn emit_map_elt_key(&mut self,
1043 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1045 try!(self.start_tag(EsMapKey as uint));
1050 fn emit_map_elt_val(&mut self,
1052 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1053 try!(self.start_tag(EsMapVal as uint));
1060 // ___________________________________________________________________________
1065 use super::{Doc, reader, writer};
1066 use super::io::SeekableMemWriter;
1068 use serialize::{Encodable, Decodable};
1070 use std::option::Option;
1071 use std::option::Option::{None, Some};
1074 fn test_vuint_at() {
1082 0x10, 0x00, 0x00, 0x00,
1083 0x1f, 0xff, 0xff, 0xff
1086 let mut res: reader::Res;
1089 res = reader::vuint_at(data, 0).unwrap();
1090 assert_eq!(res.val, 0);
1091 assert_eq!(res.next, 1);
1092 res = reader::vuint_at(data, res.next).unwrap();
1093 assert_eq!(res.val, (1 << 7) - 1);
1094 assert_eq!(res.next, 2);
1097 res = reader::vuint_at(data, res.next).unwrap();
1098 assert_eq!(res.val, 0);
1099 assert_eq!(res.next, 4);
1100 res = reader::vuint_at(data, res.next).unwrap();
1101 assert_eq!(res.val, (1 << 14) - 1);
1102 assert_eq!(res.next, 6);
1105 res = reader::vuint_at(data, res.next).unwrap();
1106 assert_eq!(res.val, 0);
1107 assert_eq!(res.next, 9);
1108 res = reader::vuint_at(data, res.next).unwrap();
1109 assert_eq!(res.val, (1 << 21) - 1);
1110 assert_eq!(res.next, 12);
1113 res = reader::vuint_at(data, res.next).unwrap();
1114 assert_eq!(res.val, 0);
1115 assert_eq!(res.next, 16);
1116 res = reader::vuint_at(data, res.next).unwrap();
1117 assert_eq!(res.val, (1 << 28) - 1);
1118 assert_eq!(res.next, 20);
1122 fn test_option_int() {
1123 fn test_v(v: Option<int>) {
1124 debug!("v == {}", v);
1125 let mut wr = SeekableMemWriter::new();
1127 let mut rbml_w = writer::Encoder::new(&mut wr);
1128 let _ = v.encode(&mut rbml_w);
1130 let rbml_doc = Doc::new(wr.get_ref());
1131 let mut deser = reader::Decoder::new(rbml_doc);
1132 let v1 = Decodable::decode(&mut deser).unwrap();
1133 debug!("v1 == {}", v1);
1145 #![allow(non_snake_case)]
1150 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1151 let data = Vec::from_fn(4*100, |i| {
1160 while i < data.len() {
1161 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1168 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1169 let data = Vec::from_fn(4*100+1, |i| {
1178 while i < data.len() {
1179 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1186 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1187 let data = Vec::from_fn(4*100, |i| {
1197 while i < data.len() {
1198 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1205 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
1206 let data = Vec::from_fn(4*100+1, |i| {
1216 while i < data.len() {
1217 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;