diff --git a/reference-impl/rust/star-lite/src/encode.rs b/reference-impl/rust/star-lite/src/encode.rs index 57b91e0..ae43d0f 100644 --- a/reference-impl/rust/star-lite/src/encode.rs +++ b/reference-impl/rust/star-lite/src/encode.rs @@ -21,11 +21,35 @@ where I: IntoIterator)>, K: AsRef, { - let partial = commit.to_partial_bytes()?; - let mut w = Writer::new(output); - w.write_header(commit.data, Some(&partial))?; + let mut builder = ArchiveBuilder::new(output, commit)?; for (k, v) in entries { - w.write_entry(k.as_ref(), &v)?; + builder.add_entry(k.as_ref(), &v)?; + } + builder.finish() +} + +/// Encode a STAR-lite archive into `output` like [`encode_archive`], but with a +/// push-style interface that works better for fallible content sources and +/// sinks +pub struct ArchiveBuilder { + writer: Writer, +} + +impl ArchiveBuilder { + /// start an archive write from the header + partial commit + pub fn new(output: W, commit: &Commit) -> Result { + let partial = commit.to_partial_bytes()?; + let mut writer = Writer::new(output); + writer.write_header(commit.data, Some(&partial))?; + Ok(Self { writer }) + } + + /// append one record, in strict key-ascending order + pub fn add_entry(&mut self, key: &str, record: &[u8]) -> Result<()> { + self.writer.write_entry(key, record) + } + + pub fn finish(self) -> Result<()> { + self.writer.finish() } - w.finish() }