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 #![allow(missing_doc)]
16 // Simple Extensible Binary Markup Language (ebml) reader and writer on a
17 // cursor model. See the specification here:
18 // http://www.matroska.org/technical/specs/rfc/index.html
20 // Common data structures
28 impl<'doc> Doc<'doc> {
29 pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
30 reader::get_doc(*self, tag)
33 pub fn as_str_slice<'a>(&'a self) -> &'a str {
34 str::from_utf8(self.data.slice(self.start, self.end)).unwrap()
37 pub fn as_str(&self) -> String {
38 self.as_str_slice().to_string()
42 pub struct TaggedDoc<'a> {
48 pub enum EbmlEncoderTag {
78 EsLabel, // Used only when debugging
87 // --------------------------------------
92 use std::mem::transmute;
94 use std::option::{None, Option, Some};
95 use std::io::extensions::u64_from_be_bytes;
99 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
100 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
101 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
102 EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, Error, IntTooBig,
105 pub type DecodeResult<T> = Result<T, Error>;
109 ($e:expr, $r:expr) => (
113 debug!("ignored error: {}", e);
126 fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
128 if a & 0x80u8 != 0u8 {
129 return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
131 if a & 0x40u8 != 0u8 {
132 return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
133 (data[start + 1u] as uint),
136 if a & 0x20u8 != 0u8 {
137 return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
138 (data[start + 1u] as uint) << 8u |
139 (data[start + 2u] as uint),
142 if a & 0x10u8 != 0u8 {
143 return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
144 (data[start + 1u] as uint) << 16u |
145 (data[start + 2u] as uint) << 8u |
146 (data[start + 3u] as uint),
149 Err(IntTooBig(a as uint))
152 pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
153 use std::mem::from_be32;
155 if data.len() - start < 4 {
156 return vuint_at_slow(data, start);
159 // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
160 // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
161 // Using the four most significant bits of the u32 we lookup in the table below how the
162 // element ID should be derived from it.
164 // The table stores tuples (shift, mask) where shift is the number the u32 should be right
165 // shifted with and mask is the value the right shifted value should be masked with.
166 // If for example the most significant bit is set this means it's a class A ID and the u32
167 // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
168 // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
170 // By storing the number of shifts and masks in a table instead of checking in order if
171 // the most significant bit is set, the second most significant bit is set etc. we can
172 // replace up to three "and+branch" with a single table lookup which gives us a measured
173 // speedup of around 2x on x86_64.
174 static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
175 (0, 0x0), (0, 0x0fffffff),
176 (8, 0x1fffff), (8, 0x1fffff),
177 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
178 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
179 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
183 let ptr = data.as_ptr().offset(start as int) as *u32;
184 let val = from_be32(*ptr);
186 let i = (val >> 28u) as uint;
187 let (shift, mask) = SHIFT_MASK_TABLE[i];
189 val: ((val >> shift) & mask) as uint,
190 next: start + (((32 - shift) >> 3) as uint)
195 pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
196 Doc { data: data, start: 0u, end: data.len() }
199 pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
200 let elt_tag = try!(vuint_at(data, start));
201 let elt_size = try!(vuint_at(data, elt_tag.next));
202 let end = elt_size.next + elt_size.val;
205 doc: Doc { data: data, start: elt_size.next, end: end }
209 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
210 let mut pos = d.start;
212 let elt_tag = try_or!(vuint_at(d.data, pos), None);
213 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
214 pos = elt_size.next + elt_size.val;
215 if elt_tag.val == tg {
216 return Some(Doc { data: d.data, start: elt_size.next,
223 pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
224 match maybe_get_doc(d, tg) {
227 error!("failed to find block with tag {}", tg);
233 pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
234 let mut pos = d.start;
236 let elt_tag = try_or!(vuint_at(d.data, pos), false);
237 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
238 pos = elt_size.next + elt_size.val;
239 let doc = Doc { data: d.data, start: elt_size.next, end: pos };
240 if !it(elt_tag.val, doc) {
247 pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
248 let mut pos = d.start;
250 let elt_tag = try_or!(vuint_at(d.data, pos), false);
251 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
252 pos = elt_size.next + elt_size.val;
253 if elt_tag.val == tg {
254 let doc = Doc { data: d.data, start: elt_size.next,
264 pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
265 f(d.data.slice(d.start, d.end))
269 pub fn doc_as_u8(d: Doc) -> u8 {
270 assert_eq!(d.end, d.start + 1u);
274 pub fn doc_as_u16(d: Doc) -> u16 {
275 assert_eq!(d.end, d.start + 2u);
276 u64_from_be_bytes(d.data, d.start, 2u) as u16
279 pub fn doc_as_u32(d: Doc) -> u32 {
280 assert_eq!(d.end, d.start + 4u);
281 u64_from_be_bytes(d.data, d.start, 4u) as u32
284 pub fn doc_as_u64(d: Doc) -> u64 {
285 assert_eq!(d.end, d.start + 8u);
286 u64_from_be_bytes(d.data, d.start, 8u)
289 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
290 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
291 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
292 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
294 pub struct Decoder<'a> {
299 pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
306 impl<'doc> Decoder<'doc> {
307 fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
308 if self.pos < self.parent.end {
309 let TaggedDoc { tag: r_tag, doc: r_doc } =
310 try!(doc_at(self.parent.data, self.pos));
312 if r_tag == (EsLabel as uint) {
313 self.pos = r_doc.end;
314 let str = r_doc.as_str_slice();
316 return Err(Expected(format!("Expected label {} but \
317 found {}", lbl, str)));
324 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
325 debug!(". next_doc(exp_tag={})", exp_tag);
326 if self.pos >= self.parent.end {
327 return Err(Expected(format!("no more documents in \
330 let TaggedDoc { tag: r_tag, doc: r_doc } =
331 try!(doc_at(self.parent.data, self.pos));
332 debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
339 if r_tag != (exp_tag as uint) {
340 return Err(Expected(format!("expected EBML doc with tag {} but \
341 found tag {}", exp_tag, r_tag)));
343 if r_doc.end > self.parent.end {
344 return Err(Expected(format!("invalid EBML, child extends to \
345 {:#x}, parent to {:#x}",
346 r_doc.end, self.parent.end)));
348 self.pos = r_doc.end;
352 fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
353 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
354 let d = try!(self.next_doc(exp_tag));
355 let old_parent = self.parent;
356 let old_pos = self.pos;
359 let r = try!(f(self));
360 self.parent = old_parent;
365 fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
366 let r = doc_as_u32(try!(self.next_doc(exp_tag)));
367 debug!("_next_uint exp_tag={} result={}", exp_tag, r);
371 pub fn read_opaque<R>(&mut self,
372 op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
373 let doc = try!(self.next_doc(EsOpaque));
375 let (old_parent, old_pos) = (self.parent, self.pos);
377 self.pos = doc.start;
379 let result = try!(op(self, doc));
381 self.parent = old_parent;
387 impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
388 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
390 fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
391 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
392 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
393 fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
394 fn read_uint(&mut self) -> DecodeResult<uint> {
395 let v = doc_as_u64(try!(self.next_doc(EsUint)));
396 if v > (::std::uint::MAX as u64) {
397 Err(IntTooBig(v as uint))
403 fn read_i64(&mut self) -> DecodeResult<i64> {
404 Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
406 fn read_i32(&mut self) -> DecodeResult<i32> {
407 Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
409 fn read_i16(&mut self) -> DecodeResult<i16> {
410 Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
412 fn read_i8 (&mut self) -> DecodeResult<i8> {
413 Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
415 fn read_int(&mut self) -> DecodeResult<int> {
416 let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
417 if v > (int::MAX as i64) || v < (int::MIN as i64) {
418 debug!("FIXME \\#6122: Removing this makes this function miscompile");
419 Err(IntTooBig(v as uint))
425 fn read_bool(&mut self) -> DecodeResult<bool> {
426 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
429 fn read_f64(&mut self) -> DecodeResult<f64> {
430 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
431 Ok(unsafe { transmute(bits) })
433 fn read_f32(&mut self) -> DecodeResult<f32> {
434 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
435 Ok(unsafe { transmute(bits) })
437 fn read_char(&mut self) -> DecodeResult<char> {
438 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
440 fn read_str(&mut self) -> DecodeResult<String> {
441 Ok(try!(self.next_doc(EsStr)).as_str())
445 fn read_enum<T>(&mut self,
447 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
448 debug!("read_enum({})", name);
449 try!(self._check_label(name));
451 let doc = try!(self.next_doc(EsEnum));
453 let (old_parent, old_pos) = (self.parent, self.pos);
455 self.pos = self.parent.start;
457 let result = try!(f(self));
459 self.parent = old_parent;
464 fn read_enum_variant<T>(&mut self,
466 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
468 debug!("read_enum_variant()");
469 let idx = try!(self._next_uint(EsEnumVid));
470 debug!(" idx={}", idx);
472 let doc = try!(self.next_doc(EsEnumBody));
474 let (old_parent, old_pos) = (self.parent, self.pos);
476 self.pos = self.parent.start;
478 let result = try!(f(self, idx));
480 self.parent = old_parent;
485 fn read_enum_variant_arg<T>(&mut self,
487 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
488 debug!("read_enum_variant_arg(idx={})", idx);
492 fn read_enum_struct_variant<T>(&mut self,
494 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
496 debug!("read_enum_struct_variant()");
497 let idx = try!(self._next_uint(EsEnumVid));
498 debug!(" idx={}", idx);
500 let doc = try!(self.next_doc(EsEnumBody));
502 let (old_parent, old_pos) = (self.parent, self.pos);
504 self.pos = self.parent.start;
506 let result = try!(f(self, idx));
508 self.parent = old_parent;
513 fn read_enum_struct_variant_field<T>(&mut self,
516 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
518 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
522 fn read_struct<T>(&mut self,
525 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
527 debug!("read_struct(name={})", name);
531 fn read_struct_field<T>(&mut self,
534 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
536 debug!("read_struct_field(name={}, idx={})", name, idx);
537 try!(self._check_label(name));
541 fn read_tuple<T>(&mut self,
542 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
543 debug!("read_tuple()");
547 fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
549 debug!("read_tuple_arg(idx={})", idx);
550 self.read_seq_elt(idx, f)
553 fn read_tuple_struct<T>(&mut self,
555 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
557 debug!("read_tuple_struct(name={})", name);
561 fn read_tuple_struct_arg<T>(&mut self,
563 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
565 debug!("read_tuple_struct_arg(idx={})", idx);
566 self.read_tuple_arg(idx, f)
569 fn read_option<T>(&mut self,
570 f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
571 debug!("read_option()");
572 self.read_enum("Option", |this| {
573 this.read_enum_variant(["None", "Some"], |this, idx| {
578 Err(Expected(format!("Expected None or Some")))
585 fn read_seq<T>(&mut self,
586 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
587 debug!("read_seq()");
588 self.push_doc(EsVec, |d| {
589 let len = try!(d._next_uint(EsVecLen));
590 debug!(" len={}", len);
595 fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
597 debug!("read_seq_elt(idx={})", idx);
598 self.push_doc(EsVecElt, f)
601 fn read_map<T>(&mut self,
602 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
603 debug!("read_map()");
604 self.push_doc(EsMap, |d| {
605 let len = try!(d._next_uint(EsMapLen));
606 debug!(" len={}", len);
611 fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
613 debug!("read_map_elt_key(idx={})", idx);
614 self.push_doc(EsMapKey, f)
617 fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
619 debug!("read_map_elt_val(idx={})", idx);
620 self.push_doc(EsMapVal, f)
626 use std::clone::Clone;
627 use std::io::extensions::u64_to_be_bytes;
628 use std::io::{Writer, Seek};
632 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
633 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
634 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
635 EsOpaque, EsLabel, EbmlEncoderTag };
640 pub type EncodeResult = io::IoResult<()>;
643 pub struct Encoder<'a, W> {
644 pub writer: &'a mut W,
645 size_positions: Vec<uint>,
648 fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
650 1u => w.write(&[0x80u8 | (n as u8)]),
651 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
652 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
654 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
655 (n >> 8_u) as u8, n as u8]),
656 _ => Err(io::IoError {
657 kind: io::OtherIoError,
659 detail: Some(format!("{}", n))
664 fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
665 if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
666 if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
667 if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
668 if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
670 kind: io::OtherIoError,
672 detail: Some(format!("{}", n))
676 pub fn Encoder<'a, W: Writer + Seek>(w: &'a mut W) -> Encoder<'a, W> {
679 size_positions: vec!(),
683 // FIXME (#2741): Provide a function to write the standard ebml header.
684 impl<'a, W: Writer + Seek> Encoder<'a, W> {
685 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
686 pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
688 writer: mem::transmute_copy(&self.writer),
689 size_positions: self.size_positions.clone(),
693 pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
694 debug!("Start tag {}", tag_id);
696 // Write the enum ID:
697 try!(write_vuint(self.writer, tag_id));
699 // Write a placeholder four-byte size.
700 self.size_positions.push(try!(self.writer.tell()) as uint);
701 let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
702 self.writer.write(zeroes)
705 pub fn end_tag(&mut self) -> EncodeResult {
706 let last_size_pos = self.size_positions.pop().unwrap();
707 let cur_pos = try!(self.writer.tell());
708 try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
709 let size = cur_pos as uint - last_size_pos - 4;
710 try!(write_sized_vuint(self.writer, size, 4u));
711 let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
713 debug!("End tag (size = {})", size);
717 pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
718 try!(self.start_tag(tag_id));
723 pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
724 try!(write_vuint(self.writer, tag_id));
725 try!(write_vuint(self.writer, b.len()));
729 pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
730 u64_to_be_bytes(v, 8u, |v| {
731 self.wr_tagged_bytes(tag_id, v)
735 pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
736 u64_to_be_bytes(v as u64, 4u, |v| {
737 self.wr_tagged_bytes(tag_id, v)
741 pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
742 u64_to_be_bytes(v as u64, 2u, |v| {
743 self.wr_tagged_bytes(tag_id, v)
747 pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
748 self.wr_tagged_bytes(tag_id, &[v])
751 pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
752 u64_to_be_bytes(v as u64, 8u, |v| {
753 self.wr_tagged_bytes(tag_id, v)
757 pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
758 u64_to_be_bytes(v as u64, 4u, |v| {
759 self.wr_tagged_bytes(tag_id, v)
763 pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
764 u64_to_be_bytes(v as u64, 2u, |v| {
765 self.wr_tagged_bytes(tag_id, v)
769 pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
770 self.wr_tagged_bytes(tag_id, &[v as u8])
773 pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
774 self.wr_tagged_bytes(tag_id, v.as_bytes())
777 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
778 debug!("Write {} bytes", b.len());
782 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
783 debug!("Write str: {}", s);
784 self.writer.write(s.as_bytes())
788 // FIXME (#2743): optionally perform "relaxations" on end_tag to more
789 // efficiently encode sizes; this is a fixed point iteration
791 // Set to true to generate more debugging in EBML code.
792 // Totally lame approach.
793 static DEBUG: bool = true;
795 impl<'a, W: Writer + Seek> Encoder<'a, W> {
796 // used internally to emit things like the vector length and so on
797 fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
798 assert!(v <= 0xFFFF_FFFF_u);
799 self.wr_tagged_u32(t as uint, v as u32)
802 fn _emit_label(&mut self, label: &str) -> EncodeResult {
803 // There are various strings that we have access to, such as
804 // the name of a record field, which do not actually appear in
805 // the encoded EBML (normally). This is just for
806 // efficiency. When debugging, though, we can emit such
807 // labels and then they will be checked by decoder to
808 // try and check failures more quickly.
809 if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
813 pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
814 try!(self.start_tag(EsOpaque as uint));
820 impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
821 fn emit_nil(&mut self) -> EncodeResult {
825 fn emit_uint(&mut self, v: uint) -> EncodeResult {
826 self.wr_tagged_u64(EsUint as uint, v as u64)
828 fn emit_u64(&mut self, v: u64) -> EncodeResult {
829 self.wr_tagged_u64(EsU64 as uint, v)
831 fn emit_u32(&mut self, v: u32) -> EncodeResult {
832 self.wr_tagged_u32(EsU32 as uint, v)
834 fn emit_u16(&mut self, v: u16) -> EncodeResult {
835 self.wr_tagged_u16(EsU16 as uint, v)
837 fn emit_u8(&mut self, v: u8) -> EncodeResult {
838 self.wr_tagged_u8(EsU8 as uint, v)
841 fn emit_int(&mut self, v: int) -> EncodeResult {
842 self.wr_tagged_i64(EsInt as uint, v as i64)
844 fn emit_i64(&mut self, v: i64) -> EncodeResult {
845 self.wr_tagged_i64(EsI64 as uint, v)
847 fn emit_i32(&mut self, v: i32) -> EncodeResult {
848 self.wr_tagged_i32(EsI32 as uint, v)
850 fn emit_i16(&mut self, v: i16) -> EncodeResult {
851 self.wr_tagged_i16(EsI16 as uint, v)
853 fn emit_i8(&mut self, v: i8) -> EncodeResult {
854 self.wr_tagged_i8(EsI8 as uint, v)
857 fn emit_bool(&mut self, v: bool) -> EncodeResult {
858 self.wr_tagged_u8(EsBool as uint, v as u8)
861 fn emit_f64(&mut self, v: f64) -> EncodeResult {
862 let bits = unsafe { mem::transmute(v) };
863 self.wr_tagged_u64(EsF64 as uint, bits)
865 fn emit_f32(&mut self, v: f32) -> EncodeResult {
866 let bits = unsafe { mem::transmute(v) };
867 self.wr_tagged_u32(EsF32 as uint, bits)
869 fn emit_char(&mut self, v: char) -> EncodeResult {
870 self.wr_tagged_u32(EsChar as uint, v as u32)
873 fn emit_str(&mut self, v: &str) -> EncodeResult {
874 self.wr_tagged_str(EsStr as uint, v)
877 fn emit_enum(&mut self,
879 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
880 try!(self._emit_label(name));
881 try!(self.start_tag(EsEnum as uint));
886 fn emit_enum_variant(&mut self,
890 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
891 try!(self._emit_tagged_uint(EsEnumVid, v_id));
892 try!(self.start_tag(EsEnumBody as uint));
897 fn emit_enum_variant_arg(&mut self,
899 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
903 fn emit_enum_struct_variant(&mut self,
907 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
908 self.emit_enum_variant(v_name, v_id, cnt, f)
911 fn emit_enum_struct_variant_field(&mut self,
914 f: |&mut Encoder<'a, W>| -> EncodeResult)
916 self.emit_enum_variant_arg(idx, f)
919 fn emit_struct(&mut self,
922 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
926 fn emit_struct_field(&mut self,
929 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
930 try!(self._emit_label(name));
934 fn emit_tuple(&mut self,
936 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
937 self.emit_seq(len, f)
939 fn emit_tuple_arg(&mut self,
941 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
942 self.emit_seq_elt(idx, f)
945 fn emit_tuple_struct(&mut self,
948 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
949 self.emit_seq(len, f)
951 fn emit_tuple_struct_arg(&mut self,
953 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
954 self.emit_seq_elt(idx, f)
957 fn emit_option(&mut self,
958 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
959 self.emit_enum("Option", f)
961 fn emit_option_none(&mut self) -> EncodeResult {
962 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
964 fn emit_option_some(&mut self,
965 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
967 self.emit_enum_variant("Some", 1, 1, f)
970 fn emit_seq(&mut self,
972 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
974 try!(self.start_tag(EsVec as uint));
975 try!(self._emit_tagged_uint(EsVecLen, len));
980 fn emit_seq_elt(&mut self,
982 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
984 try!(self.start_tag(EsVecElt as uint));
989 fn emit_map(&mut self,
991 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
993 try!(self.start_tag(EsMap as uint));
994 try!(self._emit_tagged_uint(EsMapLen, len));
999 fn emit_map_elt_key(&mut self,
1001 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1003 try!(self.start_tag(EsMapKey as uint));
1008 fn emit_map_elt_val(&mut self,
1010 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1011 try!(self.start_tag(EsMapVal as uint));
1018 // ___________________________________________________________________________
1025 use {Encodable, Decodable};
1027 use std::io::MemWriter;
1028 use std::option::{None, Option, Some};
1031 fn test_vuint_at() {
1039 0x10, 0x00, 0x00, 0x00,
1040 0x1f, 0xff, 0xff, 0xff
1043 let mut res: reader::Res;
1046 res = reader::vuint_at(data, 0).unwrap();
1047 assert_eq!(res.val, 0);
1048 assert_eq!(res.next, 1);
1049 res = reader::vuint_at(data, res.next).unwrap();
1050 assert_eq!(res.val, (1 << 7) - 1);
1051 assert_eq!(res.next, 2);
1054 res = reader::vuint_at(data, res.next).unwrap();
1055 assert_eq!(res.val, 0);
1056 assert_eq!(res.next, 4);
1057 res = reader::vuint_at(data, res.next).unwrap();
1058 assert_eq!(res.val, (1 << 14) - 1);
1059 assert_eq!(res.next, 6);
1062 res = reader::vuint_at(data, res.next).unwrap();
1063 assert_eq!(res.val, 0);
1064 assert_eq!(res.next, 9);
1065 res = reader::vuint_at(data, res.next).unwrap();
1066 assert_eq!(res.val, (1 << 21) - 1);
1067 assert_eq!(res.next, 12);
1070 res = reader::vuint_at(data, res.next).unwrap();
1071 assert_eq!(res.val, 0);
1072 assert_eq!(res.next, 16);
1073 res = reader::vuint_at(data, res.next).unwrap();
1074 assert_eq!(res.val, (1 << 28) - 1);
1075 assert_eq!(res.next, 20);
1079 fn test_option_int() {
1080 fn test_v(v: Option<int>) {
1081 debug!("v == {}", v);
1082 let mut wr = MemWriter::new();
1084 let mut ebml_w = writer::Encoder(&mut wr);
1085 let _ = v.encode(&mut ebml_w);
1087 let ebml_doc = reader::Doc(wr.get_ref());
1088 let mut deser = reader::Decoder(ebml_doc);
1089 let v1 = Decodable::decode(&mut deser).unwrap();
1090 debug!("v1 == {}", v1);
1103 use self::test::Bencher;
1107 pub fn vuint_at_A_aligned(b: &mut Bencher) {
1108 let data = Vec::from_fn(4*100, |i| {
1117 while i < data.len() {
1118 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1125 pub fn vuint_at_A_unaligned(b: &mut Bencher) {
1126 let data = Vec::from_fn(4*100+1, |i| {
1135 while i < data.len() {
1136 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;
1143 pub fn vuint_at_D_aligned(b: &mut Bencher) {
1144 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_D_unaligned(b: &mut Bencher) {
1163 let data = Vec::from_fn(4*100+1, |i| {
1173 while i < data.len() {
1174 sum += reader::vuint_at(data.as_slice(), i).unwrap().val;