]> git.lizzy.rs Git - rust.git/blob - src/libextra/ebml.rs
Tweak the interface of std::io
[rust.git] / src / libextra / ebml.rs
1 // Copyright 2012-2013 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.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #[allow(missing_doc)];
12
13 use std::str;
14
15 // Simple Extensible Binary Markup Language (ebml) reader and writer on a
16 // cursor model. See the specification here:
17 //     http://www.matroska.org/technical/specs/rfc/index.html
18
19 // Common data structures
20 #[deriving(Clone)]
21 pub struct Doc<'a> {
22     data: &'a [u8],
23     start: uint,
24     end: uint,
25 }
26
27 impl<'doc> Doc<'doc> {
28     pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
29         reader::get_doc(*self, tag)
30     }
31
32     pub fn as_str_slice<'a>(&'a self) -> &'a str {
33         str::from_utf8(self.data.slice(self.start, self.end))
34     }
35
36     pub fn as_str(&self) -> ~str {
37         self.as_str_slice().to_owned()
38     }
39 }
40
41 pub struct TaggedDoc<'a> {
42     priv tag: uint,
43     doc: Doc<'a>,
44 }
45
46 pub enum EbmlEncoderTag {
47     EsUint,     // 0
48     EsU64,      // 1
49     EsU32,      // 2
50     EsU16,      // 3
51     EsU8,       // 4
52     EsInt,      // 5
53     EsI64,      // 6
54     EsI32,      // 7
55     EsI16,      // 8
56     EsI8,       // 9
57     EsBool,     // 10
58     EsChar,     // 11
59     EsStr,      // 12
60     EsF64,      // 13
61     EsF32,      // 14
62     EsFloat,    // 15
63     EsEnum,     // 16
64     EsEnumVid,  // 17
65     EsEnumBody, // 18
66     EsVec,      // 19
67     EsVecLen,   // 20
68     EsVecElt,   // 21
69     EsMap,      // 22
70     EsMapLen,   // 23
71     EsMapKey,   // 24
72     EsMapVal,   // 25
73
74     EsOpaque,
75
76     EsLabel, // Used only when debugging
77 }
78 // --------------------------------------
79
80 pub mod reader {
81     use std::char;
82     use super::*;
83
84     use serialize;
85
86     use std::cast::transmute;
87     use std::int;
88     use std::option::{None, Option, Some};
89     use std::io::extensions::u64_from_be_bytes;
90
91     // ebml reading
92
93     struct Res {
94         val: uint,
95         next: uint
96     }
97
98     #[inline(never)]
99     fn vuint_at_slow(data: &[u8], start: uint) -> Res {
100         let a = data[start];
101         if a & 0x80u8 != 0u8 {
102             return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
103         }
104         if a & 0x40u8 != 0u8 {
105             return Res {val: ((a & 0x3fu8) as uint) << 8u |
106                         (data[start + 1u] as uint),
107                     next: start + 2u};
108         }
109         if a & 0x20u8 != 0u8 {
110             return Res {val: ((a & 0x1fu8) as uint) << 16u |
111                         (data[start + 1u] as uint) << 8u |
112                         (data[start + 2u] as uint),
113                     next: start + 3u};
114         }
115         if a & 0x10u8 != 0u8 {
116             return Res {val: ((a & 0x0fu8) as uint) << 24u |
117                         (data[start + 1u] as uint) << 16u |
118                         (data[start + 2u] as uint) << 8u |
119                         (data[start + 3u] as uint),
120                     next: start + 4u};
121         }
122         fail!("vint too big");
123     }
124
125     pub fn vuint_at(data: &[u8], start: uint) -> Res {
126         use std::ptr::offset;
127         use std::unstable::intrinsics::from_be32;
128
129         if data.len() - start < 4 {
130             return vuint_at_slow(data, start);
131         }
132
133         unsafe {
134             let (ptr, _): (*u8, uint) = transmute(data);
135             let ptr = offset(ptr, start as int);
136             let ptr: *i32 = transmute(ptr);
137             let val = from_be32(*ptr);
138             let val: u32 = transmute(val);
139             if (val & 0x80000000) != 0 {
140                 Res {
141                     val: ((val >> 24) & 0x7f) as uint,
142                     next: start + 1
143                 }
144             } else if (val & 0x40000000) != 0 {
145                 Res {
146                     val: ((val >> 16) & 0x3fff) as uint,
147                     next: start + 2
148                 }
149             } else if (val & 0x20000000) != 0 {
150                 Res {
151                     val: ((val >> 8) & 0x1fffff) as uint,
152                     next: start + 3
153                 }
154             } else {
155                 Res {
156                     val: (val & 0x0fffffff) as uint,
157                     next: start + 4
158                 }
159             }
160         }
161     }
162
163     pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
164         Doc { data: data, start: 0u, end: data.len() }
165     }
166
167     pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> {
168         let elt_tag = vuint_at(data, start);
169         let elt_size = vuint_at(data, elt_tag.next);
170         let end = elt_size.next + elt_size.val;
171         TaggedDoc {
172             tag: elt_tag.val,
173             doc: Doc { data: data, start: elt_size.next, end: end }
174         }
175     }
176
177     pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
178         let mut pos = d.start;
179         while pos < d.end {
180             let elt_tag = vuint_at(d.data, pos);
181             let elt_size = vuint_at(d.data, elt_tag.next);
182             pos = elt_size.next + elt_size.val;
183             if elt_tag.val == tg {
184                 return Some(Doc { data: d.data, start: elt_size.next,
185                                   end: pos });
186             }
187         }
188         None
189     }
190
191     pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
192         match maybe_get_doc(d, tg) {
193             Some(d) => d,
194             None => {
195                 error!("failed to find block with tag {}", tg);
196                 fail!();
197             }
198         }
199     }
200
201     pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
202         let mut pos = d.start;
203         while pos < d.end {
204             let elt_tag = vuint_at(d.data, pos);
205             let elt_size = vuint_at(d.data, elt_tag.next);
206             pos = elt_size.next + elt_size.val;
207             let doc = Doc { data: d.data, start: elt_size.next, end: pos };
208             if !it(elt_tag.val, doc) {
209                 return false;
210             }
211         }
212         return true;
213     }
214
215     pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
216         let mut pos = d.start;
217         while pos < d.end {
218             let elt_tag = vuint_at(d.data, pos);
219             let elt_size = vuint_at(d.data, elt_tag.next);
220             pos = elt_size.next + elt_size.val;
221             if elt_tag.val == tg {
222                 let doc = Doc { data: d.data, start: elt_size.next,
223                                 end: pos };
224                 if !it(doc) {
225                     return false;
226                 }
227             }
228         }
229         return true;
230     }
231
232     pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
233         f(d.data.slice(d.start, d.end))
234     }
235
236
237     pub fn doc_as_u8(d: Doc) -> u8 {
238         assert_eq!(d.end, d.start + 1u);
239         d.data[d.start]
240     }
241
242     pub fn doc_as_u16(d: Doc) -> u16 {
243         assert_eq!(d.end, d.start + 2u);
244         u64_from_be_bytes(d.data, d.start, 2u) as u16
245     }
246
247     pub fn doc_as_u32(d: Doc) -> u32 {
248         assert_eq!(d.end, d.start + 4u);
249         u64_from_be_bytes(d.data, d.start, 4u) as u32
250     }
251
252     pub fn doc_as_u64(d: Doc) -> u64 {
253         assert_eq!(d.end, d.start + 8u);
254         u64_from_be_bytes(d.data, d.start, 8u)
255     }
256
257     pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
258     pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
259     pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
260     pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
261
262     pub struct Decoder<'a> {
263         priv parent: Doc<'a>,
264         priv pos: uint,
265     }
266
267     pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
268         Decoder {
269             parent: d,
270             pos: d.start
271         }
272     }
273
274     impl<'doc> Decoder<'doc> {
275         fn _check_label(&mut self, lbl: &str) {
276             if self.pos < self.parent.end {
277                 let TaggedDoc { tag: r_tag, doc: r_doc } =
278                     doc_at(self.parent.data, self.pos);
279
280                 if r_tag == (EsLabel as uint) {
281                     self.pos = r_doc.end;
282                     let str = r_doc.as_str_slice();
283                     if lbl != str {
284                         fail!("Expected label {} but found {}", lbl, str);
285                     }
286                 }
287             }
288         }
289
290         fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
291             debug!(". next_doc(exp_tag={:?})", exp_tag);
292             if self.pos >= self.parent.end {
293                 fail!("no more documents in current node!");
294             }
295             let TaggedDoc { tag: r_tag, doc: r_doc } =
296                 doc_at(self.parent.data, self.pos);
297             debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
298                    self.parent.start,
299                    self.parent.end,
300                    self.pos,
301                    r_tag,
302                    r_doc.start,
303                    r_doc.end);
304             if r_tag != (exp_tag as uint) {
305                 fail!("expected EBML doc with tag {:?} but found tag {:?}",
306                        exp_tag, r_tag);
307             }
308             if r_doc.end > self.parent.end {
309                 fail!("invalid EBML, child extends to {:#x}, parent to {:#x}",
310                       r_doc.end, self.parent.end);
311             }
312             self.pos = r_doc.end;
313             r_doc
314         }
315
316         fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
317                        f: |&mut Decoder<'doc>| -> T) -> T {
318             let d = self.next_doc(exp_tag);
319             let old_parent = self.parent;
320             let old_pos = self.pos;
321             self.parent = d;
322             self.pos = d.start;
323             let r = f(self);
324             self.parent = old_parent;
325             self.pos = old_pos;
326             r
327         }
328
329         fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
330             let r = doc_as_u32(self.next_doc(exp_tag));
331             debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
332             r as uint
333         }
334
335         pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R {
336             let doc = self.next_doc(EsOpaque);
337
338             let (old_parent, old_pos) = (self.parent, self.pos);
339             self.parent = doc;
340             self.pos = doc.start;
341
342             let result = op(self, doc);
343
344             self.parent = old_parent;
345             self.pos = old_pos;
346             result
347         }
348     }
349
350     impl<'doc> serialize::Decoder for Decoder<'doc> {
351         fn read_nil(&mut self) -> () { () }
352
353         fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
354         fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
355         fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
356         fn read_u8 (&mut self) -> u8  { doc_as_u8 (self.next_doc(EsU8 )) }
357         fn read_uint(&mut self) -> uint {
358             let v = doc_as_u64(self.next_doc(EsUint));
359             if v > (::std::uint::max_value as u64) {
360                 fail!("uint {} too large for this architecture", v);
361             }
362             v as uint
363         }
364
365         fn read_i64(&mut self) -> i64 {
366             doc_as_u64(self.next_doc(EsI64)) as i64
367         }
368         fn read_i32(&mut self) -> i32 {
369             doc_as_u32(self.next_doc(EsI32)) as i32
370         }
371         fn read_i16(&mut self) -> i16 {
372             doc_as_u16(self.next_doc(EsI16)) as i16
373         }
374         fn read_i8 (&mut self) -> i8 {
375             doc_as_u8(self.next_doc(EsI8 )) as i8
376         }
377         fn read_int(&mut self) -> int {
378             let v = doc_as_u64(self.next_doc(EsInt)) as i64;
379             if v > (int::max_value as i64) || v < (int::min_value as i64) {
380                 debug!("FIXME \\#6122: Removing this makes this function miscompile");
381                 fail!("int {} out of range for this architecture", v);
382             }
383             v as int
384         }
385
386         fn read_bool(&mut self) -> bool {
387             doc_as_u8(self.next_doc(EsBool)) != 0
388         }
389
390         fn read_f64(&mut self) -> f64 {
391             let bits = doc_as_u64(self.next_doc(EsF64));
392             unsafe { transmute(bits) }
393         }
394         fn read_f32(&mut self) -> f32 {
395             let bits = doc_as_u32(self.next_doc(EsF32));
396             unsafe { transmute(bits) }
397         }
398         fn read_char(&mut self) -> char {
399             char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
400         }
401         fn read_str(&mut self) -> ~str {
402             self.next_doc(EsStr).as_str()
403         }
404
405         // Compound types:
406         fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T {
407             debug!("read_enum({})", name);
408             self._check_label(name);
409
410             let doc = self.next_doc(EsEnum);
411
412             let (old_parent, old_pos) = (self.parent, self.pos);
413             self.parent = doc;
414             self.pos = self.parent.start;
415
416             let result = f(self);
417
418             self.parent = old_parent;
419             self.pos = old_pos;
420             result
421         }
422
423         fn read_enum_variant<T>(&mut self,
424                                 _: &[&str],
425                                 f: |&mut Decoder<'doc>, uint| -> T)
426                                 -> T {
427             debug!("read_enum_variant()");
428             let idx = self._next_uint(EsEnumVid);
429             debug!("  idx={}", idx);
430
431             let doc = self.next_doc(EsEnumBody);
432
433             let (old_parent, old_pos) = (self.parent, self.pos);
434             self.parent = doc;
435             self.pos = self.parent.start;
436
437             let result = f(self, idx);
438
439             self.parent = old_parent;
440             self.pos = old_pos;
441             result
442         }
443
444         fn read_enum_variant_arg<T>(&mut self,
445                                     idx: uint,
446                                     f: |&mut Decoder<'doc>| -> T) -> T {
447             debug!("read_enum_variant_arg(idx={})", idx);
448             f(self)
449         }
450
451         fn read_enum_struct_variant<T>(&mut self,
452                                        _: &[&str],
453                                        f: |&mut Decoder<'doc>, uint| -> T)
454                                        -> T {
455             debug!("read_enum_struct_variant()");
456             let idx = self._next_uint(EsEnumVid);
457             debug!("  idx={}", idx);
458
459             let doc = self.next_doc(EsEnumBody);
460
461             let (old_parent, old_pos) = (self.parent, self.pos);
462             self.parent = doc;
463             self.pos = self.parent.start;
464
465             let result = f(self, idx);
466
467             self.parent = old_parent;
468             self.pos = old_pos;
469             result
470         }
471
472         fn read_enum_struct_variant_field<T>(&mut self,
473                                              name: &str,
474                                              idx: uint,
475                                              f: |&mut Decoder<'doc>| -> T)
476                                              -> T {
477             debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
478             f(self)
479         }
480
481         fn read_struct<T>(&mut self,
482                           name: &str,
483                           _: uint,
484                           f: |&mut Decoder<'doc>| -> T)
485                           -> T {
486             debug!("read_struct(name={})", name);
487             f(self)
488         }
489
490         fn read_struct_field<T>(&mut self,
491                                 name: &str,
492                                 idx: uint,
493                                 f: |&mut Decoder<'doc>| -> T)
494                                 -> T {
495             debug!("read_struct_field(name={}, idx={})", name, idx);
496             self._check_label(name);
497             f(self)
498         }
499
500         fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
501             debug!("read_tuple()");
502             self.read_seq(f)
503         }
504
505         fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
506                              -> T {
507             debug!("read_tuple_arg(idx={})", idx);
508             self.read_seq_elt(idx, f)
509         }
510
511         fn read_tuple_struct<T>(&mut self,
512                                 name: &str,
513                                 f: |&mut Decoder<'doc>, uint| -> T)
514                                 -> T {
515             debug!("read_tuple_struct(name={})", name);
516             self.read_tuple(f)
517         }
518
519         fn read_tuple_struct_arg<T>(&mut self,
520                                     idx: uint,
521                                     f: |&mut Decoder<'doc>| -> T)
522                                     -> T {
523             debug!("read_tuple_struct_arg(idx={})", idx);
524             self.read_tuple_arg(idx, f)
525         }
526
527         fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T {
528             debug!("read_option()");
529             self.read_enum("Option", |this| {
530                 this.read_enum_variant(["None", "Some"], |this, idx| {
531                     match idx {
532                         0 => f(this, false),
533                         1 => f(this, true),
534                         _ => fail!(),
535                     }
536                 })
537             })
538         }
539
540         fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
541             debug!("read_seq()");
542             self.push_doc(EsVec, |d| {
543                 let len = d._next_uint(EsVecLen);
544                 debug!("  len={}", len);
545                 f(d, len)
546             })
547         }
548
549         fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
550                            -> T {
551             debug!("read_seq_elt(idx={})", idx);
552             self.push_doc(EsVecElt, f)
553         }
554
555         fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
556             debug!("read_map()");
557             self.push_doc(EsMap, |d| {
558                 let len = d._next_uint(EsMapLen);
559                 debug!("  len={}", len);
560                 f(d, len)
561             })
562         }
563
564         fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
565                                -> T {
566             debug!("read_map_elt_key(idx={})", idx);
567             self.push_doc(EsMapKey, f)
568         }
569
570         fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
571                                -> T {
572             debug!("read_map_elt_val(idx={})", idx);
573             self.push_doc(EsMapVal, f)
574         }
575     }
576 }
577
578 pub mod writer {
579     use super::*;
580
581     use std::cast;
582     use std::clone::Clone;
583     use std::io;
584     use std::io::{Writer, Seek};
585     use std::io::MemWriter;
586     use std::io::extensions::u64_to_be_bytes;
587
588     // ebml writing
589     pub struct Encoder<'a> {
590         // FIXME(#5665): this should take a trait object
591         writer: &'a mut MemWriter,
592         priv size_positions: ~[uint],
593     }
594
595     fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
596         match size {
597             1u => w.write(&[0x80u8 | (n as u8)]),
598             2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
599             3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
600                             n as u8]),
601             4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
602                             (n >> 8_u) as u8, n as u8]),
603             _ => fail!("vint to write too big: {}", n)
604         };
605     }
606
607     fn write_vuint(w: &mut MemWriter, n: uint) {
608         if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
609         if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
610         if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
611         if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
612         fail!("vint to write too big: {}", n);
613     }
614
615     pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
616         let size_positions: ~[uint] = ~[];
617         Encoder {
618             writer: w,
619             size_positions: size_positions
620         }
621     }
622
623     // FIXME (#2741): Provide a function to write the standard ebml header.
624     impl<'a> Encoder<'a> {
625         /// XXX(pcwalton): Workaround for badness in trans. DO NOT USE ME.
626         pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
627             Encoder {
628                 writer: cast::transmute_copy(&self.writer),
629                 size_positions: self.size_positions.clone(),
630             }
631         }
632
633         pub fn start_tag(&mut self, tag_id: uint) {
634             debug!("Start tag {}", tag_id);
635
636             // Write the enum ID:
637             write_vuint(self.writer, tag_id);
638
639             // Write a placeholder four-byte size.
640             self.size_positions.push(self.writer.tell() as uint);
641             let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
642             self.writer.write(zeroes);
643         }
644
645         pub fn end_tag(&mut self) {
646             let last_size_pos = self.size_positions.pop();
647             let cur_pos = self.writer.tell();
648             self.writer.seek(last_size_pos as i64, io::SeekSet);
649             let size = (cur_pos as uint - last_size_pos - 4);
650             write_sized_vuint(self.writer, size, 4u);
651             self.writer.seek(cur_pos as i64, io::SeekSet);
652
653             debug!("End tag (size = {})", size);
654         }
655
656         pub fn wr_tag(&mut self, tag_id: uint, blk: ||) {
657             self.start_tag(tag_id);
658             blk();
659             self.end_tag();
660         }
661
662         pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
663             write_vuint(self.writer, tag_id);
664             write_vuint(self.writer, b.len());
665             self.writer.write(b);
666         }
667
668         pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
669             u64_to_be_bytes(v, 8u, |v| {
670                 self.wr_tagged_bytes(tag_id, v);
671             })
672         }
673
674         pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
675             u64_to_be_bytes(v as u64, 4u, |v| {
676                 self.wr_tagged_bytes(tag_id, v);
677             })
678         }
679
680         pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
681             u64_to_be_bytes(v as u64, 2u, |v| {
682                 self.wr_tagged_bytes(tag_id, v);
683             })
684         }
685
686         pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
687             self.wr_tagged_bytes(tag_id, &[v]);
688         }
689
690         pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
691             u64_to_be_bytes(v as u64, 8u, |v| {
692                 self.wr_tagged_bytes(tag_id, v);
693             })
694         }
695
696         pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
697             u64_to_be_bytes(v as u64, 4u, |v| {
698                 self.wr_tagged_bytes(tag_id, v);
699             })
700         }
701
702         pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
703             u64_to_be_bytes(v as u64, 2u, |v| {
704                 self.wr_tagged_bytes(tag_id, v);
705             })
706         }
707
708         pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
709             self.wr_tagged_bytes(tag_id, &[v as u8]);
710         }
711
712         pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
713             self.wr_tagged_bytes(tag_id, v.as_bytes());
714         }
715
716         pub fn wr_bytes(&mut self, b: &[u8]) {
717             debug!("Write {} bytes", b.len());
718             self.writer.write(b);
719         }
720
721         pub fn wr_str(&mut self, s: &str) {
722             debug!("Write str: {}", s);
723             self.writer.write(s.as_bytes());
724         }
725     }
726
727     // FIXME (#2743): optionally perform "relaxations" on end_tag to more
728     // efficiently encode sizes; this is a fixed point iteration
729
730     // Set to true to generate more debugging in EBML code.
731     // Totally lame approach.
732     static DEBUG: bool = true;
733
734     impl<'a> Encoder<'a> {
735         // used internally to emit things like the vector length and so on
736         fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
737             assert!(v <= 0xFFFF_FFFF_u);
738             self.wr_tagged_u32(t as uint, v as u32);
739         }
740
741         fn _emit_label(&mut self, label: &str) {
742             // There are various strings that we have access to, such as
743             // the name of a record field, which do not actually appear in
744             // the encoded EBML (normally).  This is just for
745             // efficiency.  When debugging, though, we can emit such
746             // labels and then they will be checked by decoder to
747             // try and check failures more quickly.
748             if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
749         }
750
751         pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
752             self.start_tag(EsOpaque as uint);
753             f(self);
754             self.end_tag();
755         }
756     }
757
758     impl<'a> ::serialize::Encoder for Encoder<'a> {
759         fn emit_nil(&mut self) {}
760
761         fn emit_uint(&mut self, v: uint) {
762             self.wr_tagged_u64(EsUint as uint, v as u64);
763         }
764         fn emit_u64(&mut self, v: u64) {
765             self.wr_tagged_u64(EsU64 as uint, v);
766         }
767         fn emit_u32(&mut self, v: u32) {
768             self.wr_tagged_u32(EsU32 as uint, v);
769         }
770         fn emit_u16(&mut self, v: u16) {
771             self.wr_tagged_u16(EsU16 as uint, v);
772         }
773         fn emit_u8(&mut self, v: u8) {
774             self.wr_tagged_u8(EsU8 as uint, v);
775         }
776
777         fn emit_int(&mut self, v: int) {
778             self.wr_tagged_i64(EsInt as uint, v as i64);
779         }
780         fn emit_i64(&mut self, v: i64) {
781             self.wr_tagged_i64(EsI64 as uint, v);
782         }
783         fn emit_i32(&mut self, v: i32) {
784             self.wr_tagged_i32(EsI32 as uint, v);
785         }
786         fn emit_i16(&mut self, v: i16) {
787             self.wr_tagged_i16(EsI16 as uint, v);
788         }
789         fn emit_i8(&mut self, v: i8) {
790             self.wr_tagged_i8(EsI8 as uint, v);
791         }
792
793         fn emit_bool(&mut self, v: bool) {
794             self.wr_tagged_u8(EsBool as uint, v as u8)
795         }
796
797         fn emit_f64(&mut self, v: f64) {
798             let bits = unsafe { cast::transmute(v) };
799             self.wr_tagged_u64(EsF64 as uint, bits);
800         }
801         fn emit_f32(&mut self, v: f32) {
802             let bits = unsafe { cast::transmute(v) };
803             self.wr_tagged_u32(EsF32 as uint, bits);
804         }
805         fn emit_char(&mut self, v: char) {
806             self.wr_tagged_u32(EsChar as uint, v as u32);
807         }
808
809         fn emit_str(&mut self, v: &str) {
810             self.wr_tagged_str(EsStr as uint, v)
811         }
812
813         fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
814             self._emit_label(name);
815             self.start_tag(EsEnum as uint);
816             f(self);
817             self.end_tag();
818         }
819
820         fn emit_enum_variant(&mut self,
821                              _: &str,
822                              v_id: uint,
823                              _: uint,
824                              f: |&mut Encoder<'a>|) {
825             self._emit_tagged_uint(EsEnumVid, v_id);
826             self.start_tag(EsEnumBody as uint);
827             f(self);
828             self.end_tag();
829         }
830
831         fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
832             f(self)
833         }
834
835         fn emit_enum_struct_variant(&mut self,
836                                     v_name: &str,
837                                     v_id: uint,
838                                     cnt: uint,
839                                     f: |&mut Encoder<'a>|) {
840             self.emit_enum_variant(v_name, v_id, cnt, f)
841         }
842
843         fn emit_enum_struct_variant_field(&mut self,
844                                           _: &str,
845                                           idx: uint,
846                                           f: |&mut Encoder<'a>|) {
847             self.emit_enum_variant_arg(idx, f)
848         }
849
850         fn emit_struct(&mut self,
851                        _: &str,
852                        _len: uint,
853                        f: |&mut Encoder<'a>|) {
854             f(self)
855         }
856
857         fn emit_struct_field(&mut self,
858                              name: &str,
859                              _: uint,
860                              f: |&mut Encoder<'a>|) {
861             self._emit_label(name);
862             f(self)
863         }
864
865         fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
866             self.emit_seq(len, f)
867         }
868         fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
869             self.emit_seq_elt(idx, f)
870         }
871
872         fn emit_tuple_struct(&mut self,
873                              _: &str,
874                              len: uint,
875                              f: |&mut Encoder<'a>|) {
876             self.emit_seq(len, f)
877         }
878         fn emit_tuple_struct_arg(&mut self,
879                                  idx: uint,
880                                  f: |&mut Encoder<'a>|) {
881             self.emit_seq_elt(idx, f)
882         }
883
884         fn emit_option(&mut self, f: |&mut Encoder<'a>|) {
885             self.emit_enum("Option", f);
886         }
887         fn emit_option_none(&mut self) {
888             self.emit_enum_variant("None", 0, 0, |_| ())
889         }
890         fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) {
891             self.emit_enum_variant("Some", 1, 1, f)
892         }
893
894         fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) {
895             self.start_tag(EsVec as uint);
896             self._emit_tagged_uint(EsVecLen, len);
897             f(self);
898             self.end_tag();
899         }
900
901         fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
902             self.start_tag(EsVecElt as uint);
903             f(self);
904             self.end_tag();
905         }
906
907         fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) {
908             self.start_tag(EsMap as uint);
909             self._emit_tagged_uint(EsMapLen, len);
910             f(self);
911             self.end_tag();
912         }
913
914         fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
915             self.start_tag(EsMapKey as uint);
916             f(self);
917             self.end_tag();
918         }
919
920         fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
921             self.start_tag(EsMapVal as uint);
922             f(self);
923             self.end_tag();
924         }
925     }
926 }
927
928 // ___________________________________________________________________________
929 // Testing
930
931 #[cfg(test)]
932 mod tests {
933     use ebml::reader;
934     use ebml::writer;
935     use serialize::Encodable;
936     use serialize;
937
938     use std::io::MemWriter;
939     use std::option::{None, Option, Some};
940
941     #[test]
942     fn test_option_int() {
943         fn test_v(v: Option<int>) {
944             debug!("v == {:?}", v);
945             let mut wr = MemWriter::new();
946             {
947                 let mut ebml_w = writer::Encoder(&mut wr);
948                 v.encode(&mut ebml_w);
949             }
950             let ebml_doc = reader::Doc(wr.get_ref());
951             let mut deser = reader::Decoder(ebml_doc);
952             let v1 = serialize::Decodable::decode(&mut deser);
953             debug!("v1 == {:?}", v1);
954             assert_eq!(v, v1);
955         }
956
957         test_v(Some(22));
958         test_v(None);
959         test_v(Some(3));
960     }
961 }
962
963 #[cfg(test)]
964 mod bench {
965     use ebml::reader;
966     use test::BenchHarness;
967
968     #[bench]
969     pub fn vuint_at_A_aligned(bh: &mut BenchHarness) {
970         use std::vec;
971         let data = vec::from_fn(4*100, |i| {
972             match (i % 2) {
973               0 => 0x80u8,
974               _ => i as u8,
975             }
976         });
977         let mut sum = 0u;
978         bh.iter(|| {
979             let mut i = 0;
980             while (i < data.len()) {
981                 sum += reader::vuint_at(data, i).val;
982                 i += 4;
983             }
984         });
985     }
986
987     #[bench]
988     pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) {
989         use std::vec;
990         let data = vec::from_fn(4*100+1, |i| {
991             match (i % 2) {
992               1 => 0x80u8,
993               _ => i as u8
994             }
995         });
996         let mut sum = 0u;
997         bh.iter(|| {
998             let mut i = 1;
999             while (i < data.len()) {
1000                 sum += reader::vuint_at(data, i).val;
1001                 i += 4;
1002             }
1003         });
1004     }
1005
1006     #[bench]
1007     pub fn vuint_at_D_aligned(bh: &mut BenchHarness) {
1008         use std::vec;
1009         let data = vec::from_fn(4*100, |i| {
1010             match (i % 4) {
1011               0 => 0x10u8,
1012               3 => i as u8,
1013               _ => 0u8
1014             }
1015         });
1016         let mut sum = 0u;
1017         bh.iter(|| {
1018             let mut i = 0;
1019             while (i < data.len()) {
1020                 sum += reader::vuint_at(data, i).val;
1021                 i += 4;
1022             }
1023         });
1024     }
1025
1026     #[bench]
1027     pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) {
1028         use std::vec;
1029         let data = vec::from_fn(4*100+1, |i| {
1030             match (i % 4) {
1031               1 => 0x10u8,
1032               0 => i as u8,
1033               _ => 0u8
1034             }
1035         });
1036         let mut sum = 0u;
1037         bh.iter(|| {
1038             let mut i = 1;
1039             while (i < data.len()) {
1040                 sum += reader::vuint_at(data, i).val;
1041                 i += 4;
1042             }
1043         });
1044     }
1045 }