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) -> ~str {
38 self.as_str_slice().to_owned()
42 pub struct TaggedDoc<'a> {
47 pub enum EbmlEncoderTag {
77 EsLabel, // Used only when debugging
86 // --------------------------------------
91 use std::cast::transmute;
93 use std::option::{None, Option, Some};
94 use std::io::extensions::u64_from_be_bytes;
98 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
99 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
100 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
101 EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, Error, IntTooBig,
104 pub type DecodeResult<T> = Result<T, Error>;
108 ($e:expr, $r:expr) => (
112 debug!("ignored error: {}", e);
125 fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
127 if a & 0x80u8 != 0u8 {
128 return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
130 if a & 0x40u8 != 0u8 {
131 return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
132 (data[start + 1u] as uint),
135 if a & 0x20u8 != 0u8 {
136 return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
137 (data[start + 1u] as uint) << 8u |
138 (data[start + 2u] as uint),
141 if a & 0x10u8 != 0u8 {
142 return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
143 (data[start + 1u] as uint) << 16u |
144 (data[start + 2u] as uint) << 8u |
145 (data[start + 3u] as uint),
148 Err(IntTooBig(a as uint))
151 pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
152 use std::mem::from_be32;
154 if data.len() - start < 4 {
155 return vuint_at_slow(data, start);
158 // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
159 // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
160 // Using the four most significant bits of the u32 we lookup in the table below how the
161 // element ID should be derived from it.
163 // The table stores tuples (shift, mask) where shift is the number the u32 should be right
164 // shifted with and mask is the value the right shifted value should be masked with.
165 // If for example the most significant bit is set this means it's a class A ID and the u32
166 // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
167 // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
169 // By storing the number of shifts and masks in a table instead of checking in order if
170 // the most significant bit is set, the second most significant bit is set etc. we can
171 // replace up to three "and+branch" with a single table lookup which gives us a measured
172 // speedup of around 2x on x86_64.
173 static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
174 (0, 0x0), (0, 0x0fffffff),
175 (8, 0x1fffff), (8, 0x1fffff),
176 (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
177 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
178 (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
182 let ptr = data.as_ptr().offset(start as int) as *i32;
183 let val = from_be32(*ptr) as u32;
185 let i = (val >> 28u) as uint;
186 let (shift, mask) = SHIFT_MASK_TABLE[i];
188 val: ((val >> shift) & mask) as uint,
189 next: start + (((32 - shift) >> 3) as uint)
194 pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
195 Doc { data: data, start: 0u, end: data.len() }
198 pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
199 let elt_tag = try!(vuint_at(data, start));
200 let elt_size = try!(vuint_at(data, elt_tag.next));
201 let end = elt_size.next + elt_size.val;
204 doc: Doc { data: data, start: elt_size.next, end: end }
208 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
209 let mut pos = d.start;
211 let elt_tag = try_or!(vuint_at(d.data, pos), None);
212 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
213 pos = elt_size.next + elt_size.val;
214 if elt_tag.val == tg {
215 return Some(Doc { data: d.data, start: elt_size.next,
222 pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
223 match maybe_get_doc(d, tg) {
226 error!("failed to find block with tag {}", tg);
232 pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
233 let mut pos = d.start;
235 let elt_tag = try_or!(vuint_at(d.data, pos), false);
236 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
237 pos = elt_size.next + elt_size.val;
238 let doc = Doc { data: d.data, start: elt_size.next, end: pos };
239 if !it(elt_tag.val, doc) {
246 pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
247 let mut pos = d.start;
249 let elt_tag = try_or!(vuint_at(d.data, pos), false);
250 let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
251 pos = elt_size.next + elt_size.val;
252 if elt_tag.val == tg {
253 let doc = Doc { data: d.data, start: elt_size.next,
263 pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
264 f(d.data.slice(d.start, d.end))
268 pub fn doc_as_u8(d: Doc) -> u8 {
269 assert_eq!(d.end, d.start + 1u);
273 pub fn doc_as_u16(d: Doc) -> u16 {
274 assert_eq!(d.end, d.start + 2u);
275 u64_from_be_bytes(d.data, d.start, 2u) as u16
278 pub fn doc_as_u32(d: Doc) -> u32 {
279 assert_eq!(d.end, d.start + 4u);
280 u64_from_be_bytes(d.data, d.start, 4u) as u32
283 pub fn doc_as_u64(d: Doc) -> u64 {
284 assert_eq!(d.end, d.start + 8u);
285 u64_from_be_bytes(d.data, d.start, 8u)
288 pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
289 pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
290 pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
291 pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
293 pub struct Decoder<'a> {
294 priv parent: Doc<'a>,
298 pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
305 impl<'doc> Decoder<'doc> {
306 fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
307 if self.pos < self.parent.end {
308 let TaggedDoc { tag: r_tag, doc: r_doc } =
309 try!(doc_at(self.parent.data, self.pos));
311 if r_tag == (EsLabel as uint) {
312 self.pos = r_doc.end;
313 let str = r_doc.as_str_slice();
315 return Err(Expected(format!("Expected label {} but found {}", lbl, str)));
322 fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
323 debug!(". next_doc(exp_tag={:?})", exp_tag);
324 if self.pos >= self.parent.end {
325 return Err(Expected(format!("no more documents in current node!")));
327 let TaggedDoc { tag: r_tag, doc: r_doc } =
328 try!(doc_at(self.parent.data, self.pos));
329 debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
336 if r_tag != (exp_tag as uint) {
337 return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}",
340 if r_doc.end > self.parent.end {
341 return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to {:#x}",
342 r_doc.end, self.parent.end)));
344 self.pos = r_doc.end;
348 fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
349 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
350 let d = try!(self.next_doc(exp_tag));
351 let old_parent = self.parent;
352 let old_pos = self.pos;
355 let r = try!(f(self));
356 self.parent = old_parent;
361 fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
362 let r = doc_as_u32(try!(self.next_doc(exp_tag)));
363 debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
367 pub fn read_opaque<R>(&mut self,
368 op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
369 let doc = try!(self.next_doc(EsOpaque));
371 let (old_parent, old_pos) = (self.parent, self.pos);
373 self.pos = doc.start;
375 let result = try!(op(self, doc));
377 self.parent = old_parent;
383 impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
384 fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
386 fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
387 fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
388 fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
389 fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
390 fn read_uint(&mut self) -> DecodeResult<uint> {
391 let v = doc_as_u64(try!(self.next_doc(EsUint)));
392 if v > (::std::uint::MAX as u64) {
393 Err(IntTooBig(v as uint))
399 fn read_i64(&mut self) -> DecodeResult<i64> {
400 Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
402 fn read_i32(&mut self) -> DecodeResult<i32> {
403 Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
405 fn read_i16(&mut self) -> DecodeResult<i16> {
406 Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
408 fn read_i8 (&mut self) -> DecodeResult<i8> {
409 Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
411 fn read_int(&mut self) -> DecodeResult<int> {
412 let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
413 if v > (int::MAX as i64) || v < (int::MIN as i64) {
414 debug!("FIXME \\#6122: Removing this makes this function miscompile");
415 Err(IntTooBig(v as uint))
421 fn read_bool(&mut self) -> DecodeResult<bool> {
422 Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
425 fn read_f64(&mut self) -> DecodeResult<f64> {
426 let bits = doc_as_u64(try!(self.next_doc(EsF64)));
427 Ok(unsafe { transmute(bits) })
429 fn read_f32(&mut self) -> DecodeResult<f32> {
430 let bits = doc_as_u32(try!(self.next_doc(EsF32)));
431 Ok(unsafe { transmute(bits) })
433 fn read_char(&mut self) -> DecodeResult<char> {
434 Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
436 fn read_str(&mut self) -> DecodeResult<~str> {
437 Ok(try!(self.next_doc(EsStr)).as_str())
441 fn read_enum<T>(&mut self,
443 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
444 debug!("read_enum({})", name);
445 try!(self._check_label(name));
447 let doc = try!(self.next_doc(EsEnum));
449 let (old_parent, old_pos) = (self.parent, self.pos);
451 self.pos = self.parent.start;
453 let result = try!(f(self));
455 self.parent = old_parent;
460 fn read_enum_variant<T>(&mut self,
462 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
464 debug!("read_enum_variant()");
465 let idx = try!(self._next_uint(EsEnumVid));
466 debug!(" idx={}", idx);
468 let doc = try!(self.next_doc(EsEnumBody));
470 let (old_parent, old_pos) = (self.parent, self.pos);
472 self.pos = self.parent.start;
474 let result = try!(f(self, idx));
476 self.parent = old_parent;
481 fn read_enum_variant_arg<T>(&mut self,
483 f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
484 debug!("read_enum_variant_arg(idx={})", idx);
488 fn read_enum_struct_variant<T>(&mut self,
490 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
492 debug!("read_enum_struct_variant()");
493 let idx = try!(self._next_uint(EsEnumVid));
494 debug!(" idx={}", idx);
496 let doc = try!(self.next_doc(EsEnumBody));
498 let (old_parent, old_pos) = (self.parent, self.pos);
500 self.pos = self.parent.start;
502 let result = try!(f(self, idx));
504 self.parent = old_parent;
509 fn read_enum_struct_variant_field<T>(&mut self,
512 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
514 debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
518 fn read_struct<T>(&mut self,
521 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
523 debug!("read_struct(name={})", name);
527 fn read_struct_field<T>(&mut self,
530 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
532 debug!("read_struct_field(name={}, idx={})", name, idx);
533 try!(self._check_label(name));
537 fn read_tuple<T>(&mut self,
538 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
539 debug!("read_tuple()");
543 fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
545 debug!("read_tuple_arg(idx={})", idx);
546 self.read_seq_elt(idx, f)
549 fn read_tuple_struct<T>(&mut self,
551 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
553 debug!("read_tuple_struct(name={})", name);
557 fn read_tuple_struct_arg<T>(&mut self,
559 f: |&mut Decoder<'doc>| -> DecodeResult<T>)
561 debug!("read_tuple_struct_arg(idx={})", idx);
562 self.read_tuple_arg(idx, f)
565 fn read_option<T>(&mut self,
566 f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
567 debug!("read_option()");
568 self.read_enum("Option", |this| {
569 this.read_enum_variant(["None", "Some"], |this, idx| {
573 _ => Err(Expected(format!("Expected None or Some"))),
579 fn read_seq<T>(&mut self,
580 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
581 debug!("read_seq()");
582 self.push_doc(EsVec, |d| {
583 let len = try!(d._next_uint(EsVecLen));
584 debug!(" len={}", len);
589 fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
591 debug!("read_seq_elt(idx={})", idx);
592 self.push_doc(EsVecElt, f)
595 fn read_map<T>(&mut self,
596 f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
597 debug!("read_map()");
598 self.push_doc(EsMap, |d| {
599 let len = try!(d._next_uint(EsMapLen));
600 debug!(" len={}", len);
605 fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
607 debug!("read_map_elt_key(idx={})", idx);
608 self.push_doc(EsMapKey, f)
611 fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
613 debug!("read_map_elt_val(idx={})", idx);
614 self.push_doc(EsMapVal, f)
621 use std::clone::Clone;
623 use std::io::{Writer, Seek};
624 use std::io::extensions::u64_to_be_bytes;
626 use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
627 EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
628 EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
629 EsOpaque, EsLabel, EbmlEncoderTag };
634 pub type EncodeResult = io::IoResult<()>;
637 pub struct Encoder<'a, W> {
639 priv size_positions: ~[uint],
642 fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
644 1u => w.write(&[0x80u8 | (n as u8)]),
645 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
646 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
648 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
649 (n >> 8_u) as u8, n as u8]),
650 _ => Err(io::IoError {
651 kind: io::OtherIoError,
653 detail: Some(format!("{}", n))
658 fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
659 if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
660 if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
661 if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
662 if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
664 kind: io::OtherIoError,
666 detail: Some(format!("{}", n))
670 pub fn Encoder<'a, W: Writer + Seek>(w: &'a mut W) -> Encoder<'a, W> {
671 let size_positions: ~[uint] = ~[];
674 size_positions: size_positions,
678 // FIXME (#2741): Provide a function to write the standard ebml header.
679 impl<'a, W: Writer + Seek> Encoder<'a, W> {
680 /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
681 pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
683 writer: cast::transmute_copy(&self.writer),
684 size_positions: self.size_positions.clone(),
688 pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
689 debug!("Start tag {}", tag_id);
691 // Write the enum ID:
692 try!(write_vuint(self.writer, tag_id));
694 // Write a placeholder four-byte size.
695 self.size_positions.push(try!(self.writer.tell()) as uint);
696 let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
697 self.writer.write(zeroes)
700 pub fn end_tag(&mut self) -> EncodeResult {
701 let last_size_pos = self.size_positions.pop().unwrap();
702 let cur_pos = try!(self.writer.tell());
703 try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
704 let size = cur_pos as uint - last_size_pos - 4;
705 try!(write_sized_vuint(self.writer, size, 4u));
706 let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
708 debug!("End tag (size = {})", size);
712 pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
713 try!(self.start_tag(tag_id));
718 pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
719 try!(write_vuint(self.writer, tag_id));
720 try!(write_vuint(self.writer, b.len()));
724 pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
725 u64_to_be_bytes(v, 8u, |v| {
726 self.wr_tagged_bytes(tag_id, v)
730 pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
731 u64_to_be_bytes(v as u64, 4u, |v| {
732 self.wr_tagged_bytes(tag_id, v)
736 pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
737 u64_to_be_bytes(v as u64, 2u, |v| {
738 self.wr_tagged_bytes(tag_id, v)
742 pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
743 self.wr_tagged_bytes(tag_id, &[v])
746 pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
747 u64_to_be_bytes(v as u64, 8u, |v| {
748 self.wr_tagged_bytes(tag_id, v)
752 pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
753 u64_to_be_bytes(v as u64, 4u, |v| {
754 self.wr_tagged_bytes(tag_id, v)
758 pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
759 u64_to_be_bytes(v as u64, 2u, |v| {
760 self.wr_tagged_bytes(tag_id, v)
764 pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
765 self.wr_tagged_bytes(tag_id, &[v as u8])
768 pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
769 self.wr_tagged_bytes(tag_id, v.as_bytes())
772 pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
773 debug!("Write {} bytes", b.len());
777 pub fn wr_str(&mut self, s: &str) -> EncodeResult {
778 debug!("Write str: {}", s);
779 self.writer.write(s.as_bytes())
783 // FIXME (#2743): optionally perform "relaxations" on end_tag to more
784 // efficiently encode sizes; this is a fixed point iteration
786 // Set to true to generate more debugging in EBML code.
787 // Totally lame approach.
788 static DEBUG: bool = true;
790 impl<'a, W: Writer + Seek> Encoder<'a, W> {
791 // used internally to emit things like the vector length and so on
792 fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
793 assert!(v <= 0xFFFF_FFFF_u);
794 self.wr_tagged_u32(t as uint, v as u32)
797 fn _emit_label(&mut self, label: &str) -> EncodeResult {
798 // There are various strings that we have access to, such as
799 // the name of a record field, which do not actually appear in
800 // the encoded EBML (normally). This is just for
801 // efficiency. When debugging, though, we can emit such
802 // labels and then they will be checked by decoder to
803 // try and check failures more quickly.
804 if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
808 pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
809 try!(self.start_tag(EsOpaque as uint));
815 impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
816 fn emit_nil(&mut self) -> EncodeResult {
820 fn emit_uint(&mut self, v: uint) -> EncodeResult {
821 self.wr_tagged_u64(EsUint as uint, v as u64)
823 fn emit_u64(&mut self, v: u64) -> EncodeResult {
824 self.wr_tagged_u64(EsU64 as uint, v)
826 fn emit_u32(&mut self, v: u32) -> EncodeResult {
827 self.wr_tagged_u32(EsU32 as uint, v)
829 fn emit_u16(&mut self, v: u16) -> EncodeResult {
830 self.wr_tagged_u16(EsU16 as uint, v)
832 fn emit_u8(&mut self, v: u8) -> EncodeResult {
833 self.wr_tagged_u8(EsU8 as uint, v)
836 fn emit_int(&mut self, v: int) -> EncodeResult {
837 self.wr_tagged_i64(EsInt as uint, v as i64)
839 fn emit_i64(&mut self, v: i64) -> EncodeResult {
840 self.wr_tagged_i64(EsI64 as uint, v)
842 fn emit_i32(&mut self, v: i32) -> EncodeResult {
843 self.wr_tagged_i32(EsI32 as uint, v)
845 fn emit_i16(&mut self, v: i16) -> EncodeResult {
846 self.wr_tagged_i16(EsI16 as uint, v)
848 fn emit_i8(&mut self, v: i8) -> EncodeResult {
849 self.wr_tagged_i8(EsI8 as uint, v)
852 fn emit_bool(&mut self, v: bool) -> EncodeResult {
853 self.wr_tagged_u8(EsBool as uint, v as u8)
856 fn emit_f64(&mut self, v: f64) -> EncodeResult {
857 let bits = unsafe { cast::transmute(v) };
858 self.wr_tagged_u64(EsF64 as uint, bits)
860 fn emit_f32(&mut self, v: f32) -> EncodeResult {
861 let bits = unsafe { cast::transmute(v) };
862 self.wr_tagged_u32(EsF32 as uint, bits)
864 fn emit_char(&mut self, v: char) -> EncodeResult {
865 self.wr_tagged_u32(EsChar as uint, v as u32)
868 fn emit_str(&mut self, v: &str) -> EncodeResult {
869 self.wr_tagged_str(EsStr as uint, v)
872 fn emit_enum(&mut self,
874 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
875 try!(self._emit_label(name));
876 try!(self.start_tag(EsEnum as uint));
881 fn emit_enum_variant(&mut self,
885 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
886 try!(self._emit_tagged_uint(EsEnumVid, v_id));
887 try!(self.start_tag(EsEnumBody as uint));
892 fn emit_enum_variant_arg(&mut self,
894 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
898 fn emit_enum_struct_variant(&mut self,
902 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
903 self.emit_enum_variant(v_name, v_id, cnt, f)
906 fn emit_enum_struct_variant_field(&mut self,
909 f: |&mut Encoder<'a, W>| -> EncodeResult)
911 self.emit_enum_variant_arg(idx, f)
914 fn emit_struct(&mut self,
917 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
921 fn emit_struct_field(&mut self,
924 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
925 try!(self._emit_label(name));
929 fn emit_tuple(&mut self,
931 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
932 self.emit_seq(len, f)
934 fn emit_tuple_arg(&mut self,
936 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
937 self.emit_seq_elt(idx, f)
940 fn emit_tuple_struct(&mut self,
943 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
944 self.emit_seq(len, f)
946 fn emit_tuple_struct_arg(&mut self,
948 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
949 self.emit_seq_elt(idx, f)
952 fn emit_option(&mut self,
953 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
954 self.emit_enum("Option", f)
956 fn emit_option_none(&mut self) -> EncodeResult {
957 self.emit_enum_variant("None", 0, 0, |_| Ok(()))
959 fn emit_option_some(&mut self,
960 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
962 self.emit_enum_variant("Some", 1, 1, f)
965 fn emit_seq(&mut self,
967 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
969 try!(self.start_tag(EsVec as uint));
970 try!(self._emit_tagged_uint(EsVecLen, len));
975 fn emit_seq_elt(&mut self,
977 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
979 try!(self.start_tag(EsVecElt as uint));
984 fn emit_map(&mut self,
986 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
988 try!(self.start_tag(EsMap as uint));
989 try!(self._emit_tagged_uint(EsMapLen, len));
994 fn emit_map_elt_key(&mut self,
996 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
998 try!(self.start_tag(EsMapKey as uint));
1003 fn emit_map_elt_val(&mut self,
1005 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
1006 try!(self.start_tag(EsMapVal as uint));
1013 // ___________________________________________________________________________
1020 use {Encodable, Decodable};
1022 use std::io::MemWriter;
1023 use std::option::{None, Option, Some};
1026 fn test_vuint_at() {
1034 0x10, 0x00, 0x00, 0x00,
1035 0x1f, 0xff, 0xff, 0xff
1038 let mut res: reader::Res;
1041 res = reader::vuint_at(data, 0).unwrap();
1042 assert_eq!(res.val, 0);
1043 assert_eq!(res.next, 1);
1044 res = reader::vuint_at(data, res.next).unwrap();
1045 assert_eq!(res.val, (1 << 7) - 1);
1046 assert_eq!(res.next, 2);
1049 res = reader::vuint_at(data, res.next).unwrap();
1050 assert_eq!(res.val, 0);
1051 assert_eq!(res.next, 4);
1052 res = reader::vuint_at(data, res.next).unwrap();
1053 assert_eq!(res.val, (1 << 14) - 1);
1054 assert_eq!(res.next, 6);
1057 res = reader::vuint_at(data, res.next).unwrap();
1058 assert_eq!(res.val, 0);
1059 assert_eq!(res.next, 9);
1060 res = reader::vuint_at(data, res.next).unwrap();
1061 assert_eq!(res.val, (1 << 21) - 1);
1062 assert_eq!(res.next, 12);
1065 res = reader::vuint_at(data, res.next).unwrap();
1066 assert_eq!(res.val, 0);
1067 assert_eq!(res.next, 16);
1068 res = reader::vuint_at(data, res.next).unwrap();
1069 assert_eq!(res.val, (1 << 28) - 1);
1070 assert_eq!(res.next, 20);
1074 fn test_option_int() {
1075 fn test_v(v: Option<int>) {
1076 debug!("v == {:?}", v);
1077 let mut wr = MemWriter::new();
1079 let mut ebml_w = writer::Encoder(&mut wr);
1080 let _ = v.encode(&mut ebml_w);
1082 let ebml_doc = reader::Doc(wr.get_ref());
1083 let mut deser = reader::Decoder(ebml_doc);
1084 let v1 = Decodable::decode(&mut deser).unwrap();
1085 debug!("v1 == {:?}", v1);
1098 use self::test::BenchHarness;
1102 pub fn vuint_at_A_aligned(bh: &mut BenchHarness) {
1104 let data = slice::from_fn(4*100, |i| {
1113 while i < data.len() {
1114 sum += reader::vuint_at(data, i).unwrap().val;
1121 pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) {
1123 let data = slice::from_fn(4*100+1, |i| {
1132 while i < data.len() {
1133 sum += reader::vuint_at(data, i).unwrap().val;
1140 pub fn vuint_at_D_aligned(bh: &mut BenchHarness) {
1142 let data = slice::from_fn(4*100, |i| {
1152 while i < data.len() {
1153 sum += reader::vuint_at(data, i).unwrap().val;
1160 pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) {
1162 let data = slice::from_fn(4*100+1, |i| {
1172 while i < data.len() {
1173 sum += reader::vuint_at(data, i).unwrap().val;