diff options
| author | Jeff Olson <olson.jeffery@gmail.com> | 2014-02-05 08:52:54 -0800 |
|---|---|---|
| committer | Jeff Olson <olson.jeffery@gmail.com> | 2014-02-05 10:38:22 -0800 |
| commit | b8852e89ced0a0cdf66963aba08382ff18fd2d4b (patch) | |
| tree | 436f978485e7ceb1fc7daa36ab999afcdea30193 /src/libserialize | |
| parent | 2bf575c86fd3c053df83b90862441fec71c7a622 (diff) | |
| download | rust-b8852e89ced0a0cdf66963aba08382ff18fd2d4b.tar.gz rust-b8852e89ced0a0cdf66963aba08382ff18fd2d4b.zip | |
pull extra::{serialize, ebml} into a separate libserialize crate
- `extra::json` didn't make the cut, because of `extra::json` required dep on `extra::TreeMap`. If/when `extra::TreeMap` moves out of `extra`, then `extra::json` could move into `serialize` - `libextra`, `libsyntax` and `librustc` depend on the newly created `libserialize` - The extensions to various `extra` types like `DList`, `RingBuf`, `TreeMap` and `TreeSet` for `Encodable`/`Decodable` were moved into the respective modules in `extra` - There is some trickery, evident in `src/libextra/lib.rs` where a stub of `extra::serialize` is set up (in `src/libextra/serialize.rs`) for use in the stage0 build, where the snapshot rustc is still making deriving for `Encodable` and `Decodable` point at extra. Big props to @huonw for help working out the re-export solution for this extra: inline extra::serialize stub fix stuff clobbered in rebase + don't reexport serialize::serialize no more globs in libserialize syntax: fix import of libserialize traits librustc: fix bad imports in encoder/decoder add serialize dep to librustdoc fix failing run-pass tests w/ serialize dep adjust uuid dep more rebase de-clobbering for libserialize fixing tests, pushing libextra dep into cfg(test) fix doc code in extra::json adjust index.md links to serialize and uuid library
Diffstat (limited to 'src/libserialize')
| -rw-r--r-- | src/libserialize/ebml.rs | 1121 | ||||
| -rw-r--r-- | src/libserialize/lib.rs | 33 | ||||
| -rw-r--r-- | src/libserialize/serialize.rs | 760 |
3 files changed, 1914 insertions, 0 deletions
diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs new file mode 100644 index 00000000000..9d1c099c6f0 --- /dev/null +++ b/src/libserialize/ebml.rs @@ -0,0 +1,1121 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(missing_doc)]; + +use std::str; + +macro_rules! if_ok( ($e:expr) => ( + match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } } +) ) + +// Simple Extensible Binary Markup Language (ebml) reader and writer on a +// cursor model. See the specification here: +// http://www.matroska.org/technical/specs/rfc/index.html + +// Common data structures +#[deriving(Clone)] +pub struct Doc<'a> { + data: &'a [u8], + start: uint, + end: uint, +} + +impl<'doc> Doc<'doc> { + pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> { + reader::get_doc(*self, tag) + } + + pub fn as_str_slice<'a>(&'a self) -> &'a str { + str::from_utf8(self.data.slice(self.start, self.end)).unwrap() + } + + pub fn as_str(&self) -> ~str { + self.as_str_slice().to_owned() + } +} + +pub struct TaggedDoc<'a> { + priv tag: uint, + doc: Doc<'a>, +} + +pub enum EbmlEncoderTag { + EsUint, // 0 + EsU64, // 1 + EsU32, // 2 + EsU16, // 3 + EsU8, // 4 + EsInt, // 5 + EsI64, // 6 + EsI32, // 7 + EsI16, // 8 + EsI8, // 9 + EsBool, // 10 + EsChar, // 11 + EsStr, // 12 + EsF64, // 13 + EsF32, // 14 + EsFloat, // 15 + EsEnum, // 16 + EsEnumVid, // 17 + EsEnumBody, // 18 + EsVec, // 19 + EsVecLen, // 20 + EsVecElt, // 21 + EsMap, // 22 + EsMapLen, // 23 + EsMapKey, // 24 + EsMapVal, // 25 + + EsOpaque, + + EsLabel, // Used only when debugging +} +// -------------------------------------- + +pub mod reader { + use std::char; + + use std::cast::transmute; + use std::int; + use std::option::{None, Option, Some}; + use std::io::extensions::u64_from_be_bytes; + + use serialize; + + use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, + EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, + EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, + EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc }; + + // ebml reading + + pub struct Res { + val: uint, + next: uint + } + + #[inline(never)] + fn vuint_at_slow(data: &[u8], start: uint) -> Res { + let a = data[start]; + if a & 0x80u8 != 0u8 { + return Res {val: (a & 0x7fu8) as uint, next: start + 1u}; + } + if a & 0x40u8 != 0u8 { + return Res {val: ((a & 0x3fu8) as uint) << 8u | + (data[start + 1u] as uint), + next: start + 2u}; + } + if a & 0x20u8 != 0u8 { + return Res {val: ((a & 0x1fu8) as uint) << 16u | + (data[start + 1u] as uint) << 8u | + (data[start + 2u] as uint), + next: start + 3u}; + } + if a & 0x10u8 != 0u8 { + return Res {val: ((a & 0x0fu8) as uint) << 24u | + (data[start + 1u] as uint) << 16u | + (data[start + 2u] as uint) << 8u | + (data[start + 3u] as uint), + next: start + 4u}; + } + fail!("vint too big"); + } + + pub fn vuint_at(data: &[u8], start: uint) -> Res { + use std::ptr::offset; + use std::unstable::intrinsics::from_be32; + + if data.len() - start < 4 { + return vuint_at_slow(data, start); + } + + // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/ + // The Element IDs are parsed by reading a big endian u32 positioned at data[start]. + // Using the four most significant bits of the u32 we lookup in the table below how the + // element ID should be derived from it. + // + // The table stores tuples (shift, mask) where shift is the number the u32 should be right + // shifted with and mask is the value the right shifted value should be masked with. + // If for example the most significant bit is set this means it's a class A ID and the u32 + // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at + // index 0x8 - 0xF (four bit numbers where the most significant bit is set). + // + // By storing the number of shifts and masks in a table instead of checking in order if + // the most significant bit is set, the second most significant bit is set etc. we can + // replace up to three "and+branch" with a single table lookup which gives us a measured + // speedup of around 2x on x86_64. + static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [ + (0, 0x0), (0, 0x0fffffff), + (8, 0x1fffff), (8, 0x1fffff), + (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), + (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f), + (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f) + ]; + + unsafe { + let (ptr, _): (*u8, uint) = transmute(data); + let ptr = offset(ptr, start as int); + let ptr: *i32 = transmute(ptr); + let val = from_be32(*ptr) as u32; + + let i = (val >> 28u) as uint; + let (shift, mask) = SHIFT_MASK_TABLE[i]; + Res { + val: ((val >> shift) & mask) as uint, + next: start + (((32 - shift) >> 3) as uint) + } + } + } + + pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> { + Doc { data: data, start: 0u, end: data.len() } + } + + pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> { + let elt_tag = vuint_at(data, start); + let elt_size = vuint_at(data, elt_tag.next); + let end = elt_size.next + elt_size.val; + TaggedDoc { + tag: elt_tag.val, + doc: Doc { data: data, start: elt_size.next, end: end } + } + } + + pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> { + let mut pos = d.start; + while pos < d.end { + let elt_tag = vuint_at(d.data, pos); + let elt_size = vuint_at(d.data, elt_tag.next); + pos = elt_size.next + elt_size.val; + if elt_tag.val == tg { + return Some(Doc { data: d.data, start: elt_size.next, + end: pos }); + } + } + None + } + + pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> { + match maybe_get_doc(d, tg) { + Some(d) => d, + None => { + error!("failed to find block with tag {}", tg); + fail!(); + } + } + } + + pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool { + let mut pos = d.start; + while pos < d.end { + let elt_tag = vuint_at(d.data, pos); + let elt_size = vuint_at(d.data, elt_tag.next); + pos = elt_size.next + elt_size.val; + let doc = Doc { data: d.data, start: elt_size.next, end: pos }; + if !it(elt_tag.val, doc) { + return false; + } + } + return true; + } + + pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool { + let mut pos = d.start; + while pos < d.end { + let elt_tag = vuint_at(d.data, pos); + let elt_size = vuint_at(d.data, elt_tag.next); + pos = elt_size.next + elt_size.val; + if elt_tag.val == tg { + let doc = Doc { data: d.data, start: elt_size.next, + end: pos }; + if !it(doc) { + return false; + } + } + } + return true; + } + + pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T { + f(d.data.slice(d.start, d.end)) + } + + + pub fn doc_as_u8(d: Doc) -> u8 { + assert_eq!(d.end, d.start + 1u); + d.data[d.start] + } + + pub fn doc_as_u16(d: Doc) -> u16 { + assert_eq!(d.end, d.start + 2u); + u64_from_be_bytes(d.data, d.start, 2u) as u16 + } + + pub fn doc_as_u32(d: Doc) -> u32 { + assert_eq!(d.end, d.start + 4u); + u64_from_be_bytes(d.data, d.start, 4u) as u32 + } + + pub fn doc_as_u64(d: Doc) -> u64 { + assert_eq!(d.end, d.start + 8u); + u64_from_be_bytes(d.data, d.start, 8u) + } + + pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } + pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 } + pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 } + pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } + + pub struct Decoder<'a> { + priv parent: Doc<'a>, + priv pos: uint, + } + + pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> { + Decoder { + parent: d, + pos: d.start + } + } + + impl<'doc> Decoder<'doc> { + fn _check_label(&mut self, lbl: &str) { + if self.pos < self.parent.end { + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); + + if r_tag == (EsLabel as uint) { + self.pos = r_doc.end; + let str = r_doc.as_str_slice(); + if lbl != str { + fail!("Expected label {} but found {}", lbl, str); + } + } + } + } + + fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> { + debug!(". next_doc(exp_tag={:?})", exp_tag); + if self.pos >= self.parent.end { + fail!("no more documents in current node!"); + } + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); + debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}", + self.parent.start, + self.parent.end, + self.pos, + r_tag, + r_doc.start, + r_doc.end); + if r_tag != (exp_tag as uint) { + fail!("expected EBML doc with tag {:?} but found tag {:?}", + exp_tag, r_tag); + } + if r_doc.end > self.parent.end { + fail!("invalid EBML, child extends to {:#x}, parent to {:#x}", + r_doc.end, self.parent.end); + } + self.pos = r_doc.end; + r_doc + } + + fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag, + f: |&mut Decoder<'doc>| -> T) -> T { + let d = self.next_doc(exp_tag); + let old_parent = self.parent; + let old_pos = self.pos; + self.parent = d; + self.pos = d.start; + let r = f(self); + self.parent = old_parent; + self.pos = old_pos; + r + } + + fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint { + let r = doc_as_u32(self.next_doc(exp_tag)); + debug!("_next_uint exp_tag={:?} result={}", exp_tag, r); + r as uint + } + + pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R { + let doc = self.next_doc(EsOpaque); + + let (old_parent, old_pos) = (self.parent, self.pos); + self.parent = doc; + self.pos = doc.start; + + let result = op(self, doc); + + self.parent = old_parent; + self.pos = old_pos; + result + } + } + + impl<'doc> serialize::Decoder for Decoder<'doc> { + fn read_nil(&mut self) -> () { () } + + fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) } + fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) } + fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) } + fn read_u8 (&mut self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) } + fn read_uint(&mut self) -> uint { + let v = doc_as_u64(self.next_doc(EsUint)); + if v > (::std::uint::MAX as u64) { + fail!("uint {} too large for this architecture", v); + } + v as uint + } + + fn read_i64(&mut self) -> i64 { + doc_as_u64(self.next_doc(EsI64)) as i64 + } + fn read_i32(&mut self) -> i32 { + doc_as_u32(self.next_doc(EsI32)) as i32 + } + fn read_i16(&mut self) -> i16 { + doc_as_u16(self.next_doc(EsI16)) as i16 + } + fn read_i8 (&mut self) -> i8 { + doc_as_u8(self.next_doc(EsI8 )) as i8 + } + fn read_int(&mut self) -> int { + let v = doc_as_u64(self.next_doc(EsInt)) as i64; + if v > (int::MAX as i64) || v < (int::MIN as i64) { + debug!("FIXME \\#6122: Removing this makes this function miscompile"); + fail!("int {} out of range for this architecture", v); + } + v as int + } + + fn read_bool(&mut self) -> bool { + doc_as_u8(self.next_doc(EsBool)) != 0 + } + + fn read_f64(&mut self) -> f64 { + let bits = doc_as_u64(self.next_doc(EsF64)); + unsafe { transmute(bits) } + } + fn read_f32(&mut self) -> f32 { + let bits = doc_as_u32(self.next_doc(EsF32)); + unsafe { transmute(bits) } + } + fn read_char(&mut self) -> char { + char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap() + } + fn read_str(&mut self) -> ~str { + self.next_doc(EsStr).as_str() + } + + // Compound types: + fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T { + debug!("read_enum({})", name); + self._check_label(name); + + let doc = self.next_doc(EsEnum); + + let (old_parent, old_pos) = (self.parent, self.pos); + self.parent = doc; + self.pos = self.parent.start; + + let result = f(self); + + self.parent = old_parent; + self.pos = old_pos; + result + } + + fn read_enum_variant<T>(&mut self, + _: &[&str], + f: |&mut Decoder<'doc>, uint| -> T) + -> T { + debug!("read_enum_variant()"); + let idx = self._next_uint(EsEnumVid); + debug!(" idx={}", idx); + + let doc = self.next_doc(EsEnumBody); + + let (old_parent, old_pos) = (self.parent, self.pos); + self.parent = doc; + self.pos = self.parent.start; + + let result = f(self, idx); + + self.parent = old_parent; + self.pos = old_pos; + result + } + + fn read_enum_variant_arg<T>(&mut self, + idx: uint, + f: |&mut Decoder<'doc>| -> T) -> T { + debug!("read_enum_variant_arg(idx={})", idx); + f(self) + } + + fn read_enum_struct_variant<T>(&mut self, + _: &[&str], + f: |&mut Decoder<'doc>, uint| -> T) + -> T { + debug!("read_enum_struct_variant()"); + let idx = self._next_uint(EsEnumVid); + debug!(" idx={}", idx); + + let doc = self.next_doc(EsEnumBody); + + let (old_parent, old_pos) = (self.parent, self.pos); + self.parent = doc; + self.pos = self.parent.start; + + let result = f(self, idx); + + self.parent = old_parent; + self.pos = old_pos; + result + } + + fn read_enum_struct_variant_field<T>(&mut self, + name: &str, + idx: uint, + f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); + f(self) + } + + fn read_struct<T>(&mut self, + name: &str, + _: uint, + f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_struct(name={})", name); + f(self) + } + + fn read_struct_field<T>(&mut self, + name: &str, + idx: uint, + f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_struct_field(name={}, idx={})", name, idx); + self._check_label(name); + f(self) + } + + fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + debug!("read_tuple()"); + self.read_seq(f) + } + + fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_tuple_arg(idx={})", idx); + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct<T>(&mut self, + name: &str, + f: |&mut Decoder<'doc>, uint| -> T) + -> T { + debug!("read_tuple_struct(name={})", name); + self.read_tuple(f) + } + + fn read_tuple_struct_arg<T>(&mut self, + idx: uint, + f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_tuple_struct_arg(idx={})", idx); + self.read_tuple_arg(idx, f) + } + + fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T { + debug!("read_option()"); + self.read_enum("Option", |this| { + this.read_enum_variant(["None", "Some"], |this, idx| { + match idx { + 0 => f(this, false), + 1 => f(this, true), + _ => fail!(), + } + }) + }) + } + + fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + debug!("read_seq()"); + self.push_doc(EsVec, |d| { + let len = d._next_uint(EsVecLen); + debug!(" len={}", len); + f(d, len) + }) + } + + fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_seq_elt(idx={})", idx); + self.push_doc(EsVecElt, f) + } + + fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + debug!("read_map()"); + self.push_doc(EsMap, |d| { + let len = d._next_uint(EsMapLen); + debug!(" len={}", len); + f(d, len) + }) + } + + fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_map_elt_key(idx={})", idx); + self.push_doc(EsMapKey, f) + } + + fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_map_elt_val(idx={})", idx); + self.push_doc(EsMapVal, f) + } + } +} + +pub mod writer { + use std::cast; + use std::clone::Clone; + use std::io; + use std::io::{Writer, Seek}; + use std::io::MemWriter; + use std::io::extensions::u64_to_be_bytes; + + use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, + EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, + EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, + EsOpaque, EsLabel, EbmlEncoderTag }; + + use serialize; + + // ebml writing + pub struct Encoder<'a> { + // FIXME(#5665): this should take a trait object. Note that if you + // delete this comment you should consider removing the + // unwrap()'s below of the results of the calls to + // write(). We're guaranteed that writing into a MemWriter + // won't fail, but this is not true for all I/O streams in + // general. + writer: &'a mut MemWriter, + priv size_positions: ~[uint], + last_error: io::IoResult<()>, + } + + fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) { + match size { + 1u => w.write(&[0x80u8 | (n as u8)]), + 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), + 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8, + n as u8]), + 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8, + (n >> 8_u) as u8, n as u8]), + _ => fail!("vint to write too big: {}", n) + }.unwrap() + } + + fn write_vuint(w: &mut MemWriter, n: uint) { + if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; } + if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; } + if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; } + if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; } + fail!("vint to write too big: {}", n); + } + + pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> { + let size_positions: ~[uint] = ~[]; + Encoder { + writer: w, + size_positions: size_positions, + last_error: Ok(()), + } + } + + // FIXME (#2741): Provide a function to write the standard ebml header. + impl<'a> Encoder<'a> { + /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME. + pub unsafe fn unsafe_clone(&self) -> Encoder<'a> { + Encoder { + writer: cast::transmute_copy(&self.writer), + size_positions: self.size_positions.clone(), + last_error: Ok(()), + } + } + + pub fn start_tag(&mut self, tag_id: uint) { + debug!("Start tag {}", tag_id); + + // Write the enum ID: + write_vuint(self.writer, tag_id); + + // Write a placeholder four-byte size. + self.size_positions.push(if_ok!(self.writer.tell()) as uint); + let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8]; + if_ok!(self.writer.write(zeroes)); + } + + pub fn end_tag(&mut self) { + let last_size_pos = self.size_positions.pop().unwrap(); + let cur_pos = if_ok!(self.writer.tell()); + if_ok!(self.writer.seek(last_size_pos as i64, io::SeekSet)); + let size = (cur_pos as uint - last_size_pos - 4); + write_sized_vuint(self.writer, size, 4u); + if_ok!(self.writer.seek(cur_pos as i64, io::SeekSet)); + + debug!("End tag (size = {})", size); + } + + pub fn wr_tag(&mut self, tag_id: uint, blk: ||) { + self.start_tag(tag_id); + blk(); + self.end_tag(); + } + + pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) { + write_vuint(self.writer, tag_id); + write_vuint(self.writer, b.len()); + self.writer.write(b).unwrap(); + } + + pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) { + u64_to_be_bytes(v, 8u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) { + u64_to_be_bytes(v as u64, 4u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) { + u64_to_be_bytes(v as u64, 2u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) { + self.wr_tagged_bytes(tag_id, &[v]); + } + + pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) { + u64_to_be_bytes(v as u64, 8u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) { + u64_to_be_bytes(v as u64, 4u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) { + u64_to_be_bytes(v as u64, 2u, |v| { + self.wr_tagged_bytes(tag_id, v); + }) + } + + pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) { + self.wr_tagged_bytes(tag_id, &[v as u8]); + } + + pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) { + self.wr_tagged_bytes(tag_id, v.as_bytes()); + } + + pub fn wr_bytes(&mut self, b: &[u8]) { + debug!("Write {} bytes", b.len()); + self.writer.write(b).unwrap(); + } + + pub fn wr_str(&mut self, s: &str) { + debug!("Write str: {}", s); + self.writer.write(s.as_bytes()).unwrap(); + } + } + + // FIXME (#2743): optionally perform "relaxations" on end_tag to more + // efficiently encode sizes; this is a fixed point iteration + + // Set to true to generate more debugging in EBML code. + // Totally lame approach. + static DEBUG: bool = true; + + impl<'a> Encoder<'a> { + // used internally to emit things like the vector length and so on + fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) { + assert!(v <= 0xFFFF_FFFF_u); + self.wr_tagged_u32(t as uint, v as u32); + } + + fn _emit_label(&mut self, label: &str) { + // There are various strings that we have access to, such as + // the name of a record field, which do not actually appear in + // the encoded EBML (normally). This is just for + // efficiency. When debugging, though, we can emit such + // labels and then they will be checked by decoder to + // try and check failures more quickly. + if DEBUG { self.wr_tagged_str(EsLabel as uint, label) } + } + + pub fn emit_opaque(&mut self, f: |&mut Encoder|) { + self.start_tag(EsOpaque as uint); + f(self); + self.end_tag(); + } + } + + impl<'a> serialize::Encoder for Encoder<'a> { + fn emit_nil(&mut self) {} + + fn emit_uint(&mut self, v: uint) { + self.wr_tagged_u64(EsUint as uint, v as u64); + } + fn emit_u64(&mut self, v: u64) { + self.wr_tagged_u64(EsU64 as uint, v); + } + fn emit_u32(&mut self, v: u32) { + self.wr_tagged_u32(EsU32 as uint, v); + } + fn emit_u16(&mut self, v: u16) { + self.wr_tagged_u16(EsU16 as uint, v); + } + fn emit_u8(&mut self, v: u8) { + self.wr_tagged_u8(EsU8 as uint, v); + } + + fn emit_int(&mut self, v: int) { + self.wr_tagged_i64(EsInt as uint, v as i64); + } + fn emit_i64(&mut self, v: i64) { + self.wr_tagged_i64(EsI64 as uint, v); + } + fn emit_i32(&mut self, v: i32) { + self.wr_tagged_i32(EsI32 as uint, v); + } + fn emit_i16(&mut self, v: i16) { + self.wr_tagged_i16(EsI16 as uint, v); + } + fn emit_i8(&mut self, v: i8) { + self.wr_tagged_i8(EsI8 as uint, v); + } + + fn emit_bool(&mut self, v: bool) { + self.wr_tagged_u8(EsBool as uint, v as u8) + } + + fn emit_f64(&mut self, v: f64) { + let bits = unsafe { cast::transmute(v) }; + self.wr_tagged_u64(EsF64 as uint, bits); + } + fn emit_f32(&mut self, v: f32) { + let bits = unsafe { cast::transmute(v) }; + self.wr_tagged_u32(EsF32 as uint, bits); + } + fn emit_char(&mut self, v: char) { + self.wr_tagged_u32(EsChar as uint, v as u32); + } + + fn emit_str(&mut self, v: &str) { + self.wr_tagged_str(EsStr as uint, v) + } + + fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) { + self._emit_label(name); + self.start_tag(EsEnum as uint); + f(self); + self.end_tag(); + } + + fn emit_enum_variant(&mut self, + _: &str, + v_id: uint, + _: uint, + f: |&mut Encoder<'a>|) { + self._emit_tagged_uint(EsEnumVid, v_id); + self.start_tag(EsEnumBody as uint); + f(self); + self.end_tag(); + } + + fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) { + f(self) + } + + fn emit_enum_struct_variant(&mut self, + v_name: &str, + v_id: uint, + cnt: uint, + f: |&mut Encoder<'a>|) { + self.emit_enum_variant(v_name, v_id, cnt, f) + } + + fn emit_enum_struct_variant_field(&mut self, + _: &str, + idx: uint, + f: |&mut Encoder<'a>|) { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&mut self, + _: &str, + _len: uint, + f: |&mut Encoder<'a>|) { + f(self) + } + + fn emit_struct_field(&mut self, + name: &str, + _: uint, + f: |&mut Encoder<'a>|) { + self._emit_label(name); + f(self) + } + + fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) { + self.emit_seq(len, f) + } + fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) { + self.emit_seq_elt(idx, f) + } + + fn emit_tuple_struct(&mut self, + _: &str, + len: uint, + f: |&mut Encoder<'a>|) { + self.emit_seq(len, f) + } + fn emit_tuple_struct_arg(&mut self, + idx: uint, + f: |&mut Encoder<'a>|) { + self.emit_seq_elt(idx, f) + } + + fn emit_option(&mut self, f: |&mut Encoder<'a>|) { + self.emit_enum("Option", f); + } + fn emit_option_none(&mut self) { + self.emit_enum_variant("None", 0, 0, |_| ()) + } + fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { + self.emit_enum_variant("Some", 1, 1, f) + } + + fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) { + self.start_tag(EsVec as uint); + self._emit_tagged_uint(EsVecLen, len); + f(self); + self.end_tag(); + } + + fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { + self.start_tag(EsVecElt as uint); + f(self); + self.end_tag(); + } + + fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) { + self.start_tag(EsMap as uint); + self._emit_tagged_uint(EsMapLen, len); + f(self); + self.end_tag(); + } + + fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { + self.start_tag(EsMapKey as uint); + f(self); + self.end_tag(); + } + + fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { + self.start_tag(EsMapVal as uint); + f(self); + self.end_tag(); + } + } +} + +// ___________________________________________________________________________ +// Testing + +#[cfg(test)] +mod tests { + use ebml::reader; + use ebml::writer; + use {Encodable, Decodable}; + + use std::io::MemWriter; + use std::option::{None, Option, Some}; + + #[test] + fn test_vuint_at() { + let data = [ + 0x80, + 0xff, + 0x40, 0x00, + 0x7f, 0xff, + 0x20, 0x00, 0x00, + 0x3f, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xff, 0xff + ]; + + let mut res: reader::Res; + + // Class A + res = reader::vuint_at(data, 0); + assert_eq!(res.val, 0); + assert_eq!(res.next, 1); + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, (1 << 7) - 1); + assert_eq!(res.next, 2); + + // Class B + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, 0); + assert_eq!(res.next, 4); + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, (1 << 14) - 1); + assert_eq!(res.next, 6); + + // Class C + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, 0); + assert_eq!(res.next, 9); + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, (1 << 21) - 1); + assert_eq!(res.next, 12); + + // Class D + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, 0); + assert_eq!(res.next, 16); + res = reader::vuint_at(data, res.next); + assert_eq!(res.val, (1 << 28) - 1); + assert_eq!(res.next, 20); + } + + #[test] + fn test_option_int() { + fn test_v(v: Option<int>) { + debug!("v == {:?}", v); + let mut wr = MemWriter::new(); + { + let mut ebml_w = writer::Encoder(&mut wr); + v.encode(&mut ebml_w); + } + let ebml_doc = reader::Doc(wr.get_ref()); + let mut deser = reader::Decoder(ebml_doc); + let v1 = Decodable::decode(&mut deser); + debug!("v1 == {:?}", v1); + assert_eq!(v, v1); + } + + test_v(Some(22)); + test_v(None); + test_v(Some(3)); + } +} + +#[cfg(test)] +mod bench { + use ebml::reader; + use extra::test::BenchHarness; + + #[bench] + pub fn vuint_at_A_aligned(bh: &mut BenchHarness) { + use std::vec; + let data = vec::from_fn(4*100, |i| { + match i % 2 { + 0 => 0x80u8, + _ => i as u8, + } + }); + let mut sum = 0u; + bh.iter(|| { + let mut i = 0; + while i < data.len() { + sum += reader::vuint_at(data, i).val; + i += 4; + } + }); + } + + #[bench] + pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) { + use std::vec; + let data = vec::from_fn(4*100+1, |i| { + match i % 2 { + 1 => 0x80u8, + _ => i as u8 + } + }); + let mut sum = 0u; + bh.iter(|| { + let mut i = 1; + while i < data.len() { + sum += reader::vuint_at(data, i).val; + i += 4; + } + }); + } + + #[bench] + pub fn vuint_at_D_aligned(bh: &mut BenchHarness) { + use std::vec; + let data = vec::from_fn(4*100, |i| { + match i % 4 { + 0 => 0x10u8, + 3 => i as u8, + _ => 0u8 + } + }); + let mut sum = 0u; + bh.iter(|| { + let mut i = 0; + while i < data.len() { + sum += reader::vuint_at(data, i).val; + i += 4; + } + }); + } + + #[bench] + pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) { + use std::vec; + let data = vec::from_fn(4*100+1, |i| { + match i % 4 { + 1 => 0x10u8, + 0 => i as u8, + _ => 0u8 + } + }); + let mut sum = 0u; + bh.iter(|| { + let mut i = 1; + while i < data.len() { + sum += reader::vuint_at(data, i).val; + i += 4; + } + }); + } +} diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs new file mode 100644 index 00000000000..5f473b25369 --- /dev/null +++ b/src/libserialize/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Support code for encoding and decoding types. + +/* +Core encoding and decoding interfaces. +*/ + +#[crate_id = "serialize#0.10-pre"]; +#[crate_type = "rlib"]; +#[crate_type = "dylib"]; +#[license = "MIT/ASL2"]; +#[allow(missing_doc)]; +#[forbid(non_camel_case_types)]; +#[feature(macro_rules,managed_boxes)]; + +// test harness access +#[cfg(test)] +extern mod extra; + +pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, + DecoderHelpers, EncoderHelpers}; + +mod serialize; +pub mod ebml; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs new file mode 100644 index 00000000000..c4f0a7a1830 --- /dev/null +++ b/src/libserialize/serialize.rs @@ -0,0 +1,760 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Support code for encoding and decoding types. + +/* +Core encoding and decoding interfaces. +*/ + +use std::hashmap::{HashMap, HashSet}; +use std::rc::Rc; +use std::trie::{TrieMap, TrieSet}; +use std::vec; + +pub trait Encoder { + // Primitive types: + fn emit_nil(&mut self); + fn emit_uint(&mut self, v: uint); + fn emit_u64(&mut self, v: u64); + fn emit_u32(&mut self, v: u32); + fn emit_u16(&mut self, v: u16); + fn emit_u8(&mut self, v: u8); + fn emit_int(&mut self, v: int); + fn emit_i64(&mut self, v: i64); + fn emit_i32(&mut self, v: i32); + fn emit_i16(&mut self, v: i16); + fn emit_i8(&mut self, v: i8); + fn emit_bool(&mut self, v: bool); + fn emit_f64(&mut self, v: f64); + fn emit_f32(&mut self, v: f32); + fn emit_char(&mut self, v: char); + fn emit_str(&mut self, v: &str); + + // Compound types: + fn emit_enum(&mut self, name: &str, f: |&mut Self|); + + fn emit_enum_variant(&mut self, + v_name: &str, + v_id: uint, + len: uint, + f: |&mut Self|); + fn emit_enum_variant_arg(&mut self, a_idx: uint, f: |&mut Self|); + + fn emit_enum_struct_variant(&mut self, + v_name: &str, + v_id: uint, + len: uint, + f: |&mut Self|); + fn emit_enum_struct_variant_field(&mut self, + f_name: &str, + f_idx: uint, + f: |&mut Self|); + + fn emit_struct(&mut self, name: &str, len: uint, f: |&mut Self|); + fn emit_struct_field(&mut self, + f_name: &str, + f_idx: uint, + f: |&mut Self|); + + fn emit_tuple(&mut self, len: uint, f: |&mut Self|); + fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self|); + + fn emit_tuple_struct(&mut self, name: &str, len: uint, f: |&mut Self|); + fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: |&mut Self|); + + // Specialized types: + fn emit_option(&mut self, f: |&mut Self|); + fn emit_option_none(&mut self); + fn emit_option_some(&mut self, f: |&mut Self|); + + fn emit_seq(&mut self, len: uint, f: |this: &mut Self|); + fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self|); + + fn emit_map(&mut self, len: uint, f: |&mut Self|); + fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self|); + fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self|); +} + +pub trait Decoder { + // Primitive types: + fn read_nil(&mut self) -> (); + fn read_uint(&mut self) -> uint; + fn read_u64(&mut self) -> u64; + fn read_u32(&mut self) -> u32; + fn read_u16(&mut self) -> u16; + fn read_u8(&mut self) -> u8; + fn read_int(&mut self) -> int; + fn read_i64(&mut self) -> i64; + fn read_i32(&mut self) -> i32; + fn read_i16(&mut self) -> i16; + fn read_i8(&mut self) -> i8; + fn read_bool(&mut self) -> bool; + fn read_f64(&mut self) -> f64; + fn read_f32(&mut self) -> f32; + fn read_char(&mut self) -> char; + fn read_str(&mut self) -> ~str; + + // Compound types: + fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> T) -> T; + + fn read_enum_variant<T>(&mut self, + names: &[&str], + f: |&mut Self, uint| -> T) + -> T; + fn read_enum_variant_arg<T>(&mut self, + a_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_enum_struct_variant<T>(&mut self, + names: &[&str], + f: |&mut Self, uint| -> T) + -> T; + fn read_enum_struct_variant_field<T>(&mut self, + &f_name: &str, + f_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T) + -> T; + fn read_struct_field<T>(&mut self, + f_name: &str, + f_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T; + + fn read_tuple_struct<T>(&mut self, + s_name: &str, + f: |&mut Self, uint| -> T) + -> T; + fn read_tuple_struct_arg<T>(&mut self, + a_idx: uint, + f: |&mut Self| -> T) + -> T; + + // Specialized types: + fn read_option<T>(&mut self, f: |&mut Self, bool| -> T) -> T; + + fn read_seq<T>(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + + fn read_map<T>(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T; +} + +pub trait Encodable<S:Encoder> { + fn encode(&self, s: &mut S); +} + +pub trait Decodable<D:Decoder> { + fn decode(d: &mut D) -> Self; +} + +impl<S:Encoder> Encodable<S> for uint { + fn encode(&self, s: &mut S) { + s.emit_uint(*self) + } +} + +impl<D:Decoder> Decodable<D> for uint { + fn decode(d: &mut D) -> uint { + d.read_uint() + } +} + +impl<S:Encoder> Encodable<S> for u8 { + fn encode(&self, s: &mut S) { + s.emit_u8(*self) + } +} + +impl<D:Decoder> Decodable<D> for u8 { + fn decode(d: &mut D) -> u8 { + d.read_u8() + } +} + +impl<S:Encoder> Encodable<S> for u16 { + fn encode(&self, s: &mut S) { + s.emit_u16(*self) + } +} + +impl<D:Decoder> Decodable<D> for u16 { + fn decode(d: &mut D) -> u16 { + d.read_u16() + } +} + +impl<S:Encoder> Encodable<S> for u32 { + fn encode(&self, s: &mut S) { + s.emit_u32(*self) + } +} + +impl<D:Decoder> Decodable<D> for u32 { + fn decode(d: &mut D) -> u32 { + d.read_u32() + } +} + +impl<S:Encoder> Encodable<S> for u64 { + fn encode(&self, s: &mut S) { + s.emit_u64(*self) + } +} + +impl<D:Decoder> Decodable<D> for u64 { + fn decode(d: &mut D) -> u64 { + d.read_u64() + } +} + +impl<S:Encoder> Encodable<S> for int { + fn encode(&self, s: &mut S) { + s.emit_int(*self) + } +} + +impl<D:Decoder> Decodable<D> for int { + fn decode(d: &mut D) -> int { + d.read_int() + } +} + +impl<S:Encoder> Encodable<S> for i8 { + fn encode(&self, s: &mut S) { + s.emit_i8(*self) + } +} + +impl<D:Decoder> Decodable<D> for i8 { + fn decode(d: &mut D) -> i8 { + d.read_i8() + } +} + +impl<S:Encoder> Encodable<S> for i16 { + fn encode(&self, s: &mut S) { + s.emit_i16(*self) + } +} + +impl<D:Decoder> Decodable<D> for i16 { + fn decode(d: &mut D) -> i16 { + d.read_i16() + } +} + +impl<S:Encoder> Encodable<S> for i32 { + fn encode(&self, s: &mut S) { + s.emit_i32(*self) + } +} + +impl<D:Decoder> Decodable<D> for i32 { + fn decode(d: &mut D) -> i32 { + d.read_i32() + } +} + +impl<S:Encoder> Encodable<S> for i64 { + fn encode(&self, s: &mut S) { + s.emit_i64(*self) + } +} + +impl<D:Decoder> Decodable<D> for i64 { + fn decode(d: &mut D) -> i64 { + d.read_i64() + } +} + +impl<'a, S:Encoder> Encodable<S> for &'a str { + fn encode(&self, s: &mut S) { + s.emit_str(*self) + } +} + +impl<S:Encoder> Encodable<S> for ~str { + fn encode(&self, s: &mut S) { + s.emit_str(*self) + } +} + +impl<D:Decoder> Decodable<D> for ~str { + fn decode(d: &mut D) -> ~str { + d.read_str() + } +} + +impl<S:Encoder> Encodable<S> for f32 { + fn encode(&self, s: &mut S) { + s.emit_f32(*self) + } +} + +impl<D:Decoder> Decodable<D> for f32 { + fn decode(d: &mut D) -> f32 { + d.read_f32() + } +} + +impl<S:Encoder> Encodable<S> for f64 { + fn encode(&self, s: &mut S) { + s.emit_f64(*self) + } +} + +impl<D:Decoder> Decodable<D> for f64 { + fn decode(d: &mut D) -> f64 { + d.read_f64() + } +} + +impl<S:Encoder> Encodable<S> for bool { + fn encode(&self, s: &mut S) { + s.emit_bool(*self) + } +} + +impl<D:Decoder> Decodable<D> for bool { + fn decode(d: &mut D) -> bool { + d.read_bool() + } +} + +impl<S:Encoder> Encodable<S> for char { + fn encode(&self, s: &mut S) { + s.emit_char(*self) + } +} + +impl<D:Decoder> Decodable<D> for char { + fn decode(d: &mut D) -> char { + d.read_char() + } +} + +impl<S:Encoder> Encodable<S> for () { + fn encode(&self, s: &mut S) { + s.emit_nil() + } +} + +impl<D:Decoder> Decodable<D> for () { + fn decode(d: &mut D) -> () { + d.read_nil() + } +} + +impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T { + fn decode(d: &mut D) -> ~T { + ~Decodable::decode(d) + } +} + +impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> { + #[inline] + fn encode(&self, s: &mut S) { + self.borrow().encode(s) + } +} + +impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> { + #[inline] + fn decode(d: &mut D) -> Rc<T> { + Rc::new(Decodable::decode(d)) + } +} + +impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T { + fn decode(d: &mut D) -> @T { + @Decodable::decode(d) + } +} + +impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + s.emit_seq_elt(i, |s| e.encode(s)) + } + }) + } +} + +impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + s.emit_seq_elt(i, |s| e.encode(s)) + } + }) + } +} + +impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] { + fn decode(d: &mut D) -> ~[T] { + d.read_seq(|d, len| { + vec::from_fn(len, |i| { + d.read_seq_elt(i, |d| Decodable::decode(d)) + }) + }) + } +} + +impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> { + fn encode(&self, s: &mut S) { + s.emit_option(|s| { + match *self { + None => s.emit_option_none(), + Some(ref v) => s.emit_option_some(|s| v.encode(s)), + } + }) + } +} + +impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> { + fn decode(d: &mut D) -> Option<T> { + d.read_option(|d, b| { + if b { + Some(Decodable::decode(d)) + } else { + None + } + }) + } +} + +impl<S:Encoder,T0:Encodable<S>,T1:Encodable<S>> Encodable<S> for (T0, T1) { + fn encode(&self, s: &mut S) { + match *self { + (ref t0, ref t1) => { + s.emit_seq(2, |s| { + s.emit_seq_elt(0, |s| t0.encode(s)); + s.emit_seq_elt(1, |s| t1.encode(s)); + }) + } + } + } +} + +impl<D:Decoder,T0:Decodable<D>,T1:Decodable<D>> Decodable<D> for (T0, T1) { + fn decode(d: &mut D) -> (T0, T1) { + d.read_seq(|d, len| { + assert_eq!(len, 2); + ( + d.read_seq_elt(0, |d| Decodable::decode(d)), + d.read_seq_elt(1, |d| Decodable::decode(d)) + ) + }) + } +} + +impl< + S: Encoder, + T0: Encodable<S>, + T1: Encodable<S>, + T2: Encodable<S> +> Encodable<S> for (T0, T1, T2) { + fn encode(&self, s: &mut S) { + match *self { + (ref t0, ref t1, ref t2) => { + s.emit_seq(3, |s| { + s.emit_seq_elt(0, |s| t0.encode(s)); + s.emit_seq_elt(1, |s| t1.encode(s)); + s.emit_seq_elt(2, |s| t2.encode(s)); + }) + } + } + } +} + +impl< + D: Decoder, + T0: Decodable<D>, + T1: Decodable<D>, + T2: Decodable<D> +> Decodable<D> for (T0, T1, T2) { + fn decode(d: &mut D) -> (T0, T1, T2) { + d.read_seq(|d, len| { + assert_eq!(len, 3); + ( + d.read_seq_elt(0, |d| Decodable::decode(d)), + d.read_seq_elt(1, |d| Decodable::decode(d)), + d.read_seq_elt(2, |d| Decodable::decode(d)) + ) + }) + } +} + +impl< + S: Encoder, + T0: Encodable<S>, + T1: Encodable<S>, + T2: Encodable<S>, + T3: Encodable<S> +> Encodable<S> for (T0, T1, T2, T3) { + fn encode(&self, s: &mut S) { + match *self { + (ref t0, ref t1, ref t2, ref t3) => { + s.emit_seq(4, |s| { + s.emit_seq_elt(0, |s| t0.encode(s)); + s.emit_seq_elt(1, |s| t1.encode(s)); + s.emit_seq_elt(2, |s| t2.encode(s)); + s.emit_seq_elt(3, |s| t3.encode(s)); + }) + } + } + } +} + +impl< + D: Decoder, + T0: Decodable<D>, + T1: Decodable<D>, + T2: Decodable<D>, + T3: Decodable<D> +> Decodable<D> for (T0, T1, T2, T3) { + fn decode(d: &mut D) -> (T0, T1, T2, T3) { + d.read_seq(|d, len| { + assert_eq!(len, 4); + ( + d.read_seq_elt(0, |d| Decodable::decode(d)), + d.read_seq_elt(1, |d| Decodable::decode(d)), + d.read_seq_elt(2, |d| Decodable::decode(d)), + d.read_seq_elt(3, |d| Decodable::decode(d)) + ) + }) + } +} + +impl< + S: Encoder, + T0: Encodable<S>, + T1: Encodable<S>, + T2: Encodable<S>, + T3: Encodable<S>, + T4: Encodable<S> +> Encodable<S> for (T0, T1, T2, T3, T4) { + fn encode(&self, s: &mut S) { + match *self { + (ref t0, ref t1, ref t2, ref t3, ref t4) => { + s.emit_seq(5, |s| { + s.emit_seq_elt(0, |s| t0.encode(s)); + s.emit_seq_elt(1, |s| t1.encode(s)); + s.emit_seq_elt(2, |s| t2.encode(s)); + s.emit_seq_elt(3, |s| t3.encode(s)); + s.emit_seq_elt(4, |s| t4.encode(s)); + }) + } + } + } +} + +impl< + D: Decoder, + T0: Decodable<D>, + T1: Decodable<D>, + T2: Decodable<D>, + T3: Decodable<D>, + T4: Decodable<D> +> Decodable<D> for (T0, T1, T2, T3, T4) { + fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) { + d.read_seq(|d, len| { + assert_eq!(len, 5); + ( + d.read_seq_elt(0, |d| Decodable::decode(d)), + d.read_seq_elt(1, |d| Decodable::decode(d)), + d.read_seq_elt(2, |d| Decodable::decode(d)), + d.read_seq_elt(3, |d| Decodable::decode(d)), + d.read_seq_elt(4, |d| Decodable::decode(d)) + ) + }) + } +} + +impl< + E: Encoder, + K: Encodable<E> + Hash + IterBytes + Eq, + V: Encodable<E> +> Encodable<E> for HashMap<K, V> { + fn encode(&self, e: &mut E) { + e.emit_map(self.len(), |e| { + let mut i = 0; + for (key, val) in self.iter() { + e.emit_map_elt_key(i, |e| key.encode(e)); + e.emit_map_elt_val(i, |e| val.encode(e)); + i += 1; + } + }) + } +} + +impl< + D: Decoder, + K: Decodable<D> + Hash + IterBytes + Eq, + V: Decodable<D> +> Decodable<D> for HashMap<K, V> { + fn decode(d: &mut D) -> HashMap<K, V> { + d.read_map(|d, len| { + let mut map = HashMap::with_capacity(len); + for i in range(0u, len) { + let key = d.read_map_elt_key(i, |d| Decodable::decode(d)); + let val = d.read_map_elt_val(i, |d| Decodable::decode(d)); + map.insert(key, val); + } + map + }) + } +} + +impl< + S: Encoder, + T: Encodable<S> + Hash + IterBytes + Eq +> Encodable<S> for HashSet<T> { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + let mut i = 0; + for e in self.iter() { + s.emit_seq_elt(i, |s| e.encode(s)); + i += 1; + } + }) + } +} + +impl< + D: Decoder, + T: Decodable<D> + Hash + IterBytes + Eq +> Decodable<D> for HashSet<T> { + fn decode(d: &mut D) -> HashSet<T> { + d.read_seq(|d, len| { + let mut set = HashSet::with_capacity(len); + for i in range(0u, len) { + set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + set + }) + } +} + +impl< + E: Encoder, + V: Encodable<E> +> Encodable<E> for TrieMap<V> { + fn encode(&self, e: &mut E) { + e.emit_map(self.len(), |e| { + for (i, (key, val)) in self.iter().enumerate() { + e.emit_map_elt_key(i, |e| key.encode(e)); + e.emit_map_elt_val(i, |e| val.encode(e)); + } + }); + } +} + +impl< + D: Decoder, + V: Decodable<D> +> Decodable<D> for TrieMap<V> { + fn decode(d: &mut D) -> TrieMap<V> { + d.read_map(|d, len| { + let mut map = TrieMap::new(); + for i in range(0u, len) { + let key = d.read_map_elt_key(i, |d| Decodable::decode(d)); + let val = d.read_map_elt_val(i, |d| Decodable::decode(d)); + map.insert(key, val); + } + map + }) + } +} + +impl<S: Encoder> Encodable<S> for TrieSet { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + s.emit_seq_elt(i, |s| e.encode(s)); + } + }) + } +} + +impl<D: Decoder> Decodable<D> for TrieSet { + fn decode(d: &mut D) -> TrieSet { + d.read_seq(|d, len| { + let mut set = TrieSet::new(); + for i in range(0u, len) { + set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + set + }) + } +} + +// ___________________________________________________________________________ +// Helper routines +// +// In some cases, these should eventually be coded as traits. + +pub trait EncoderHelpers { + fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut Self, v: &T|); +} + +impl<S:Encoder> EncoderHelpers for S { + fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T|) { + self.emit_seq(v.len(), |this| { + for (i, e) in v.iter().enumerate() { + this.emit_seq_elt(i, |this| { + f(this, e) + }) + } + }) + } +} + +pub trait DecoderHelpers { + fn read_to_vec<T>(&mut self, f: |&mut Self| -> T) -> ~[T]; +} + +impl<D:Decoder> DecoderHelpers for D { + fn read_to_vec<T>(&mut self, f: |&mut D| -> T) -> ~[T] { + self.read_seq(|this, len| { + vec::from_fn(len, |i| { + this.read_seq_elt(i, |this| f(this)) + }) + }) + } +} |
