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> Doc<'doc> {
51 pub fn new(data: &'doc [u8]) -> Doc<'doc> {
52 Doc { data: data, start: 0u, end: data.len() }
55 pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
56 reader::get_doc(*self, tag)
59 pub fn as_str_slice<'a>(&'a self) -> &'a str {
60 str::from_utf8(self.data[self.start..self.end]).unwrap()
63 pub fn as_str(&self) -> String {
64 self.as_str_slice().to_string()
68 pub struct TaggedDoc<'a> {
74 pub enum EbmlEncoderTag {
104 EsLabel, // Used only when debugging
111 IoError(std::io::IoError),
112 ApplicationError(String)
114 // --------------------------------------
120 use std::io::extensions::u64_from_be_bytes;
121 use std::mem::transmute;
123 use std::option::Option;
124 use std::option::Option::{None, Some};
128 use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt,
129 EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
130 EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
131 EsEnumBody, EsUint, EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc,
132 Error, IntTooBig, Expected };
134 pub type DecodeResult<T> = Result<T, Error>;
138 ($e:expr, $r:expr) => (
142 debug!("ignored error: {}", e);
155 fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
157 if a & 0x80u8 != 0u8 {
158 return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
160 if a & 0x40u8 != 0u8 {
161 return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
162 (data[start + 1u] as uint),
165 if a & 0x20u8 != 0u8 {
166 return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
167 (data[start + 1u] as uint) << 8u |
168 (data[start + 2u] as uint),
171 if a & 0x10u8 != 0u8 {
172 return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
173 (data[start + 1u] as uint) << 16u |
174 (data[start + 2u] as uint) << 8u |
175 (data[start + 3u] as uint),
178 Err(IntTooBig(a as uint))
181 pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
182 if data.len() - start < 4 {
183 return vuint_at_slow(data, start);
186 // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
187 // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
188 // Using the four most significant bits of the u32 we lookup in the table below how the
189 // element ID should be derived from it.
191 // The table stores tuples (shift, mask) where shift is the number the u32 should be right
192 // shifted with and mask is the value the right shifted value should be masked with.
193 // If for example the most significant bit is set this means it's a class A ID and the u32
194 // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
195 // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
197 // By storing the number of shifts and masks in a table instead of checking in order if
198 // the most significant bit is set, the second most significant bit is set etc. we can
199 // replace up to three "and+branch" with a single table lookup which gives us a measured
200 // speedup of around 2x on x86_64.
201 static SHIFT_MASK_TABLE: [(uint, u32), ..16] = [
202 (0, 0x0), (0, 0x0fffffff),
203 (8, 0x1fffff), (8, 0x1fffff),
204 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
205 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
206 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
210 let ptr = data.as_ptr().offset(start as int) as *const u32;
211 let val = Int::from_be(*ptr);
213 let i = (val >> 28u) as uint;
214 let (shift, mask) = SHIFT_MASK_TABLE[i];
216 val: ((val >> shift) & mask) as uint,
217 next: start + (((32 - shift) >> 3) as uint)
222 pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
223 let elt_tag = try!(vuint_at(data, start));
224 let elt_size = try!(vuint_at(data, elt_tag.next));
225 let end = elt_size.next + elt_size.val;
228 doc: Doc { data: data, start: elt_size.next, end: end }
232 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
233 let mut pos = d.start;
235 let elt_tag = try_or!(vuint_at(d.data, pos), None);
236 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
237 pos = elt_size.next + elt_size.val;
238 if elt_tag.val == tg {
239 return Some(Doc { data: d.data, start: elt_size.next,
246 pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
247 match maybe_get_doc(d, tg) {
250 error!("failed to find block with tag {}", tg);
256 pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
257 let mut pos = d.start;
259 let elt_tag = try_or!(vuint_at(d.data, pos), false);
260 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
261 pos = elt_size.next + elt_size.val;
262 let doc = Doc { data: d.data, start: elt_size.next, end: pos };
263 if !it(elt_tag.val, doc) {
270 pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
271 let mut pos = d.start;
273 let elt_tag = try_or!(vuint_at(d.data, pos), false);
274 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
275 pos = elt_size.next + elt_size.val;
276 if elt_tag.val == tg {
277 let doc = Doc { data: d.data, start: elt_size.next,
287 pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
288 f(d.data[d.start..d.end])
292 pub fn doc_as_u8(d: Doc) -> u8 {
293 assert_eq!(d.end, d.start + 1u);
297 pub fn doc_as_u16(d: Doc) -> u16 {
298 assert_eq!(d.end, d.start + 2u);
299 u64_from_be_bytes(d.data, d.start, 2u) as u16
302 pub fn doc_as_u32(d: Doc) -> u32 {
303 assert_eq!(d.end, d.start + 4u);
304 u64_from_be_bytes(d.data, d.start, 4u) as u32
307 pub fn doc_as_u64(d: Doc) -> u64 {
308 assert_eq!(d.end, d.start + 8u);
309 u64_from_be_bytes(d.data, d.start, 8u)
312 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
313 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
314 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
315 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
317 pub struct Decoder<'a> {
322 impl<'doc> Decoder<'doc> {
323 pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
330 fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
331 if self.pos < self.parent.end {
332 let TaggedDoc { tag: r_tag, doc: r_doc } =
333 try!(doc_at(self.parent.data, self.pos));
335 if r_tag == (EsLabel as uint) {
336 self.pos = r_doc.end;
337 let str = r_doc.as_str_slice();
339 return Err(Expected(format!("Expected label {} but \
340 found {}", lbl, str)));
347 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
348 debug!(". next_doc(exp_tag={})", exp_tag);
349 if self.pos >= self.parent.end {
350 return Err(Expected(format!("no more documents in \
353 let TaggedDoc { tag: r_tag, doc: r_doc } =
354 try!(doc_at(self.parent.data, self.pos));
355 debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
362 if r_tag != (exp_tag as uint) {
363 return Err(Expected(format!("expected EBML doc with tag {} but \
364 found tag {}", exp_tag, r_tag)));
366 if r_doc.end > self.parent.end {
367 return Err(Expected(format!("invalid EBML, child extends to \
368 {:#x}, parent to {:#x}",
369 r_doc.end, self.parent.end)));
371 self.pos = r_doc.end;
375 fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
376 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
377 let d = try!(self.next_doc(exp_tag));
378 let old_parent = self.parent;
379 let old_pos = self.pos;
382 let r = try!(f(self));
383 self.parent = old_parent;
388 fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
389 let r = doc_as_u32(try!(self.next_doc(exp_tag)));
390 debug!("_next_uint exp_tag={} result={}", exp_tag, r);
394 pub fn read_opaque<R>(&mut self,
395 op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
396 let doc = try!(self.next_doc(EsOpaque));
398 let (old_parent, old_pos) = (self.parent, self.pos);
400 self.pos = doc.start;
402 let result = try!(op(self, doc));
404 self.parent = old_parent;
410 impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
411 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
413 fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
414 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
415 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
416 fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
417 fn read_uint(&mut self) -> DecodeResult<uint> {
418 let v = doc_as_u64(try!(self.next_doc(EsUint)));
419 if v > (::std::uint::MAX as u64) {
420 Err(IntTooBig(v as uint))
426 fn read_i64(&mut self) -> DecodeResult<i64> {
427 Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
429 fn read_i32(&mut self) -> DecodeResult<i32> {
430 Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
432 fn read_i16(&mut self) -> DecodeResult<i16> {
433 Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
435 fn read_i8 (&mut self) -> DecodeResult<i8> {
436 Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
438 fn read_int(&mut self) -> DecodeResult<int> {
439 let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
440 if v > (int::MAX as i64) || v < (int::MIN as i64) {
441 debug!("FIXME \\#6122: Removing this makes this function miscompile");
442 Err(IntTooBig(v as uint))
448 fn read_bool(&mut self) -> DecodeResult<bool> {
449 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
452 fn read_f64(&mut self) -> DecodeResult<f64> {
453 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
454 Ok(unsafe { transmute(bits) })
456 fn read_f32(&mut self) -> DecodeResult<f32> {
457 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
458 Ok(unsafe { transmute(bits) })
460 fn read_char(&mut self) -> DecodeResult<char> {
461 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
463 fn read_str(&mut self) -> DecodeResult<String> {
464 Ok(try!(self.next_doc(EsStr)).as_str())
468 fn read_enum<T>(&mut self,
470 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
471 debug!("read_enum({})", name);
472 try!(self._check_label(name));
474 let doc = try!(self.next_doc(EsEnum));
476 let (old_parent, old_pos) = (self.parent, self.pos);
478 self.pos = self.parent.start;
480 let result = try!(f(self));
482 self.parent = old_parent;
487 fn read_enum_variant<T>(&mut self,
489 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
491 debug!("read_enum_variant()");
492 let idx = try!(self._next_uint(EsEnumVid));
493 debug!(" idx={}", idx);
495 let doc = try!(self.next_doc(EsEnumBody));
497 let (old_parent, old_pos) = (self.parent, self.pos);
499 self.pos = self.parent.start;
501 let result = try!(f(self, idx));
503 self.parent = old_parent;
508 fn read_enum_variant_arg<T>(&mut self,
510 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
511 debug!("read_enum_variant_arg(idx={})", idx);
515 fn read_enum_struct_variant<T>(&mut self,
517 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
519 debug!("read_enum_struct_variant()");
520 let idx = try!(self._next_uint(EsEnumVid));
521 debug!(" idx={}", idx);
523 let doc = try!(self.next_doc(EsEnumBody));
525 let (old_parent, old_pos) = (self.parent, self.pos);
527 self.pos = self.parent.start;
529 let result = try!(f(self, idx));
531 self.parent = old_parent;
536 fn read_enum_struct_variant_field<T>(&mut self,
539 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
541 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
545 fn read_struct<T>(&mut self,
548 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
550 debug!("read_struct(name={})", name);
554 fn read_struct_field<T>(&mut self,
557 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
559 debug!("read_struct_field(name={}, idx={})", name, idx);
560 try!(self._check_label(name));
564 fn read_tuple<T>(&mut self,
566 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
567 debug!("read_tuple()");
568 self.read_seq(|d, len| {
569 if len == tuple_len {
572 Err(Expected(format!("Expected tuple of length `{}`, \
573 found tuple of length `{}`", tuple_len, len)))
578 fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
580 debug!("read_tuple_arg(idx={})", idx);
581 self.read_seq_elt(idx, f)
584 fn read_tuple_struct<T>(&mut self,
587 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
589 debug!("read_tuple_struct(name={})", name);
590 self.read_tuple(len, f)
593 fn read_tuple_struct_arg<T>(&mut self,
595 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
597 debug!("read_tuple_struct_arg(idx={})", idx);
598 self.read_tuple_arg(idx, f)
601 fn read_option<T>(&mut self,
602 f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
603 debug!("read_option()");
604 self.read_enum("Option", |this| {
605 this.read_enum_variant(&["None", "Some"], |this, idx| {
610 Err(Expected(format!("Expected None or Some")))
617 fn read_seq<T>(&mut self,
618 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
619 debug!("read_seq()");
620 self.push_doc(EsVec, |d| {
621 let len = try!(d._next_uint(EsVecLen));
622 debug!(" len={}", len);
627 fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
629 debug!("read_seq_elt(idx={})", idx);
630 self.push_doc(EsVecElt, f)
633 fn read_map<T>(&mut self,
634 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
635 debug!("read_map()");
636 self.push_doc(EsMap, |d| {
637 let len = try!(d._next_uint(EsMapLen));
638 debug!(" len={}", len);
643 fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
645 debug!("read_map_elt_key(idx={})", idx);
646 self.push_doc(EsMapKey, f)
649 fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
651 debug!("read_map_elt_val(idx={})", idx);
652 self.push_doc(EsMapVal, f)
655 fn error(&mut self, err: &str) -> Error {
656 ApplicationError(err.to_string())
662 use std::clone::Clone;
663 use std::io::extensions::u64_to_be_bytes;
664 use std::io::{Writer, Seek};
668 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
669 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
670 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
671 EsOpaque, EsLabel, EbmlEncoderTag };
676 pub type EncodeResult = io::IoResult<()>;
679 pub struct Encoder<'a, W:'a> {
680 pub writer: &'a mut W,
681 size_positions: Vec<uint>,
684 fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
686 1u => w.write(&[0x80u8 | (n as u8)]),
687 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
688 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
690 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
691 (n >> 8_u) as u8, n as u8]),
692 _ => Err(io::IoError {
693 kind: io::OtherIoError,
695 detail: Some(format!("{}", n))
700 fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
701 if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
702 if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
703 if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
704 if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
706 kind: io::OtherIoError,
708 detail: Some(format!("{}", n))
712 // FIXME (#2741): Provide a function to write the standard rbml header.
713 impl<'a, W: Writer + Seek> Encoder<'a, W> {
714 pub fn new(w: &'a mut W) -> Encoder<'a, W> {
717 size_positions: vec!(),
721 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
722 pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
724 writer: mem::transmute_copy(&self.writer),
725 size_positions: self.size_positions.clone(),
729 pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
730 debug!("Start tag {}", tag_id);
732 // Write the enum ID:
733 try!(write_vuint(self.writer, tag_id));
735 // Write a placeholder four-byte size.
736 self.size_positions.push(try!(self.writer.tell()) as uint);
737 let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
738 self.writer.write(zeroes)
741 pub fn end_tag(&mut self) -> EncodeResult {
742 let last_size_pos = self.size_positions.pop().unwrap();
743 let cur_pos = try!(self.writer.tell());
744 try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
745 let size = cur_pos as uint - last_size_pos - 4;
746 try!(write_sized_vuint(self.writer, size, 4u));
747 let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
749 debug!("End tag (size = {})", size);
753 pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
754 try!(self.start_tag(tag_id));
759 pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
760 try!(write_vuint(self.writer, tag_id));
761 try!(write_vuint(self.writer, b.len()));
765 pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
766 u64_to_be_bytes(v, 8u, |v| {
767 self.wr_tagged_bytes(tag_id, v)
771 pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
772 u64_to_be_bytes(v as u64, 4u, |v| {
773 self.wr_tagged_bytes(tag_id, v)
777 pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
778 u64_to_be_bytes(v as u64, 2u, |v| {
779 self.wr_tagged_bytes(tag_id, v)
783 pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
784 self.wr_tagged_bytes(tag_id, &[v])
787 pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
788 u64_to_be_bytes(v as u64, 8u, |v| {
789 self.wr_tagged_bytes(tag_id, v)
793 pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
794 u64_to_be_bytes(v as u64, 4u, |v| {
795 self.wr_tagged_bytes(tag_id, v)
799 pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
800 u64_to_be_bytes(v as u64, 2u, |v| {
801 self.wr_tagged_bytes(tag_id, v)
805 pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
806 self.wr_tagged_bytes(tag_id, &[v as u8])
809 pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
810 self.wr_tagged_bytes(tag_id, v.as_bytes())
813 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
814 debug!("Write {} bytes", b.len());
818 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
819 debug!("Write str: {}", s);
820 self.writer.write(s.as_bytes())
824 // FIXME (#2743): optionally perform "relaxations" on end_tag to more
825 // efficiently encode sizes; this is a fixed point iteration
827 // Set to true to generate more debugging in EBML code.
828 // Totally lame approach.
829 static DEBUG: bool = true;
831 impl<'a, W: Writer + Seek> Encoder<'a, W> {
832 // used internally to emit things like the vector length and so on
833 fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
834 assert!(v <= 0xFFFF_FFFF_u);
835 self.wr_tagged_u32(t as uint, v as u32)
838 fn _emit_label(&mut self, label: &str) -> EncodeResult {
839 // There are various strings that we have access to, such as
840 // the name of a record field, which do not actually appear in
841 // the encoded EBML (normally). This is just for
842 // efficiency. When debugging, though, we can emit such
843 // labels and then they will be checked by decoder to
844 // try and check panics more quickly.
845 if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
849 pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
850 try!(self.start_tag(EsOpaque as uint));
856 impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
857 fn emit_nil(&mut self) -> EncodeResult {
861 fn emit_uint(&mut self, v: uint) -> EncodeResult {
862 self.wr_tagged_u64(EsUint as uint, v as u64)
864 fn emit_u64(&mut self, v: u64) -> EncodeResult {
865 self.wr_tagged_u64(EsU64 as uint, v)
867 fn emit_u32(&mut self, v: u32) -> EncodeResult {
868 self.wr_tagged_u32(EsU32 as uint, v)
870 fn emit_u16(&mut self, v: u16) -> EncodeResult {
871 self.wr_tagged_u16(EsU16 as uint, v)
873 fn emit_u8(&mut self, v: u8) -> EncodeResult {
874 self.wr_tagged_u8(EsU8 as uint, v)
877 fn emit_int(&mut self, v: int) -> EncodeResult {
878 self.wr_tagged_i64(EsInt as uint, v as i64)
880 fn emit_i64(&mut self, v: i64) -> EncodeResult {
881 self.wr_tagged_i64(EsI64 as uint, v)
883 fn emit_i32(&mut self, v: i32) -> EncodeResult {
884 self.wr_tagged_i32(EsI32 as uint, v)
886 fn emit_i16(&mut self, v: i16) -> EncodeResult {
887 self.wr_tagged_i16(EsI16 as uint, v)
889 fn emit_i8(&mut self, v: i8) -> EncodeResult {
890 self.wr_tagged_i8(EsI8 as uint, v)
893 fn emit_bool(&mut self, v: bool) -> EncodeResult {
894 self.wr_tagged_u8(EsBool as uint, v as u8)
897 fn emit_f64(&mut self, v: f64) -> EncodeResult {
898 let bits = unsafe { mem::transmute(v) };
899 self.wr_tagged_u64(EsF64 as uint, bits)
901 fn emit_f32(&mut self, v: f32) -> EncodeResult {
902 let bits = unsafe { mem::transmute(v) };
903 self.wr_tagged_u32(EsF32 as uint, bits)
905 fn emit_char(&mut self, v: char) -> EncodeResult {
906 self.wr_tagged_u32(EsChar as uint, v as u32)
909 fn emit_str(&mut self, v: &str) -> EncodeResult {
910 self.wr_tagged_str(EsStr as uint, v)
913 fn emit_enum(&mut self,
915 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
916 try!(self._emit_label(name));
917 try!(self.start_tag(EsEnum as uint));
922 fn emit_enum_variant(&mut self,
926 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
927 try!(self._emit_tagged_uint(EsEnumVid, v_id));
928 try!(self.start_tag(EsEnumBody as uint));
933 fn emit_enum_variant_arg(&mut self,
935 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
939 fn emit_enum_struct_variant(&mut self,
943 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
944 self.emit_enum_variant(v_name, v_id, cnt, f)
947 fn emit_enum_struct_variant_field(&mut self,
950 f: |&mut Encoder<'a, W>| -> EncodeResult)
952 self.emit_enum_variant_arg(idx, f)
955 fn emit_struct(&mut self,
958 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
962 fn emit_struct_field(&mut self,
965 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
966 try!(self._emit_label(name));
970 fn emit_tuple(&mut self,
972 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
973 self.emit_seq(len, f)
975 fn emit_tuple_arg(&mut self,
977 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
978 self.emit_seq_elt(idx, f)
981 fn emit_tuple_struct(&mut self,
984 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
985 self.emit_seq(len, f)
987 fn emit_tuple_struct_arg(&mut self,
989 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
990 self.emit_seq_elt(idx, f)
993 fn emit_option(&mut self,
994 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
995 self.emit_enum("Option", f)
997 fn emit_option_none(&mut self) -> EncodeResult {
998 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
1000 fn emit_option_some(&mut self,
1001 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1003 self.emit_enum_variant("Some", 1, 1, f)
1006 fn emit_seq(&mut self,
1008 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1010 try!(self.start_tag(EsVec as uint));
1011 try!(self._emit_tagged_uint(EsVecLen, len));
1016 fn emit_seq_elt(&mut self,
1018 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1020 try!(self.start_tag(EsVecElt as uint));
1025 fn emit_map(&mut self,
1027 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1029 try!(self.start_tag(EsMap as uint));
1030 try!(self._emit_tagged_uint(EsMapLen, len));
1035 fn emit_map_elt_key(&mut self,
1037 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1039 try!(self.start_tag(EsMapKey as uint));
1044 fn emit_map_elt_val(&mut self,
1046 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1047 try!(self.start_tag(EsMapVal as uint));
1054 // ___________________________________________________________________________
1059 use super::{Doc, reader, writer};
1060 use super::io::SeekableMemWriter;
1062 use serialize::{Encodable, Decodable};
1064 use std::option::Option;
1065 use std::option::Option::{None, Some};
1068 fn test_vuint_at() {
1076 0x10, 0x00, 0x00, 0x00,
1077 0x1f, 0xff, 0xff, 0xff
1080 let mut res: reader::Res;
1083 res = reader::vuint_at(data, 0).unwrap();
1084 assert_eq!(res.val, 0);
1085 assert_eq!(res.next, 1);
1086 res = reader::vuint_at(data, res.next).unwrap();
1087 assert_eq!(res.val, (1 << 7) - 1);
1088 assert_eq!(res.next, 2);
1091 res = reader::vuint_at(data, res.next).unwrap();
1092 assert_eq!(res.val, 0);
1093 assert_eq!(res.next, 4);
1094 res = reader::vuint_at(data, res.next).unwrap();
1095 assert_eq!(res.val, (1 << 14) - 1);
1096 assert_eq!(res.next, 6);
1099 res = reader::vuint_at(data, res.next).unwrap();
1100 assert_eq!(res.val, 0);
1101 assert_eq!(res.next, 9);
1102 res = reader::vuint_at(data, res.next).unwrap();
1103 assert_eq!(res.val, (1 << 21) - 1);
1104 assert_eq!(res.next, 12);
1107 res = reader::vuint_at(data, res.next).unwrap();
1108 assert_eq!(res.val, 0);
1109 assert_eq!(res.next, 16);
1110 res = reader::vuint_at(data, res.next).unwrap();
1111 assert_eq!(res.val, (1 << 28) - 1);
1112 assert_eq!(res.next, 20);
1116 fn test_option_int() {
1117 fn test_v(v: Option<int>) {
1118 debug!("v == {}", v);
1119 let mut wr = SeekableMemWriter::new();
1121 let mut rbml_w = writer::Encoder::new(&mut wr);
1122 let _ = v.encode(&mut rbml_w);
1124 let rbml_doc = Doc::new(wr.get_ref());
1125 let mut deser = reader::Decoder::new(rbml_doc);
1126 let v1 = Decodable::decode(&mut deser).unwrap();
1127 debug!("v1 == {}", v1);
1139 #![allow(non_snake_case)]
1144 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1145 let data = Vec::from_fn(4*100, |i| {
1154 while i < data.len() {
1155 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1162 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1163 let data = Vec::from_fn(4*100+1, |i| {
1172 while i < data.len() {
1173 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1180 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1181 let data = Vec::from_fn(4*100, |i| {
1191 while i < data.len() {
1192 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1199 pub fn vuint_at_D_unaligned(b: &mut Bencher) {
1200 let data = Vec::from_fn(4*100+1, |i| {
1210 while i < data.len() {
1211 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;