]>
Commit | Line | Data |
---|---|---|
9cc50fc6 SL |
1 | // Copyright 2012-2015 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 | ||
9cc50fc6 | 11 | use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; |
c30ab7b3 | 12 | use std::borrow::Cow; |
9cc50fc6 SL |
13 | use std::io::{self, Write}; |
14 | use serialize; | |
15 | ||
32a655c1 SL |
16 | use rustc_i128::{i128, u128}; |
17 | ||
9cc50fc6 SL |
18 | // ----------------------------------------------------------------------------- |
19 | // Encoder | |
20 | // ----------------------------------------------------------------------------- | |
21 | ||
9e0c209e SL |
22 | pub type EncodeResult = io::Result<()>; |
23 | ||
9cc50fc6 SL |
24 | pub struct Encoder<'a> { |
25 | pub cursor: &'a mut io::Cursor<Vec<u8>>, | |
26 | } | |
27 | ||
28 | impl<'a> Encoder<'a> { | |
29 | pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> { | |
30 | Encoder { cursor: cursor } | |
31 | } | |
32 | } | |
33 | ||
34 | ||
35 | macro_rules! write_uleb128 { | |
36 | ($enc:expr, $value:expr) => {{ | |
37 | let pos = $enc.cursor.position() as usize; | |
32a655c1 | 38 | let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128); |
9cc50fc6 SL |
39 | $enc.cursor.set_position((pos + bytes_written) as u64); |
40 | Ok(()) | |
41 | }} | |
42 | } | |
43 | ||
44 | macro_rules! write_sleb128 { | |
45 | ($enc:expr, $value:expr) => {{ | |
46 | let pos = $enc.cursor.position() as usize; | |
32a655c1 | 47 | let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i128); |
9cc50fc6 SL |
48 | $enc.cursor.set_position((pos + bytes_written) as u64); |
49 | Ok(()) | |
50 | }} | |
51 | } | |
52 | ||
53 | impl<'a> serialize::Encoder for Encoder<'a> { | |
54 | type Error = io::Error; | |
55 | ||
56 | fn emit_nil(&mut self) -> EncodeResult { | |
57 | Ok(()) | |
58 | } | |
59 | ||
9e0c209e | 60 | fn emit_usize(&mut self, v: usize) -> EncodeResult { |
9cc50fc6 SL |
61 | write_uleb128!(self, v) |
62 | } | |
63 | ||
32a655c1 SL |
64 | fn emit_u128(&mut self, v: u128) -> EncodeResult { |
65 | write_uleb128!(self, v) | |
66 | } | |
67 | ||
9cc50fc6 SL |
68 | fn emit_u64(&mut self, v: u64) -> EncodeResult { |
69 | write_uleb128!(self, v) | |
70 | } | |
71 | ||
72 | fn emit_u32(&mut self, v: u32) -> EncodeResult { | |
73 | write_uleb128!(self, v) | |
74 | } | |
75 | ||
76 | fn emit_u16(&mut self, v: u16) -> EncodeResult { | |
77 | write_uleb128!(self, v) | |
78 | } | |
79 | ||
80 | fn emit_u8(&mut self, v: u8) -> EncodeResult { | |
81 | let _ = self.cursor.write_all(&[v]); | |
82 | Ok(()) | |
83 | } | |
84 | ||
9e0c209e | 85 | fn emit_isize(&mut self, v: isize) -> EncodeResult { |
9cc50fc6 SL |
86 | write_sleb128!(self, v) |
87 | } | |
88 | ||
32a655c1 SL |
89 | fn emit_i128(&mut self, v: i128) -> EncodeResult { |
90 | write_sleb128!(self, v) | |
91 | } | |
92 | ||
9cc50fc6 SL |
93 | fn emit_i64(&mut self, v: i64) -> EncodeResult { |
94 | write_sleb128!(self, v) | |
95 | } | |
96 | ||
97 | fn emit_i32(&mut self, v: i32) -> EncodeResult { | |
98 | write_sleb128!(self, v) | |
99 | } | |
100 | ||
101 | fn emit_i16(&mut self, v: i16) -> EncodeResult { | |
102 | write_sleb128!(self, v) | |
103 | } | |
104 | ||
105 | fn emit_i8(&mut self, v: i8) -> EncodeResult { | |
106 | let as_u8: u8 = unsafe { ::std::mem::transmute(v) }; | |
107 | let _ = self.cursor.write_all(&[as_u8]); | |
108 | Ok(()) | |
109 | } | |
110 | ||
111 | fn emit_bool(&mut self, v: bool) -> EncodeResult { | |
112 | self.emit_u8(if v { | |
113 | 1 | |
114 | } else { | |
115 | 0 | |
116 | }) | |
117 | } | |
118 | ||
119 | fn emit_f64(&mut self, v: f64) -> EncodeResult { | |
120 | let as_u64: u64 = unsafe { ::std::mem::transmute(v) }; | |
121 | self.emit_u64(as_u64) | |
122 | } | |
123 | ||
124 | fn emit_f32(&mut self, v: f32) -> EncodeResult { | |
125 | let as_u32: u32 = unsafe { ::std::mem::transmute(v) }; | |
126 | self.emit_u32(as_u32) | |
127 | } | |
128 | ||
129 | fn emit_char(&mut self, v: char) -> EncodeResult { | |
130 | self.emit_u32(v as u32) | |
131 | } | |
132 | ||
133 | fn emit_str(&mut self, v: &str) -> EncodeResult { | |
9e0c209e | 134 | self.emit_usize(v.len())?; |
9cc50fc6 SL |
135 | let _ = self.cursor.write_all(v.as_bytes()); |
136 | Ok(()) | |
137 | } | |
9cc50fc6 SL |
138 | } |
139 | ||
140 | impl<'a> Encoder<'a> { | |
141 | pub fn position(&self) -> usize { | |
142 | self.cursor.position() as usize | |
143 | } | |
9cc50fc6 SL |
144 | } |
145 | ||
146 | // ----------------------------------------------------------------------------- | |
147 | // Decoder | |
148 | // ----------------------------------------------------------------------------- | |
149 | ||
150 | pub struct Decoder<'a> { | |
151 | pub data: &'a [u8], | |
152 | position: usize, | |
153 | } | |
154 | ||
155 | impl<'a> Decoder<'a> { | |
156 | pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { | |
157 | Decoder { | |
158 | data: data, | |
159 | position: position, | |
160 | } | |
161 | } | |
162 | ||
163 | pub fn position(&self) -> usize { | |
164 | self.position | |
165 | } | |
166 | ||
167 | pub fn advance(&mut self, bytes: usize) { | |
168 | self.position += bytes; | |
169 | } | |
170 | } | |
171 | ||
172 | macro_rules! read_uleb128 { | |
173 | ($dec:expr, $t:ty) => ({ | |
174 | let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position); | |
175 | $dec.position += bytes_read; | |
176 | Ok(value as $t) | |
177 | }) | |
178 | } | |
179 | ||
180 | macro_rules! read_sleb128 { | |
181 | ($dec:expr, $t:ty) => ({ | |
182 | let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position); | |
183 | $dec.position += bytes_read; | |
184 | Ok(value as $t) | |
185 | }) | |
186 | } | |
187 | ||
188 | ||
189 | impl<'a> serialize::Decoder for Decoder<'a> { | |
9e0c209e | 190 | type Error = String; |
9cc50fc6 | 191 | |
c30ab7b3 | 192 | #[inline] |
9cc50fc6 SL |
193 | fn read_nil(&mut self) -> Result<(), Self::Error> { |
194 | Ok(()) | |
195 | } | |
196 | ||
32a655c1 SL |
197 | #[inline] |
198 | fn read_u128(&mut self) -> Result<u128, Self::Error> { | |
199 | read_uleb128!(self, u128) | |
200 | } | |
201 | ||
c30ab7b3 | 202 | #[inline] |
9cc50fc6 SL |
203 | fn read_u64(&mut self) -> Result<u64, Self::Error> { |
204 | read_uleb128!(self, u64) | |
205 | } | |
206 | ||
c30ab7b3 | 207 | #[inline] |
9cc50fc6 SL |
208 | fn read_u32(&mut self) -> Result<u32, Self::Error> { |
209 | read_uleb128!(self, u32) | |
210 | } | |
211 | ||
c30ab7b3 | 212 | #[inline] |
9cc50fc6 SL |
213 | fn read_u16(&mut self) -> Result<u16, Self::Error> { |
214 | read_uleb128!(self, u16) | |
215 | } | |
216 | ||
c30ab7b3 | 217 | #[inline] |
9cc50fc6 SL |
218 | fn read_u8(&mut self) -> Result<u8, Self::Error> { |
219 | let value = self.data[self.position]; | |
220 | self.position += 1; | |
221 | Ok(value) | |
222 | } | |
223 | ||
c30ab7b3 | 224 | #[inline] |
9e0c209e | 225 | fn read_usize(&mut self) -> Result<usize, Self::Error> { |
9cc50fc6 SL |
226 | read_uleb128!(self, usize) |
227 | } | |
228 | ||
32a655c1 SL |
229 | #[inline] |
230 | fn read_i128(&mut self) -> Result<i128, Self::Error> { | |
231 | read_sleb128!(self, i128) | |
232 | } | |
233 | ||
c30ab7b3 | 234 | #[inline] |
9cc50fc6 SL |
235 | fn read_i64(&mut self) -> Result<i64, Self::Error> { |
236 | read_sleb128!(self, i64) | |
237 | } | |
238 | ||
c30ab7b3 | 239 | #[inline] |
9cc50fc6 SL |
240 | fn read_i32(&mut self) -> Result<i32, Self::Error> { |
241 | read_sleb128!(self, i32) | |
242 | } | |
243 | ||
c30ab7b3 | 244 | #[inline] |
9cc50fc6 SL |
245 | fn read_i16(&mut self) -> Result<i16, Self::Error> { |
246 | read_sleb128!(self, i16) | |
247 | } | |
248 | ||
c30ab7b3 | 249 | #[inline] |
9cc50fc6 SL |
250 | fn read_i8(&mut self) -> Result<i8, Self::Error> { |
251 | let as_u8 = self.data[self.position]; | |
252 | self.position += 1; | |
253 | unsafe { Ok(::std::mem::transmute(as_u8)) } | |
254 | } | |
255 | ||
c30ab7b3 | 256 | #[inline] |
9e0c209e | 257 | fn read_isize(&mut self) -> Result<isize, Self::Error> { |
9cc50fc6 SL |
258 | read_sleb128!(self, isize) |
259 | } | |
260 | ||
c30ab7b3 | 261 | #[inline] |
9cc50fc6 | 262 | fn read_bool(&mut self) -> Result<bool, Self::Error> { |
54a0048b | 263 | let value = self.read_u8()?; |
9cc50fc6 SL |
264 | Ok(value != 0) |
265 | } | |
266 | ||
c30ab7b3 | 267 | #[inline] |
9cc50fc6 | 268 | fn read_f64(&mut self) -> Result<f64, Self::Error> { |
54a0048b | 269 | let bits = self.read_u64()?; |
9cc50fc6 SL |
270 | Ok(unsafe { ::std::mem::transmute(bits) }) |
271 | } | |
272 | ||
c30ab7b3 | 273 | #[inline] |
9cc50fc6 | 274 | fn read_f32(&mut self) -> Result<f32, Self::Error> { |
54a0048b | 275 | let bits = self.read_u32()?; |
9cc50fc6 SL |
276 | Ok(unsafe { ::std::mem::transmute(bits) }) |
277 | } | |
278 | ||
c30ab7b3 | 279 | #[inline] |
9cc50fc6 | 280 | fn read_char(&mut self) -> Result<char, Self::Error> { |
54a0048b | 281 | let bits = self.read_u32()?; |
9cc50fc6 SL |
282 | Ok(::std::char::from_u32(bits).unwrap()) |
283 | } | |
284 | ||
c30ab7b3 SL |
285 | #[inline] |
286 | fn read_str(&mut self) -> Result<Cow<str>, Self::Error> { | |
9e0c209e | 287 | let len = self.read_usize()?; |
9cc50fc6 SL |
288 | let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); |
289 | self.position += len; | |
c30ab7b3 | 290 | Ok(Cow::Borrowed(s)) |
9cc50fc6 SL |
291 | } |
292 | ||
9cc50fc6 | 293 | fn error(&mut self, err: &str) -> Self::Error { |
9e0c209e | 294 | err.to_string() |
9cc50fc6 SL |
295 | } |
296 | } | |
297 | ||
298 | ||
299 | #[cfg(test)] | |
300 | mod tests { | |
301 | use serialize::{Encodable, Decodable}; | |
302 | use std::io::Cursor; | |
303 | use std::fmt::Debug; | |
304 | use super::{Encoder, Decoder}; | |
305 | ||
306 | #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] | |
307 | struct Struct { | |
308 | a: (), | |
309 | b: u8, | |
310 | c: u16, | |
311 | d: u32, | |
312 | e: u64, | |
313 | f: usize, | |
314 | ||
315 | g: i8, | |
316 | h: i16, | |
317 | i: i32, | |
318 | j: i64, | |
319 | k: isize, | |
320 | ||
321 | l: char, | |
322 | m: String, | |
323 | n: f32, | |
324 | o: f64, | |
325 | p: bool, | |
326 | q: Option<u32>, | |
327 | } | |
328 | ||
329 | ||
330 | fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) { | |
331 | let mut cursor = Cursor::new(Vec::new()); | |
332 | ||
333 | for value in &values { | |
334 | let mut encoder = Encoder::new(&mut cursor); | |
335 | Encodable::encode(&value, &mut encoder).unwrap(); | |
336 | } | |
337 | ||
338 | let data = cursor.into_inner(); | |
339 | let mut decoder = Decoder::new(&data[..], 0); | |
340 | ||
341 | for value in values { | |
342 | let decoded = Decodable::decode(&mut decoder).unwrap(); | |
343 | assert_eq!(value, decoded); | |
344 | } | |
345 | } | |
346 | ||
347 | #[test] | |
348 | fn test_unit() { | |
349 | check_round_trip(vec![(), (), (), ()]); | |
350 | } | |
351 | ||
352 | #[test] | |
353 | fn test_u8() { | |
354 | let mut vec = vec![]; | |
355 | for i in ::std::u8::MIN..::std::u8::MAX { | |
356 | vec.push(i); | |
357 | } | |
358 | check_round_trip(vec); | |
359 | } | |
360 | ||
361 | #[test] | |
362 | fn test_u16() { | |
363 | for i in ::std::u16::MIN..::std::u16::MAX { | |
364 | check_round_trip(vec![1, 2, 3, i, i, i]); | |
365 | } | |
366 | } | |
367 | ||
368 | #[test] | |
369 | fn test_u32() { | |
370 | check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]); | |
371 | } | |
372 | ||
373 | #[test] | |
374 | fn test_u64() { | |
375 | check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]); | |
376 | } | |
377 | ||
378 | #[test] | |
379 | fn test_usize() { | |
380 | check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]); | |
381 | } | |
382 | ||
383 | #[test] | |
384 | fn test_i8() { | |
385 | let mut vec = vec![]; | |
386 | for i in ::std::i8::MIN..::std::i8::MAX { | |
387 | vec.push(i); | |
388 | } | |
389 | check_round_trip(vec); | |
390 | } | |
391 | ||
392 | #[test] | |
393 | fn test_i16() { | |
394 | for i in ::std::i16::MIN..::std::i16::MAX { | |
395 | check_round_trip(vec![-1, 2, -3, i, i, i, 2]); | |
396 | } | |
397 | } | |
398 | ||
399 | #[test] | |
400 | fn test_i32() { | |
401 | check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]); | |
402 | } | |
403 | ||
404 | #[test] | |
405 | fn test_i64() { | |
406 | check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]); | |
407 | } | |
408 | ||
409 | #[test] | |
410 | fn test_isize() { | |
411 | check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]); | |
412 | } | |
413 | ||
414 | #[test] | |
415 | fn test_bool() { | |
416 | check_round_trip(vec![false, true, true, false, false]); | |
417 | } | |
418 | ||
419 | #[test] | |
420 | fn test_f32() { | |
421 | let mut vec = vec![]; | |
422 | for i in -100..100 { | |
423 | vec.push((i as f32) / 3.0); | |
424 | } | |
425 | check_round_trip(vec); | |
426 | } | |
427 | ||
428 | #[test] | |
429 | fn test_f64() { | |
430 | let mut vec = vec![]; | |
431 | for i in -100..100 { | |
432 | vec.push((i as f64) / 3.0); | |
433 | } | |
434 | check_round_trip(vec); | |
435 | } | |
436 | ||
437 | #[test] | |
438 | fn test_char() { | |
439 | let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€']; | |
440 | check_round_trip(vec); | |
441 | } | |
442 | ||
443 | #[test] | |
444 | fn test_string() { | |
445 | let vec = vec!["abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), | |
446 | "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), | |
447 | "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(), | |
448 | "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(), | |
449 | "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), | |
450 | "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(), | |
451 | "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()]; | |
452 | ||
453 | check_round_trip(vec); | |
454 | } | |
455 | ||
456 | #[test] | |
457 | fn test_option() { | |
458 | check_round_trip(vec![Some(-1i8)]); | |
459 | check_round_trip(vec![Some(-2i16)]); | |
460 | check_round_trip(vec![Some(-3i32)]); | |
461 | check_round_trip(vec![Some(-4i64)]); | |
462 | check_round_trip(vec![Some(-5isize)]); | |
463 | ||
464 | let none_i8: Option<i8> = None; | |
465 | check_round_trip(vec![none_i8]); | |
466 | ||
467 | let none_i16: Option<i16> = None; | |
468 | check_round_trip(vec![none_i16]); | |
469 | ||
470 | let none_i32: Option<i32> = None; | |
471 | check_round_trip(vec![none_i32]); | |
472 | ||
473 | let none_i64: Option<i64> = None; | |
474 | check_round_trip(vec![none_i64]); | |
475 | ||
476 | let none_isize: Option<isize> = None; | |
477 | check_round_trip(vec![none_isize]); | |
478 | } | |
479 | ||
480 | #[test] | |
481 | fn test_struct() { | |
482 | check_round_trip(vec![Struct { | |
483 | a: (), | |
484 | b: 10, | |
485 | c: 11, | |
486 | d: 12, | |
487 | e: 13, | |
488 | f: 14, | |
489 | ||
490 | g: 15, | |
491 | h: 16, | |
492 | i: 17, | |
493 | j: 18, | |
494 | k: 19, | |
495 | ||
496 | l: 'x', | |
497 | m: "abc".to_string(), | |
498 | n: 20.5, | |
499 | o: 21.5, | |
500 | p: false, | |
501 | q: None, | |
502 | }]); | |
503 | ||
504 | check_round_trip(vec![Struct { | |
505 | a: (), | |
506 | b: 101, | |
507 | c: 111, | |
508 | d: 121, | |
509 | e: 131, | |
510 | f: 141, | |
511 | ||
512 | g: -15, | |
513 | h: -16, | |
514 | i: -17, | |
515 | j: -18, | |
516 | k: -19, | |
517 | ||
518 | l: 'y', | |
519 | m: "def".to_string(), | |
520 | n: -20.5, | |
521 | o: -21.5, | |
522 | p: true, | |
523 | q: Some(1234567), | |
524 | }]); | |
525 | } | |
526 | ||
527 | #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] | |
528 | enum Enum { | |
529 | Variant1, | |
530 | Variant2(usize, f32), | |
531 | Variant3 { | |
532 | a: i32, | |
533 | b: char, | |
534 | c: bool, | |
535 | }, | |
536 | } | |
537 | ||
538 | #[test] | |
539 | fn test_enum() { | |
540 | check_round_trip(vec![Enum::Variant1, | |
541 | Enum::Variant2(1, 2.5), | |
542 | Enum::Variant3 { | |
543 | a: 3, | |
544 | b: 'b', | |
545 | c: false, | |
546 | }, | |
547 | Enum::Variant3 { | |
548 | a: -4, | |
549 | b: 'f', | |
550 | c: true, | |
551 | }]); | |
552 | } | |
553 | ||
554 | #[test] | |
555 | fn test_sequence() { | |
556 | let mut vec = vec![]; | |
557 | for i in -100i64..100i64 { | |
558 | vec.push(i * 100000); | |
559 | } | |
560 | ||
561 | check_round_trip(vec![vec]); | |
562 | } | |
563 | ||
564 | #[test] | |
565 | fn test_hash_map() { | |
566 | use std::collections::HashMap; | |
567 | let mut map = HashMap::new(); | |
568 | for i in -100i64..100i64 { | |
569 | map.insert(i * 100000, i * 10000); | |
570 | } | |
571 | ||
572 | check_round_trip(vec![map]); | |
573 | } | |
574 | ||
575 | #[test] | |
576 | fn test_tuples() { | |
577 | check_round_trip(vec![('x', (), false, 0.5f32)]); | |
578 | check_round_trip(vec![(9i8, 10u16, 1.5f64)]); | |
579 | check_round_trip(vec![(-12i16, 11u8, 12usize)]); | |
580 | check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]); | |
581 | check_round_trip(vec![(String::new(), "some string".to_string())]); | |
582 | } | |
583 | } |