Skip to content

Commit de00b85

Browse files
committed
metadata: Introduce EsSub8 and EsSub32 tags.
They replace the existing `EsEnumVid`, `EsVecLen` and `EsMapLen` tags altogether; the meaning of them can be easily inferred from the enclosing tag. It also has an added benefit of encodings for smaller variant ids or lengths being more compact (5 bytes to 2 bytes).
1 parent 35c798b commit de00b85

File tree

1 file changed

+77
-35
lines changed

1 file changed

+77
-35
lines changed

src/librbml/lib.rs

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -97,32 +97,29 @@ pub enum EbmlEncoderTag {
9797
EsChar = 0x0b, // + 4 bytes
9898
EsF64 = 0x0c, // + 8 bytes
9999
EsF32 = 0x0d, // + 4 bytes
100-
EsEnumVid = 0x0e, // + 4 bytes
101-
EsVecLen = 0x0f, // + 4 bytes
102-
EsMapLen = 0x10, // + 4 bytes
103-
104-
EsStr = 0x11,
105-
EsEnum = 0x12,
106-
EsVec = 0x13,
107-
EsVecElt = 0x14,
108-
EsMap = 0x15,
109-
EsMapKey = 0x16,
110-
EsMapVal = 0x17,
111-
EsOpaque = 0x18,
100+
EsSub8 = 0x0e, // + 1 byte
101+
EsSub32 = 0x0f, // + 4 bytes
102+
103+
EsStr = 0x10,
104+
EsEnum = 0x11, // encodes the variant id as the first EsSub*
105+
EsVec = 0x12, // encodes the # of elements as the first EsSub*
106+
EsVecElt = 0x13,
107+
EsMap = 0x14, // encodes the # of pairs as the first EsSub*
108+
EsMapKey = 0x15,
109+
EsMapVal = 0x16,
110+
EsOpaque = 0x17,
112111
}
113112

114113
const NUM_TAGS: uint = 0x1000;
115-
const NUM_IMPLICIT_TAGS: uint = 0x11;
114+
const NUM_IMPLICIT_TAGS: uint = 0x10;
116115

117116
static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
118117
8, 8, 4, 2, 1, // EsU*
119118
8, 8, 4, 2, 1, // ESI*
120119
1, // EsBool
121120
4, // EsChar
122121
8, 4, // EsF*
123-
4, // EsEnumVid
124-
4, // EsVecLen
125-
4, // EsMapLen
122+
1, 4, // EsSub*
126123
];
127124

