rust_car/
writer.rs

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