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}