1use {
2 super::{
3 error::Error,
4 header::CarHeader,
5 util::{ld_read, read_node},
6 },
7 crate::cid::Cid,
8 alloc::{string::ToString, vec::Vec},
9};
10
11#[derive(Debug)]
13pub struct CarReader<R> {
14 reader: R,
15 header: CarHeader,
16 buffer: Vec<u8>,
17}
18
19impl<R> CarReader<R>
20where
21 R: core2::io::Read,
22{
23 pub fn new(mut reader: R) -> Result<Self, Error> {
25 let mut buffer = Vec::new();
26
27 match ld_read(&mut reader, &mut buffer)? {
28 Some(buf) => {
29 let header = CarHeader::decode(buf)?;
30
31 Ok(CarReader {
32 reader,
33 header,
34 buffer,
35 })
36 }
37 None => Err(Error::Parsing(
38 "failed to parse uvarint for header".to_string(),
39 )),
40 }
41 }
42
43 pub fn header(&self) -> &CarHeader {
45 &self.header
46 }
47
48 pub fn next_block(&mut self) -> Result<Option<(Cid, Vec<u8>)>, Error> {
50 read_node(&mut self.reader, &mut self.buffer)
51 }
52}
53
54impl<R: core2::io::Read> IntoIterator for CarReader<R> {
55 type IntoIter = Iter<R>;
56 type Item = Result<(Cid, Vec<u8>), Error>;
57
58 fn into_iter(self) -> Self::IntoIter {
59 Iter(self)
60 }
61}
62
63pub struct Iter<R: core2::io::Read>(CarReader<R>);
64impl<R: core2::io::Read> Iterator for Iter<R> {
65 type Item = Result<(Cid, Vec<u8>), Error>;
66
67 fn next(&mut self) -> Option<Self::Item> {
68 read_node(&mut self.0.reader, &mut self.0.buffer).transpose()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use {
75 super::super::{header::CarHeaderV1, writer::CarWriter, *},
76 crate::{cid::Cid, multihash::Multihash},
77 ::alloc::{vec::Vec, *},
78 core2::io::Cursor,
79 itertools::Itertools,
80 };
81
82 #[test]
83 fn car_write_read() {
84 let digest_test =
85 Multihash::wrap(0x1e, blake3::hash(b"test").as_bytes()).unwrap();
86 let cid_test = Cid::new_v1(0x71, digest_test);
87 let digest_foo =
88 Multihash::wrap(0x1e, blake3::hash(b"foo").as_bytes()).unwrap();
89 let cid_foo = Cid::new_v1(0x71, digest_foo);
90
91 let header = CarHeader::V1(CarHeaderV1::from(vec![cid_foo]));
92
93 let mut buffer = Vec::new();
94 let mut writer = CarWriter::new(header, &mut buffer);
95 writer.write(cid_test, b"test").unwrap();
96 writer.write(cid_foo, b"foo").unwrap();
97 writer.finish().unwrap();
98
99 let reader = Cursor::new(&buffer);
100 let car_reader = CarReader::new(reader).unwrap();
101 let files: Vec<_> = car_reader.into_iter().try_collect().unwrap();
102
103 assert_eq!(files.len(), 2);
104 assert_eq!(files[0].0, cid_test);
105 assert_eq!(files[0].1, b"test");
106 assert_eq!(files[1].0, cid_foo);
107 assert_eq!(files[1].1, b"foo");
108 }
109}