blockless_car/utils/
ls.rs1use std::collections::{HashMap, VecDeque};
2
3use cid::Cid;
4use ipld::raw::RawCodec;
5
6use crate::{
7 error::CarError,
8 reader::CarReader,
9 unixfs::{FileType, UnixFs},
10 Ipld,
11};
12
13fn walk<F>(
15 vecq: &mut VecDeque<Cid>,
16 reader: &mut impl CarReader,
17 list_f: &F,
18) -> Result<(), CarError>
19where
20 F: Fn(&Cid, &str),
21{
22 let mut cache: HashMap<Cid, String> = HashMap::new();
23 let raw_code: u64 = RawCodec.into();
24 while let Some(file_cid) = vecq.pop_front() {
25 let codec = file_cid.codec();
26 let file_n = cache
27 .get(&file_cid)
28 .map_or(file_cid.to_string(), |c| c.to_string());
29 list_f(&file_cid, &file_n);
30 if codec == raw_code {
33 continue;
34 }
35 let file_ipld: Ipld = reader.ipld(&file_cid)?;
36 if let m @ Ipld::Map(_) = file_ipld {
37 let unixfs: UnixFs = m.try_into()?;
38 match unixfs.file_type() {
39 FileType::Directory => {}
40 _ => continue,
41 }
42 for n in unixfs.links().into_iter() {
43 let cid = n.hash;
44 cache.insert(cid, file_n.clone() + "/" + &n.name);
45 vecq.push_back(cid);
46 }
47 }
48 }
49 Ok(())
50}
51
52pub fn list(reader: &mut impl CarReader) -> Result<(), CarError> {
54 list_call(reader, |_, file_n| println!("{file_n}"))
55}
56
57pub fn list_cid(reader: &mut impl CarReader) -> Result<(), CarError> {
59 list_call(reader, |cid, _| println!("{cid}"))
60}
61
62pub fn list_call<F>(reader: &mut impl CarReader, list_f: F) -> Result<(), CarError>
66where
67 F: Fn(&Cid, &str),
68{
69 let roots = reader.header().roots();
70 let mut queue: VecDeque<Cid> = VecDeque::new();
71 for r in roots.iter() {
72 queue.push_front(*r);
73 walk(&mut queue, reader, &list_f)?;
74 }
75 Ok(())
76}