128125
#[derive(Debug)]
@@ -152,8 +149,8 @@ pub mod reader {
152149

153150
use serialize;
154151

155-
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt,
156-
EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
152+
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
153+
EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
157154
EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
158155
EsUint, EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
159156
Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
@@ -419,6 +416,37 @@ pub mod reader {
419416
Ok(r_doc)
420417
}
421418

419+
fn next_doc2(&mut self,
420+
exp_tag1: EbmlEncoderTag,
421+
exp_tag2: EbmlEncoderTag) -> DecodeResult<(bool, Doc<'doc>)> {
422+
assert!((exp_tag1 as uint) != (exp_tag2 as uint));
423+
debug!(". next_doc2(exp_tag1={:?}, exp_tag2={:?})", exp_tag1, exp_tag2);
424+
if self.pos >= self.parent.end {
425+
return Err(Expected(format!("no more documents in \
426+
current node!")));
427+
}
428+
let TaggedDoc { tag: r_tag, doc: r_doc } =
429+
try!(doc_at(self.parent.data, self.pos));
430+
debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}",
431+
self.parent.start,
432+
self.parent.end,
433+
self.pos,
434+
r_tag,
435+
r_doc.start,
436+
r_doc.end);
437+
if r_tag != (exp_tag1 as uint) && r_tag != (exp_tag2 as uint) {
438+
return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
439+
found tag {:?}", exp_tag1, exp_tag2, r_tag)));
440+
}
441+
if r_doc.end > self.parent.end {
442+
return Err(Expected(format!("invalid EBML, child extends to \
443+
{:#x}, parent to {:#x}",
444+
r_doc.end, self.parent.end)));
445+
}
446+
self.pos = r_doc.end;
447+
Ok((r_tag == (exp_tag2 as uint), r_doc))
448+
}
449+
422450
fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
423451
F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
424452
{
@@ -433,10 +461,15 @@ pub mod reader {
433461
Ok(r)
434462
}
435463

436-
fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
437-
let r = doc_as_u32(try!(self.next_doc(exp_tag)));
438-
debug!("_next_uint exp_tag={:?} result={:?}", exp_tag, r);
439-
Ok(r as uint)
464+
fn _next_sub(&mut self) -> DecodeResult<uint> {
465+
let (big, doc) = try!(self.next_doc2(EsSub8, EsSub32));
466+
let r = if big {
467+
doc_as_u32(doc) as uint
468+
} else {
469+
doc_as_u8(doc) as uint
470+
};
471+
debug!("_next_sub result={:?}", r);
472+
Ok(r)
440473
}
441474

442475
pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
@@ -538,7 +571,7 @@ pub mod reader {
538571
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
539572
{
540573
debug!("read_enum_variant()");
541-
let idx = try!(self._next_uint(EsEnumVid));
574+
let idx = try!(self._next_sub());
542575
debug!(" idx={}", idx);
543576

544577
f(self, idx)
@@ -556,7 +589,7 @@ pub mod reader {
556589
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
557590
{
558591
debug!("read_enum_struct_variant()");
559-
let idx = try!(self._next_uint(EsEnumVid));
592+
let idx = try!(self._next_sub());
560593
debug!(" idx={}", idx);
561594

562595
f(self, idx)
@@ -647,7 +680,7 @@ pub mod reader {
647680
{
648681
debug!("read_seq()");
649682
self.push_doc(EsVec, move |d| {
650-
let len = try!(d._next_uint(EsVecLen));
683+
let len = try!(d._next_sub());
651684
debug!(" len={}", len);
652685
f(d, len)
653686
})
@@ -665,7 +698,7 @@ pub mod reader {
665698
{
666699
debug!("read_map()");
667700
self.push_doc(EsMap, move |d| {
668-
let len = try!(d._next_uint(EsMapLen));
701+
let len = try!(d._next_sub());
669702
debug!(" len={}", len);
670703
f(d, len)
671704
})
@@ -697,10 +730,10 @@ pub mod writer {
697730
use std::old_io::{Writer, Seek};
698731
use std::old_io;
699732

700-
use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
701-
EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
733+
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
734+
EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
702735
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsUint,
703-
EsOpaque, EbmlEncoderTag, NUM_IMPLICIT_TAGS, NUM_TAGS };
736+
EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
704737

705738
use serialize;
706739

@@ -907,9 +940,18 @@ pub mod writer {
907940

908941
impl<'a, W: Writer + Seek> Encoder<'a, W> {
909942
// used internally to emit things like the vector length and so on
910-
fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
911-
assert!(v <= 0xFFFF_FFFF);
912-
self.wr_tagged_raw_u32(t as uint, v as u32)
943+
fn _emit_tagged_sub(&mut self, v: uint) -> EncodeResult {
944+
if let Some(v) = v.to_u8() {
945+
self.wr_tagged_raw_u8(EsSub8 as uint, v)
946+
} else if let Some(v) = v.to_u32() {
947+
self.wr_tagged_raw_u32(EsSub32 as uint, v)
948+
} else {
949+
Err(old_io::IoError {
950+
kind: old_io::OtherIoError,
951+
desc: "length or variant id too big",
952+
detail: Some(format!("{}", v))
953+
})
954+
}
913955
}
914956

915957
pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
@@ -995,7 +1037,7 @@ pub mod writer {
9951037
f: F) -> EncodeResult where
9961038
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
9971039
{
998-
try!(self._emit_tagged_uint(EsEnumVid, v_id));
1040+
try!(self._emit_tagged_sub(v_id));
9991041
f(self)
10001042
}
10011043

@@ -1078,7 +1120,7 @@ pub mod writer {
10781120
{
10791121

10801122
try!(self.start_tag(EsVec as uint));
1081-
try!(self._emit_tagged_uint(EsVecLen, len));
1123+
try!(self._emit_tagged_sub(len));
10821124
try!(f(self));
10831125
self.end_tag()
10841126
}
@@ -1097,7 +1139,7 @@ pub mod writer {
10971139
{
10981140

10991141
try!(self.start_tag(EsMap as uint));
1100-
try!(self._emit_tagged_uint(EsMapLen, len));
1142+
try!(self._emit_tagged_sub(len));
11011143
try!(f(self));
11021144
self.end_tag()
11031145
}

0 commit comments

Comments
 (0)