1#![crate_type = "lib"]
21
22extern crate byteorder;
23#[macro_use]
24extern crate error_chain;
25
26pub use std::io::{Read, Write};
27use std::ops::Deref;
28use std::cmp::min;
29use std::borrow::{Borrow, Cow};
30use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
31
32pub mod record;
33
34mod error;
35pub use error::*;
36
37#[cfg(test)]
38mod test;
39
40static PADDING: [u8; 4] = [0; 4];
41
42#[inline]
47pub fn padding(sz: usize) -> &'static [u8] {
48 &PADDING[..(4 - (sz % 4)) % 4]
49}
50
51#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
57pub struct Opaque<'a>(pub Cow<'a, [u8]>);
58
59impl<'a> Opaque<'a> {
60 pub fn owned(v: Vec<u8>) -> Opaque<'a> {
61 Opaque(Cow::Owned(v))
62 }
63 pub fn borrowed(v: &'a [u8]) -> Opaque<'a> {
64 Opaque(Cow::Borrowed(v))
65 }
66}
67
68impl<'a> Deref for Opaque<'a> {
69 type Target = [u8];
70 fn deref(&self) -> &[u8] {
71 self.0.deref()
72 }
73}
74
75impl<'a> From<&'a [u8]> for Opaque<'a> {
76 fn from(v: &'a [u8]) -> Self {
77 Opaque::borrowed(v)
78 }
79}
80
81pub fn pack<Out: Write, T: Pack<Out>>(val: &T, out: &mut Out) -> Result<()> {
85 val.pack(out).map(|_| ())
86}
87
88pub fn pack_array<Out, T>(val: &[T], sz: usize, out: &mut Out, defl: Option<&T>) -> Result<usize>
95where
96 Out: Write,
97 T: Pack<Out>,
98{
99 let mut vsz = 0;
100 let val = &val[..min(sz, val.len())];
101
102 for v in val {
103 vsz += v.pack(out)?;
104 }
105 assert!(vsz % 4 == 0);
106
107 if val.len() < sz {
108 if let Some(defl) = defl {
109 for _ in val.len()..sz {
110 vsz += defl.pack(out)?;
111 }
112 } else {
113 bail!(ErrorKind::InvalidLen(sz));
114 }
115 }
116 Ok(vsz)
117}
118
119pub fn pack_opaque_array<Out: Write>(val: &[u8], sz: usize, out: &mut Out) -> Result<usize> {
124 let mut vsz;
125 let val = &val[..min(sz, val.len())];
126
127 vsz = val.len();
128 out.write_all(val)?;
129
130 let p = padding(sz);
131 for _ in val.len()..(sz + p.len()) {
132 out.write_u8(0)?;
133 vsz += 1;
134 }
135
136 Ok(vsz)
137}
138
139#[inline]
143pub fn pack_flex<Out: Write, T: Pack<Out>>(
144 val: &[T],
145 maxsz: Option<usize>,
146 out: &mut Out,
147) -> Result<usize> {
148 if maxsz.map_or(false, |m| val.len() > m) {
149 bail!(ErrorKind::InvalidLen(maxsz.unwrap()));
150 }
151
152 val.pack(out)
153}
154
155#[inline]
159pub fn pack_opaque_flex<Out: Write>(
160 val: &[u8],
161 maxsz: Option<usize>,
162 out: &mut Out,
163) -> Result<usize> {
164 if maxsz.map_or(false, |m| val.len() > m) {
165 bail!(ErrorKind::InvalidLen(maxsz.unwrap()));
166 }
167
168 Opaque::borrowed(val).pack(out)
169}
170
171#[inline]
173pub fn pack_string<Out: Write>(val: &str, maxsz: Option<usize>, out: &mut Out) -> Result<usize> {
174 pack_opaque_flex(val.as_bytes(), maxsz, out)
175}
176
177pub fn unpack_array<In, T>(
186 input: &mut In,
187 array: &mut [T],
188 arraysz: usize,
189 defl: Option<&T>,
190) -> Result<usize>
191where
192 In: Read,
193 T: Unpack<In> + Clone,
194{
195 let mut rsz = 0;
196 let sz = min(arraysz, array.len());
197
198 for elem in &mut array[..sz] {
199 let (v, sz) = Unpack::unpack(input)?;
200 rsz += sz;
201 *elem = v;
202 }
203
204 if arraysz < array.len() {
206 if let Some(defl) = defl {
207 for elem in &mut array[arraysz..] {
208 *elem = defl.clone();
209 }
210 } else {
211 bail!(ErrorKind::InvalidLen(arraysz));
212 }
213 }
214
215 if arraysz > array.len() {
217 for _ in array.len()..arraysz {
218 let (_, sz) = T::unpack(input)?;
219 rsz += sz;
220 }
221 }
222 assert!(rsz % 4 == 0);
223
224 Ok(rsz)
225}
226
227pub fn unpack_opaque_array<In: Read>(
235 input: &mut In,
236 bytes: &mut [u8],
237 bytesz: usize,
238) -> Result<usize> {
239 let sz = min(bytesz, bytes.len());
240 let mut rsz = 0;
241
242 while rsz < sz {
243 let r = input.read(&mut bytes[rsz..])?;
244 rsz += r;
245 }
246
247 if sz < bytes.len() {
249 for b in &mut bytes[sz..] {
250 *b = 0;
251 }
252 }
253
254 let p = padding(bytesz).len();
256 if bytes.len() < bytesz + p {
257 for _ in bytes.len()..(bytesz + p) {
258 let _ = input.read_u8()?;
259 rsz += 1;
260 }
261 }
262
263 Ok(rsz)
264}
265
266pub fn unpack_flex<In: Read, T: Unpack<In>>(
268 input: &mut In,
269 maxsz: Option<usize>,
270) -> Result<(Vec<T>, usize)> {
271 let (elems, mut sz) = Unpack::unpack(input)?;
272
273 if maxsz.map_or(false, |m| elems > m) {
274 bail!(ErrorKind::InvalidLen(maxsz.unwrap()));
275 }
276
277 let mut out = Vec::with_capacity(elems);
278
279 for _ in 0..elems {
280 let (e, esz) = Unpack::unpack(input)?;
281 out.push(e);
282 sz += esz;
283 }
284
285 let p = padding(sz);
286 for _ in 0..p.len() {
287 let _ = input.read_u8()?;
288 }
289 sz += p.len();
290
291 Ok((out, sz))
292}
293
294pub fn unpack_opaque_flex<In: Read>(
298 input: &mut In,
299 maxsz: Option<usize>,
300) -> Result<(Vec<u8>, usize)> {
301 let (elems, mut sz) = Unpack::unpack(input)?;
302
303 if maxsz.map_or(false, |m| elems > m) {
304 bail!(ErrorKind::InvalidLen(maxsz.unwrap()));
305 }
306
307 let mut out = Vec::with_capacity(elems);
308
309 sz += input.take(elems as u64).read_to_end(&mut out)?;
310
311 let p = padding(sz);
312 for _ in 0..p.len() {
313 let _ = input.read_u8()?;
314 }
315 sz += p.len();
316
317 Ok((out, sz))
318}
319
320pub fn unpack_string<In: Read>(input: &mut In, maxsz: Option<usize>) -> Result<(String, usize)> {
322 let (v, sz) = unpack_opaque_flex(input, maxsz)?;
323
324 String::from_utf8(v).map_err(Error::from).map(|s| (s, sz))
325}
326
327pub trait Pack<Out: Write> {
338 fn pack(&self, out: &mut Out) -> Result<usize>;
339}
340
341#[cfg(feature = "bytecodec")]
342impl<Out: Write> Pack<Out> for u8 {
343 #[inline]
344 fn pack(&self, out: &mut Out) -> Result<usize> {
345 out.write_u32::<BigEndian>(*self as u32)
346 .map_err(Error::from)
347 .map(|_| 4)
348 }
349}
350
351#[cfg(feature = "bytecodec")]
352impl<Out: Write> Pack<Out> for i8 {
353 #[inline]
354 fn pack(&self, out: &mut Out) -> Result<usize> {
355 out.write_i32::<BigEndian>(*self as i32)
356 .map_err(Error::from)
357 .map(|_| 4)
358 }
359}
360
361impl<Out: Write> Pack<Out> for u32 {
362 #[inline]
363 fn pack(&self, out: &mut Out) -> Result<usize> {
364 out.write_u32::<BigEndian>(*self).map_err(Error::from).map(
365 |_| 4,
366 )
367 }
368}
369
370impl<Out: Write> Pack<Out> for i32 {
371 #[inline]
372 fn pack(&self, out: &mut Out) -> Result<usize> {
373 out.write_i32::<BigEndian>(*self).map_err(Error::from).map(
374 |_| 4,
375 )
376 }
377}
378
379impl<Out: Write> Pack<Out> for u64 {
380 #[inline]
381 fn pack(&self, out: &mut Out) -> Result<usize> {
382 out.write_u64::<BigEndian>(*self).map_err(Error::from).map(
383 |_| 8,
384 )
385 }
386}
387
388impl<Out: Write> Pack<Out> for i64 {
389 #[inline]
390 fn pack(&self, out: &mut Out) -> Result<usize> {
391 out.write_i64::<BigEndian>(*self).map_err(Error::from).map(
392 |_| 8,
393 )
394 }
395}
396
397impl<Out: Write> Pack<Out> for f32 {
398 #[inline]
399 fn pack(&self, out: &mut Out) -> Result<usize> {
400 out.write_f32::<BigEndian>(*self).map_err(Error::from).map(
401 |_| 4,
402 )
403 }
404}
405
406impl<Out: Write> Pack<Out> for f64 {
407 #[inline]
408 fn pack(&self, out: &mut Out) -> Result<usize> {
409 out.write_f64::<BigEndian>(*self).map_err(Error::from).map(
410 |_| 8,
411 )
412 }
413}
414
415impl<Out: Write> Pack<Out> for bool {
416 #[inline]
417 fn pack(&self, out: &mut Out) -> Result<usize> {
418 (*self as u32).pack(out)
419 }
420}
421
422impl<Out: Write> Pack<Out> for () {
423 #[inline]
424 fn pack(&self, _out: &mut Out) -> Result<usize> {
425 Ok(0)
426 }
427}
428
429impl<Out: Write> Pack<Out> for usize {
430 #[inline]
431 fn pack(&self, out: &mut Out) -> Result<usize> {
432 (*self as u32).pack(out)
433 }
434}
435
436impl<Out: Write, T: Pack<Out>> Pack<Out> for [T] {
437 fn pack(&self, out: &mut Out) -> Result<usize> {
438 let len = self.len();
439
440 let mut sz = len.pack(out)?;
441 for it in self {
442 sz += it.pack(out)?;
443 }
444
445 let p = padding(sz);
446 if p.len() > 0 {
447 out.write_all(p)?;
448 sz += p.len();
449 }
450
451 Ok(sz)
452 }
453}
454
455impl<Out: Write, T: Pack<Out>> Pack<Out> for Vec<T> {
456 #[inline]
457 fn pack(&self, out: &mut Out) -> Result<usize> {
458 if self.len() > u32::max_value() as usize {
459 return Err(ErrorKind::InvalidLen(self.len()).into());
460 }
461
462 (&self[..]).pack(out)
463 }
464}
465
466impl<'a, Out: Write> Pack<Out> for Opaque<'a> {
467 fn pack(&self, out: &mut Out) -> Result<usize> {
468 let mut sz;
469 let data: &[u8] = self.0.borrow();
470
471 if data.len() > u32::max_value() as usize {
472 return Err(ErrorKind::InvalidLen(data.len()).into());
473 }
474
475 sz = data.len().pack(out)?;
476
477 out.write_all(data)?;
478 sz += data.len();
479
480 let p = padding(sz);
481 if p.len() > 0 {
482 out.write_all(p)?;
483 sz += p.len();
484 }
485
486 Ok(sz)
487 }
488}
489
490impl<Out: Write> Pack<Out> for str {
491 #[inline]
492 fn pack(&self, out: &mut Out) -> Result<usize> {
493 Opaque::borrowed(self.as_bytes()).pack(out)
494 }
495}
496
497impl<Out: Write, T: Pack<Out>> Pack<Out> for Option<T> {
498 fn pack(&self, out: &mut Out) -> Result<usize> {
499 match self {
500 &None => false.pack(out),
501 &Some(ref v) => {
502 let sz = true.pack(out)? + v.pack(out)?;
503 Ok(sz)
504 }
505 }
506 }
507}
508
509impl<Out: Write, T: Pack<Out>> Pack<Out> for Box<T> {
510 fn pack(&self, out: &mut Out) -> Result<usize> {
511 let t: &T = self.borrow();
512 t.pack(out)
513 }
514}
515
516impl<'a, Out: Write, T> Pack<Out> for Cow<'a, T>
517where
518 T: 'a + Pack<Out> + ToOwned<Owned = T>,
519{
520 fn pack(&self, out: &mut Out) -> Result<usize> {
521 let t: &T = self.borrow();
522 t.pack(out)
523 }
524}
525
526pub fn unpack<In: Read, T: Unpack<In>>(input: &mut In) -> Result<T> {
534 T::unpack(input).map(|(v, _)| v)
535}
536
537pub trait Unpack<In: Read>: Sized {
546 fn unpack(input: &mut In) -> Result<(Self, usize)>;
547}
548
549#[cfg(feature = "bytecodec")]
550impl<In: Read> Unpack<In> for u8 {
551 #[inline]
552 fn unpack(input: &mut In) -> Result<(Self, usize)> {
553 input.read_u32::<BigEndian>().map_err(Error::from).map(
554 |v| {
555 (v as u8, 4)
556 },
557 )
558 }
559}
560
561#[cfg(feature = "bytecodec")]
562impl<In: Read> Unpack<In> for i8 {
563 #[inline]
564 fn unpack(input: &mut In) -> Result<(Self, usize)> {
565 input.read_i32::<BigEndian>().map_err(Error::from).map(
566 |v| {
567 (v as i8, 4)
568 },
569 )
570 }
571}
572
573impl<In: Read> Unpack<In> for u32 {
574 #[inline]
575 fn unpack(input: &mut In) -> Result<(Self, usize)> {
576 input.read_u32::<BigEndian>().map_err(Error::from).map(
577 |v| (v, 4),
578 )
579 }
580}
581
582impl<In: Read> Unpack<In> for i32 {
583 #[inline]
584 fn unpack(input: &mut In) -> Result<(Self, usize)> {
585 input.read_i32::<BigEndian>().map_err(Error::from).map(
586 |v| (v, 4),
587 )
588 }
589}
590
591impl<In: Read> Unpack<In> for u64 {
592 #[inline]
593 fn unpack(input: &mut In) -> Result<(Self, usize)> {
594 input.read_u64::<BigEndian>().map_err(Error::from).map(
595 |v| (v, 8),
596 )
597 }
598}
599
600impl<In: Read> Unpack<In> for i64 {
601 #[inline]
602 fn unpack(input: &mut In) -> Result<(Self, usize)> {
603 input.read_i64::<BigEndian>().map_err(Error::from).map(
604 |v| (v, 8),
605 )
606 }
607}
608
609impl<In: Read> Unpack<In> for f32 {
610 fn unpack(input: &mut In) -> Result<(Self, usize)> {
611 input.read_f32::<BigEndian>().map_err(Error::from).map(
612 |v| (v, 4),
613 )
614 }
615}
616
617impl<In: Read> Unpack<In> for f64 {
618 fn unpack(input: &mut In) -> Result<(Self, usize)> {
619 input.read_f64::<BigEndian>().map_err(Error::from).map(
620 |v| (v, 8),
621 )
622 }
623}
624
625impl<In: Read> Unpack<In> for bool {
626 #[inline]
627 fn unpack(input: &mut In) -> Result<(Self, usize)> {
628 i32::unpack(input).and_then(|(v, sz)| match v {
629 0 => Ok((false, sz)),
630 1 => Ok((true, sz)),
631 v => Err(ErrorKind::InvalidEnum(v).into()),
632 })
633 }
634}
635
636impl<In: Read> Unpack<In> for () {
637 #[inline]
638 fn unpack(_input: &mut In) -> Result<(Self, usize)> {
639 Ok(((), 0))
640 }
641}
642
643impl<In: Read> Unpack<In> for usize {
644 #[inline]
645 fn unpack(input: &mut In) -> Result<(Self, usize)> {
646 u32::unpack(input).map(|(v, sz)| (v as usize, sz))
647 }
648}
649
650impl<In: Read, T: Unpack<In>> Unpack<In> for Vec<T> {
651 fn unpack(input: &mut In) -> Result<(Self, usize)> {
652 unpack_flex(input, None)
653 }
654}
655
656impl<In: Read> Unpack<In> for String {
657 fn unpack(input: &mut In) -> Result<(Self, usize)> {
658 let (v, sz) = unpack_opaque_flex(input, None)?;
659 String::from_utf8(v).map_err(Error::from).map(|s| (s, sz))
660 }
661}
662
663impl<'a, In: Read> Unpack<In> for Opaque<'a> {
664 fn unpack(input: &mut In) -> Result<(Self, usize)> {
665 let (len, mut sz) = usize::unpack(input)?;
666 let mut v = Vec::new();
667 sz += input.by_ref().take(len as u64).read_to_end(&mut v)?;
668
669 let p = padding(sz);
670 for _ in 0..p.len() {
671 let _ = input.read_u8()?;
672 sz += 1;
673 }
674
675 Ok((Opaque(Cow::Owned(v)), sz))
676 }
677}
678
679impl<In: Read, T: Unpack<In>> Unpack<In> for Option<T> {
680 fn unpack(input: &mut In) -> Result<(Self, usize)> {
681 let (have, mut sz) = Unpack::unpack(input)?;
682 let ret = if have {
683 let (v, osz) = Unpack::unpack(input)?;
684 sz += osz;
685 Some(v)
686 } else {
687 None
688 };
689 Ok((ret, sz))
690 }
691}
692
693impl<In: Read, T: Unpack<In>> Unpack<In> for Box<T> {
694 fn unpack(input: &mut In) -> Result<(Self, usize)> {
695 let (b, sz) = Unpack::unpack(input)?;
696 Ok((Box::new(b), sz))
697 }
698}
699
700impl<'a, In: Read, T> Unpack<In> for Cow<'a, T>
701where
702 T: 'a + Unpack<In> + ToOwned<Owned = T>,
703{
704 fn unpack(input: &mut In) -> Result<(Self, usize)> {
705 let (b, sz) = Unpack::unpack(input)?;
706 Ok((Cow::Owned(b), sz))
707 }
708}