ipld_nostd/car/
writer.rs

1use {
2	super::{error::Error, header::CarHeader, util::write_varint_usize},
3	crate::cid::Cid,
4	alloc::vec::Vec,
5	core2::io::Write,
6};
7
8#[derive(Debug)]
9pub struct CarWriter<W> {
10	header: CarHeader,
11	writer: W,
12	cid_buffer: Vec<u8>,
13	is_header_written: bool,
14}
15
16impl<W> CarWriter<W>
17where
18	W: Write + Send + Unpin,
19{
20	pub fn new(header: CarHeader, writer: W) -> Self {
21		CarWriter {
22			header,
23			writer,
24			cid_buffer: Vec::new(),
25			is_header_written: false,
26		}
27	}
28
29	/// Forces the header to be written. Also called implicitly by `write`.
30	///
31	/// Returns the bytes written in this operation.
32	pub fn write_header(&mut self) -> Result<usize, Error> {
33		let mut written = 0;
34
35		if !self.is_header_written {
36			// Write header bytes
37			let header_bytes = self.header.encode()?;
38			written += write_varint_usize(header_bytes.len(), &mut self.writer)?;
39			self.writer.write_all(&header_bytes)?;
40			written += header_bytes.len();
41			self.is_header_written = true;
42		}
43
44		Ok(written)
45	}
46
47	/// Writes header and stream of data to writer in Car format.
48	///
49	/// Returns the bytes written in this operation.
50	pub fn write<T>(&mut self, cid: Cid, data: T) -> Result<usize, Error>
51	where
52		T: AsRef<[u8]>,
53	{
54		let mut written = 0;
55		written += self.write_header()?;
56
57		// Write the given block.
58		self.cid_buffer.clear();
59		cid.write_bytes(&mut self.cid_buffer).expect("vec write");
60
61		let data = data.as_ref();
62		let len = self.cid_buffer.len() + data.len();
63
64		written += write_varint_usize(len, &mut self.writer)?;
65		self.writer.write_all(&self.cid_buffer)?;
66		self.writer.write_all(data)?;
67		written += self.cid_buffer.len();
68		written += data.len();
69
70		Ok(written)
71	}
72
73	/// Finishes writing, including flushing and returns the writer.
74	pub fn finish(mut self) -> Result<W, Error> {
75		self.flush()?;
76		Ok(self.writer)
77	}
78
79	/// Flushes the underlying writer.
80	pub fn flush(&mut self) -> Result<(), Error> {
81		self.writer.flush()?;
82		Ok(())
83	}
84
85	/// Consumes the [`CarWriter`] and returns the underlying writer.
86	pub fn into_inner(self) -> W {
87		self.writer
88	}
89}