1use anyhow::{bail, Result};
16use bincode::Options;
17use std::io::{ErrorKind, Read, Write};
18
19mod bls;
20mod compress;
21mod hash;
22mod ignition;
23mod initrd;
24mod limit;
25mod peek;
26mod tee;
27mod verify;
28mod xz;
29mod zstd;
30
31pub use self::bls::*;
32pub use self::compress::*;
33pub use self::hash::*;
34pub use self::ignition::*;
35pub use self::initrd::*;
36pub use self::limit::*;
37pub use self::peek::*;
38pub use self::tee::*;
39pub use self::verify::*;
40pub use self::xz::*;
41pub use self::zstd::*;
42
43pub const BUFFER_SIZE: usize = 256 * 1024;
48
49pub fn copy_n(
54 reader: &mut (impl Read + ?Sized),
55 writer: &mut (impl Write + ?Sized),
56 mut n: u64,
57 buf: &mut [u8],
58) -> Result<u64> {
59 let mut written = 0;
60 loop {
61 if n == 0 {
62 return Ok(written);
63 }
64 let bufn = if n < (buf.len() as u64) {
65 &mut buf[..n as usize]
66 } else {
67 &mut *buf
68 };
69 let len = match reader.read(bufn) {
70 Ok(0) => return Ok(written),
71 Ok(len) => len,
72 Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
73 Err(e) => return Err(e.into()),
74 };
75 assert!(len as u64 <= n);
76 writer.write_all(&bufn[..len])?;
77 written += len as u64;
78 n -= len as u64;
79 }
80}
81
82pub fn copy_exactly_n(
84 reader: &mut (impl Read + ?Sized),
85 writer: &mut (impl Write + ?Sized),
86 n: u64,
87 buf: &mut [u8],
88) -> Result<u64> {
89 let bytes_copied = copy_n(reader, writer, n, buf)?;
90 if bytes_copied != n {
91 bail!(
92 "expected to copy {} bytes but instead copied {} bytes",
93 n,
94 bytes_copied
95 );
96 }
97 Ok(n)
98}
99
100pub fn bincoder() -> impl bincode::Options {
102 bincode::options()
103 .allow_trailing_bytes()
104 .with_no_limit()
106 .with_little_endian()
107 .with_varint_encoding()
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_copy_n() {
116 let mut sink = std::io::sink();
117 let mut buf = [0u8; 50];
118
119 let data = [0u8; 30];
120 assert_eq!(
121 copy_exactly_n(&mut &data[..], &mut sink, 0, &mut buf).unwrap(),
122 0
123 );
124 assert_eq!(
125 copy_exactly_n(&mut &data[..], &mut sink, 1, &mut buf).unwrap(),
126 1
127 );
128 assert_eq!(
129 copy_exactly_n(&mut &data[..], &mut sink, 29, &mut buf).unwrap(),
130 29
131 );
132 assert_eq!(
133 copy_exactly_n(&mut &data[..], &mut sink, 30, &mut buf).unwrap(),
134 30
135 );
136 assert_eq!(copy_n(&mut &data[..], &mut sink, 31, &mut buf).unwrap(), 30);
137 assert_eq!(copy_n(&mut &data[..], &mut sink, 49, &mut buf).unwrap(), 30);
138 assert_eq!(copy_n(&mut &data[..], &mut sink, 50, &mut buf).unwrap(), 30);
139 assert_eq!(copy_n(&mut &data[..], &mut sink, 51, &mut buf).unwrap(), 30);
140
141 let data = [0u8; 50];
142 assert_eq!(
143 copy_exactly_n(&mut &data[..], &mut sink, 0, &mut buf).unwrap(),
144 0
145 );
146 assert_eq!(
147 copy_exactly_n(&mut &data[..], &mut sink, 1, &mut buf).unwrap(),
148 1
149 );
150 assert_eq!(
151 copy_exactly_n(&mut &data[..], &mut sink, 49, &mut buf).unwrap(),
152 49
153 );
154 assert_eq!(
155 copy_exactly_n(&mut &data[..], &mut sink, 50, &mut buf).unwrap(),
156 50
157 );
158 assert_eq!(copy_n(&mut &data[..], &mut sink, 51, &mut buf).unwrap(), 50);
159
160 let data = [0u8; 80];
161 assert_eq!(
162 copy_exactly_n(&mut &data[..], &mut sink, 0, &mut buf).unwrap(),
163 0
164 );
165 assert_eq!(
166 copy_exactly_n(&mut &data[..], &mut sink, 1, &mut buf).unwrap(),
167 1
168 );
169 assert_eq!(
170 copy_exactly_n(&mut &data[..], &mut sink, 49, &mut buf).unwrap(),
171 49
172 );
173 assert_eq!(
174 copy_exactly_n(&mut &data[..], &mut sink, 50, &mut buf).unwrap(),
175 50
176 );
177 assert_eq!(
178 copy_exactly_n(&mut &data[..], &mut sink, 51, &mut buf).unwrap(),
179 51
180 );
181 assert_eq!(
182 copy_exactly_n(&mut &data[..], &mut sink, 79, &mut buf).unwrap(),
183 79
184 );
185 assert_eq!(
186 copy_exactly_n(&mut &data[..], &mut sink, 80, &mut buf).unwrap(),
187 80
188 );
189 assert_eq!(copy_n(&mut &data[..], &mut sink, 81, &mut buf).unwrap(), 80);
190 }
191}