12
12
13
13
14
14
use std:: str;
15
+ use std:: cast;
16
+ use std:: vec;
15
17
16
18
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
17
19
// cursor model. See the specification here:
@@ -29,9 +31,42 @@ struct EbmlState {
29
31
data_pos : uint ,
30
32
}
31
33
34
+ #[ deriving( Clone ) ]
35
+ pub enum EbmlData {
36
+ SafeData ( @~[ u8 ] ) ,
37
+ UnsafeData ( * u8 , uint )
38
+ }
39
+
40
+ impl EbmlData {
41
+ #[ inline]
42
+ pub fn slice < ' a > ( & ' a self , start : uint , end : uint ) -> & ' a [ u8 ] {
43
+ match * self {
44
+ SafeData ( @ref v) => v. slice ( start, end) ,
45
+ UnsafeData ( buf, len) => unsafe {
46
+ do vec:: raw:: buf_as_slice ( buf, len) |s| {
47
+ cast:: transmute ( s. slice ( start, end) )
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ #[ inline]
54
+ pub fn as_slice < ' a > ( & ' a self ) -> & ' a [ u8 ] {
55
+ self . slice ( 0 , self . len ( ) )
56
+ }
57
+
58
+ #[ inline]
59
+ pub fn len ( & self ) -> uint {
60
+ match * self {
61
+ SafeData ( @ref v) => v. len ( ) ,
62
+ UnsafeData ( _, len) => len
63
+ }
64
+ }
65
+ }
66
+
32
67
#[ deriving( Clone ) ]
33
68
pub struct Doc {
34
- data : @~ [ u8 ] ,
69
+ data : EbmlData ,
35
70
start : uint ,
36
71
end : uint ,
37
72
}
@@ -185,24 +220,28 @@ pub mod reader {
185
220
}
186
221
187
222
pub fn Doc ( data : @~[ u8 ] ) -> Doc {
188
- Doc { data : data, start : 0 u, end : data. len ( ) }
223
+ Doc { data : SafeData ( data) , start : 0 u, end : data. len ( ) }
224
+ }
225
+
226
+ pub fn unsafe_Doc ( buf : * u8 , len : uint ) -> Doc {
227
+ Doc { data : UnsafeData ( buf, len) , start : 0 u, end : len }
189
228
}
190
229
191
- pub fn doc_at ( data : @~ [ u8 ] , start : uint ) -> TaggedDoc {
192
- let elt_tag = vuint_at ( * data, start) ;
193
- let elt_size = vuint_at ( * data, elt_tag. next ) ;
230
+ pub fn doc_at ( data : & EbmlData , start : uint ) -> TaggedDoc {
231
+ let elt_tag = vuint_at ( data. as_slice ( ) , start) ;
232
+ let elt_size = vuint_at ( data. as_slice ( ) , elt_tag. next ) ;
194
233
let end = elt_size. next + elt_size. val ;
195
234
TaggedDoc {
196
235
tag : elt_tag. val ,
197
- doc : Doc { data : data, start : elt_size. next , end : end }
236
+ doc : Doc { data : data. clone ( ) , start : elt_size. next , end : end }
198
237
}
199
238
}
200
239
201
240
pub fn maybe_get_doc ( d : Doc , tg : uint ) -> Option < Doc > {
202
241
let mut pos = d. start ;
203
242
while pos < d. end {
204
- let elt_tag = vuint_at ( * d. data , pos) ;
205
- let elt_size = vuint_at ( * d. data , elt_tag. next ) ;
243
+ let elt_tag = vuint_at ( d. data . as_slice ( ) , pos) ;
244
+ let elt_size = vuint_at ( d. data . as_slice ( ) , elt_tag. next ) ;
206
245
pos = elt_size. next + elt_size. val ;
207
246
if elt_tag. val == tg {
208
247
return Some ( Doc { data : d. data , start : elt_size. next ,
@@ -225,8 +264,8 @@ pub mod reader {
225
264
pub fn docs ( d : Doc , it : & fn ( uint , Doc ) -> bool ) -> bool {
226
265
let mut pos = d. start ;
227
266
while pos < d. end {
228
- let elt_tag = vuint_at ( * d. data , pos) ;
229
- let elt_size = vuint_at ( * d. data , elt_tag. next ) ;
267
+ let elt_tag = vuint_at ( d. data . as_slice ( ) , pos) ;
268
+ let elt_size = vuint_at ( d. data . as_slice ( ) , elt_tag. next ) ;
230
269
pos = elt_size. next + elt_size. val ;
231
270
let doc = Doc { data : d. data , start : elt_size. next , end : pos } ;
232
271
if !it ( elt_tag. val , doc) {
@@ -239,8 +278,8 @@ pub mod reader {
239
278
pub fn tagged_docs ( d : Doc , tg : uint , it : & fn ( Doc ) -> bool ) -> bool {
240
279
let mut pos = d. start ;
241
280
while pos < d. end {
242
- let elt_tag = vuint_at ( * d. data , pos) ;
243
- let elt_size = vuint_at ( * d. data , elt_tag. next ) ;
281
+ let elt_tag = vuint_at ( d. data . as_slice ( ) , pos) ;
282
+ let elt_size = vuint_at ( d. data . as_slice ( ) , elt_tag. next ) ;
244
283
pos = elt_size. next + elt_size. val ;
245
284
if elt_tag. val == tg {
246
285
let doc = Doc { data : d. data , start : elt_size. next ,
@@ -260,22 +299,22 @@ pub mod reader {
260
299
261
300
pub fn doc_as_u8 ( d : Doc ) -> u8 {
262
301
assert_eq ! ( d. end, d. start + 1 u) ;
263
- ( * d. data ) [ d. start ]
302
+ d. data . as_slice ( ) [ d. start ]
264
303
}
265
304
266
305
pub fn doc_as_u16 ( d : Doc ) -> u16 {
267
306
assert_eq ! ( d. end, d. start + 2 u) ;
268
- io:: u64_from_be_bytes ( * d. data , d. start , 2 u) as u16
307
+ io:: u64_from_be_bytes ( d. data . as_slice ( ) , d. start , 2 u) as u16
269
308
}
270
309
271
310
pub fn doc_as_u32 ( d : Doc ) -> u32 {
272
311
assert_eq ! ( d. end, d. start + 4 u) ;
273
- io:: u64_from_be_bytes ( * d. data , d. start , 4 u) as u32
312
+ io:: u64_from_be_bytes ( d. data . as_slice ( ) , d. start , 4 u) as u32
274
313
}
275
314
276
315
pub fn doc_as_u64 ( d : Doc ) -> u64 {
277
316
assert_eq ! ( d. end, d. start + 8 u) ;
278
- io:: u64_from_be_bytes ( * d. data , d. start , 8 u)
317
+ io:: u64_from_be_bytes ( d. data . as_slice ( ) , d. start , 8 u)
279
318
}
280
319
281
320
pub fn doc_as_i8 ( d : Doc ) -> i8 { doc_as_u8 ( d) as i8 }
@@ -298,8 +337,7 @@ pub mod reader {
298
337
impl Decoder {
299
338
fn _check_label ( & mut self , lbl : & str ) {
300
339
if self . pos < self . parent . end {
301
- let TaggedDoc { tag : r_tag, doc : r_doc } =
302
- doc_at ( self . parent . data , self . pos ) ;
340
+ let TaggedDoc { tag : r_tag, doc : r_doc } = doc_at ( & self . parent . data , self . pos ) ;
303
341
304
342
if r_tag == ( EsLabel as uint ) {
305
343
self . pos = r_doc. end ;
@@ -316,8 +354,7 @@ pub mod reader {
316
354
if self . pos >= self . parent . end {
317
355
fail ! ( "no more documents in current node!" ) ;
318
356
}
319
- let TaggedDoc { tag : r_tag, doc : r_doc } =
320
- doc_at ( self . parent . data , self . pos ) ;
357
+ let TaggedDoc { tag : r_tag, doc : r_doc } = doc_at ( & self . parent . data , self . pos ) ;
321
358
debug ! ( "self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?" ,
322
359
self . parent. start,
323
360
self . parent. end,
0 commit comments