1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
//! Helpers for reading [crate::nar::wire] format.
use std::io::{
self,
ErrorKind::{Interrupted, InvalidData, UnexpectedEof},
};
use super::Reader;
use crate::nar::wire::Tag;
/// Consume a little-endian [prim@u64] from the reader.
pub fn u64(reader: &mut Reader) -> io::Result<u64> {
let mut buf = [0; 8];
reader.read_exact(&mut buf)?;
Ok(u64::from_le_bytes(buf))
}
/// Consume a byte string of up to `max_len` bytes from the reader.
pub fn bytes(reader: &mut Reader, max_len: usize) -> io::Result<Vec<u8>> {
assert!(max_len <= isize::MAX as usize);
// read the length, and reject excessively large values
let len = self::u64(reader)?;
if len > max_len as u64 {
return Err(InvalidData.into());
}
// we know the length fits in a usize now
let len = len as usize;
// read the data and padding into a buffer
let buf_len = (len + 7) & !7;
let mut buf = vec![0; buf_len];
reader.read_exact(&mut buf)?;
// verify that the padding is all zeroes
for b in buf.drain(len..) {
if b != 0 {
return Err(InvalidData.into());
}
}
Ok(buf)
}
/// Consume a known token from the reader.
pub fn token<const N: usize>(reader: &mut Reader, token: &[u8; N]) -> io::Result<()> {
let mut buf = [0u8; N];
// This implements something similar to [Read::read_exact], but verifies that
// the input data matches the token while we read it. These two slices respectively
// represent the remaining token to be verified, and the remaining input buffer.
let mut token = &token[..];
let mut buf = &mut buf[..];
while !token.is_empty() {
match reader.read(buf) {
Ok(0) => {
return Err(UnexpectedEof.into());
}
Ok(n) => {
let (t, b);
(t, token) = token.split_at(n);
(b, buf) = buf.split_at_mut(n);
if t != b {
return Err(InvalidData.into());
}
}
Err(e) => {
if e.kind() != Interrupted {
return Err(e);
}
}
}
}
Ok(())
}
/// Consume a [Tag] from the reader.
pub fn tag<T: Tag>(reader: &mut Reader) -> io::Result<T> {
let mut buf = T::make_buf();
let buf = buf.as_mut();
// first read the known minimum length…
reader.read_exact(&mut buf[..T::MIN])?;
// then decide which tag we're expecting
let tag = T::from_u8(buf[T::OFF]).ok_or(InvalidData)?;
let (head, tail) = tag.as_bytes().split_at(T::MIN);
// make sure what we've read so far is valid
if buf[..T::MIN] != *head {
return Err(InvalidData.into());
}
// …then read the rest, if any
if !tail.is_empty() {
let rest = tail.len();
reader.read_exact(&mut buf[..rest])?;
// and make sure it's what we expect
if buf[..rest] != *tail {
return Err(InvalidData.into());
}
}
Ok(tag)
}
|