blockless_car/utils/
cat.rs1use std::{
2 collections::VecDeque,
3 io::{self, Write},
4 str::FromStr,
5};
6
7use cid::Cid;
8
9use crate::{error::CarError, reader::CarReader, unixfs::UnixFs, Ipld};
10
11pub fn ipld_write(
15 reader: &mut impl CarReader,
16 cid: Cid,
17 output: &mut impl Write,
18) -> Result<(), CarError> {
19 let mut vecq = VecDeque::new();
20 vecq.push_back(cid);
21 ipld_write_inner(reader, &mut vecq, output)
22}
23
24fn ipld_write_inner(
28 reader: &mut impl CarReader,
29 vecq: &mut VecDeque<Cid>,
30 output: &mut impl Write,
31) -> Result<(), CarError> {
32 while let Some(file_cid) = vecq.pop_front() {
33 let file_ipld: Ipld = reader.ipld(&file_cid).unwrap();
34
35 match file_ipld {
36 Ipld::Bytes(b) => {
37 output.write_all(&b[..])?;
38 }
39 m @ Ipld::Map(_) => {
40 let unix_fs: Result<UnixFs, CarError> = (file_cid, m).try_into();
41 let ufs = unix_fs?;
42 for link in ufs.links().iter() {
43 vecq.push_back(link.hash);
44 }
45 }
46 _ => {}
47 };
48 }
49 Ok(())
50}
51
52#[inline(always)]
53pub fn cat_ipld_str(reader: &mut impl CarReader, cid: &str) -> Result<(), CarError> {
54 let cid = Cid::from_str(cid).map_err(|e| CarError::Parsing(e.to_string()))?;
55 cat_ipld(reader, cid)
56}
57
58pub fn cat_ipld(reader: &mut impl CarReader, file_cid: Cid) -> Result<(), CarError> {
59 let mut stdout = io::stdout();
60 let mut vecq = VecDeque::new();
61 vecq.push_back(file_cid);
62 ipld_write_inner(reader, &mut vecq, &mut stdout)
63}