nix_compat/nar/reader/
read.rs1use std::io::{
4 self,
5 ErrorKind::{Interrupted, InvalidData, UnexpectedEof},
6};
7
8use super::Reader;
9use crate::nar::wire::Tag;
10
11pub fn u64(reader: &mut Reader) -> io::Result<u64> {
13 let mut buf = [0; 8];
14 reader.read_exact(&mut buf)?;
15 Ok(u64::from_le_bytes(buf))
16}
17
18pub fn bytes_buf<'a, const N: usize>(
21 reader: &mut Reader,
22 buf: &'a mut [u8; N],
23 max_len: usize,
24) -> io::Result<&'a [u8]> {
25 assert_eq!(N % 8, 0);
26 assert!(max_len <= N);
27
28 let len = self::u64(reader)?;
30 if len > max_len as u64 {
31 return Err(InvalidData.into());
32 }
33 let len = len as usize;
35
36 let buf_len = (len + 7) & !7;
38 reader.read_exact(&mut buf[..buf_len])?;
39
40 for &b in &buf[len..buf_len] {
42 if b != 0 {
43 return Err(InvalidData.into());
44 }
45 }
46
47 Ok(&buf[..len])
48}
49
50pub fn bytes(reader: &mut Reader, max_len: usize) -> io::Result<Vec<u8>> {
52 assert!(max_len <= isize::MAX as usize);
53
54 let len = self::u64(reader)?;
56 if len > max_len as u64 {
57 return Err(InvalidData.into());
58 }
59 let len = len as usize;
61
62 let buf_len = (len + 7) & !7;
64 let mut buf = vec![0; buf_len];
65 reader.read_exact(&mut buf)?;
66
67 for b in buf.drain(len..) {
69 if b != 0 {
70 return Err(InvalidData.into());
71 }
72 }
73
74 Ok(buf)
75}
76
77pub fn token<const N: usize>(reader: &mut Reader, token: &[u8; N]) -> io::Result<()> {
79 let mut buf = [0u8; N];
80
81 let mut token = &token[..];
85 let mut buf = &mut buf[..];
86
87 while !token.is_empty() {
88 match reader.read(buf) {
89 Ok(0) => {
90 return Err(UnexpectedEof.into());
91 }
92 Ok(n) => {
93 let (t, b);
94 (t, token) = token.split_at(n);
95 (b, buf) = buf.split_at_mut(n);
96
97 if t != b {
98 return Err(InvalidData.into());
99 }
100 }
101 Err(e) => {
102 if e.kind() != Interrupted {
103 return Err(e);
104 }
105 }
106 }
107 }
108
109 Ok(())
110}
111
112pub fn tag<T: Tag>(reader: &mut Reader) -> io::Result<T> {
114 let mut buf = T::make_buf();
115 let buf = buf.as_mut();
116
117 reader.read_exact(&mut buf[..T::MIN])?;
119
120 let tag = T::from_u8(buf[T::OFF]).ok_or(InvalidData)?;
122 let (head, tail) = tag.as_bytes().split_at(T::MIN);
123
124 if buf[..T::MIN] != *head {
126 return Err(InvalidData.into());
127 }
128
129 if !tail.is_empty() {
131 let rest = tail.len();
132 reader.read_exact(&mut buf[..rest])?;
133
134 if buf[..rest] != *tail {
136 return Err(InvalidData.into());
137 }
138 }
139
140 Ok(tag)
141}