blockless_car/
writer.rs

1use cid::Cid;
2use ipld::{pb::DagPbCodec, prelude::Codec};
3
4use crate::{
5    error::CarError,
6    utils::{empty_pb_cid, pb_cid},
7    CarHeader, Ipld,
8};
9
10mod writer_v1;
11pub(crate) use writer_v1::CarWriterV1;
12
13pub enum WriteStream<'bs> {
14    Bytes(&'bs [u8]),
15    End,
16}
17
18pub trait CarWriter {
19    fn write_block<T>(&mut self, cid: Cid, data: T) -> Result<(), CarError>
20    where
21        T: AsRef<[u8]>;
22
23    fn stream_block<F, R>(
24        &mut self,
25        cid_f: F,
26        stream_len: usize,
27        r: &mut R,
28    ) -> Result<Cid, CarError>
29    where
30        R: std::io::Read + std::io::Seek,
31        F: FnMut(WriteStream) -> Option<Result<Cid, CarError>>;
32
33    fn write_ipld(&mut self, ipld: Ipld, hasher_codec: multicodec::Codec) -> Result<Cid, CarError> {
34        match ipld {
35            Ipld::Bytes(buf) => {
36                let file_cid = crate::utils::raw_cid(&buf, hasher_codec);
37                self.write_block(file_cid, &buf)?;
38                Ok(file_cid)
39            }
40            fs_ipld @ ipld::Ipld::Map(_) => {
41                let bs: Vec<u8> = DagPbCodec
42                    .encode(&fs_ipld)
43                    .map_err(|e| CarError::Parsing(e.to_string()))?;
44                let cid = pb_cid(&bs, hasher_codec);
45                self.write_block(cid, &bs)?;
46                Ok(cid)
47            }
48            _ => Err(CarError::Parsing("Not support write ipld.".to_lowercase())),
49        }
50    }
51
52    fn rewrite_header(&mut self, header: CarHeader) -> Result<(), CarError>;
53
54    fn flush(&mut self) -> Result<(), CarError>;
55}
56
57pub fn new_v1<W>(inner: W, header: CarHeader) -> Result<impl CarWriter, CarError>
58where
59    W: std::io::Write + std::io::Seek,
60{
61    Ok(CarWriterV1::new(inner, header))
62}
63
64pub fn new_v1_default_roots<W>(
65    inner: W,
66    hasher_codec: multicodec::Codec,
67) -> Result<impl CarWriter, CarError>
68where
69    W: std::io::Write + std::io::Seek,
70{
71    Ok(CarWriterV1::new(
72        inner,
73        CarHeader::new_v1(vec![empty_pb_cid(hasher_codec)]),
74    ))
75}