diff options
-rw-r--r-- | guide/src/chapter_01.md | 8 | ||||
-rw-r--r-- | guide/src/chapter_02.md | 8 | ||||
-rw-r--r-- | ipc/examples/gpg-agent-sign.rs | 2 | ||||
-rw-r--r-- | ipc/tests/gpg-agent.rs | 4 | ||||
-rw-r--r-- | openpgp-ffi/src/serialize.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/encrypt-for.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/generate-encrypt-decrypt.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/generate-sign-verify.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/notarize.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/pad.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/sign.rs | 2 | ||||
-rw-r--r-- | openpgp/examples/wrap-literal.rs | 2 | ||||
-rw-r--r-- | openpgp/src/autocrypt.rs | 3 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 2 | ||||
-rw-r--r-- | openpgp/src/serialize/padding.rs | 11 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 116 | ||||
-rw-r--r-- | tool/src/commands/mod.rs | 2 | ||||
-rw-r--r-- | tool/src/commands/sign.rs | 14 | ||||
-rw-r--r-- | tool/tests/sq-sign.rs | 2 |
19 files changed, 96 insertions, 92 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md index fcce2101..5c9d177f 100644 --- a/guide/src/chapter_01.md +++ b/guide/src/chapter_01.md @@ -61,7 +61,7 @@ fn main() { # let signer = Signer::new(message, keypair).build()?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(signer).build()?; # # // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; @@ -206,7 +206,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # let signer = Signer::new(message, keypair).build()?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(signer).build()?; # # // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; @@ -351,7 +351,7 @@ fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) let signer = Signer::new(message, keypair).build()?; // Emit a literal data packet. - let mut literal_writer = LiteralWriter::new(signer, None, None, None)?; + let mut literal_writer = LiteralWriter::new(signer).build()?; // Sign the data. literal_writer.write_all(plaintext.as_bytes())?; @@ -507,7 +507,7 @@ Verified data can be read from this using [`io::Read`]. # let signer = Signer::new(message, keypair).build()?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(signer).build()?; # # // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md index 3eb0fad5..d00fa669 100644 --- a/guide/src/chapter_02.md +++ b/guide/src/chapter_02.md @@ -68,7 +68,7 @@ fn main() { # None, None)?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(encryptor, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(encryptor).build()?; # # // Encrypt the data. # literal_writer.write_all(plaintext.as_bytes())?; @@ -209,7 +209,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # None, None)?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(encryptor, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(encryptor).build()?; # # // Encrypt the data. # literal_writer.write_all(plaintext.as_bytes())?; @@ -350,7 +350,7 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) None, None)?; // Emit a literal data packet. - let mut literal_writer = LiteralWriter::new(encryptor, None, None, None)?; + let mut literal_writer = LiteralWriter::new(encryptor).build()?; // Encrypt the data. literal_writer.write_all(plaintext.as_bytes())?; @@ -505,7 +505,7 @@ Decrypted data can be read from this using [`io::Read`]. # None, None)?; # # // Emit a literal data packet. -# let mut literal_writer = LiteralWriter::new(encryptor, None, None, None)?; +# let mut literal_writer = LiteralWriter::new(encryptor).build()?; # # // Encrypt the data. # literal_writer.write_all(plaintext.as_bytes())?; diff --git a/ipc/examples/gpg-agent-sign.rs b/ipc/examples/gpg-agent-sign.rs index c4b3d6c0..923657bd 100644 --- a/ipc/examples/gpg-agent-sign.rs +++ b/ipc/examples/gpg-agent-sign.rs @@ -63,7 +63,7 @@ fn main() { // Then, create a literal writer to wrap the data in a literal // message packet. - let mut literal = LiteralWriter::new(signer, None, None, None) + let mut literal = LiteralWriter::new(signer).build() .expect("Failed to create literal writer"); // Copy all the data. diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs index dab1fb74..2dd5bb2b 100644 --- a/ipc/tests/gpg-agent.rs +++ b/ipc/tests/gpg-agent.rs @@ -111,7 +111,7 @@ fn sign() { // Emit a literal data packet. let mut literal_writer = LiteralWriter::new( - signer, None, None, None).unwrap(); + signer).build().unwrap(); // Sign the data. literal_writer.write_all(MESSAGE.as_bytes()).unwrap(); @@ -225,7 +225,7 @@ fn decrypt() { // Emit a literal data packet. let mut literal_writer = LiteralWriter::new( - encryptor, None, None, None).unwrap(); + encryptor).build().unwrap(); // Encrypt the data. literal_writer.write_all(MESSAGE.as_bytes()).unwrap(); diff --git a/openpgp-ffi/src/serialize.rs b/openpgp-ffi/src/serialize.rs index 2b123673..7046b667 100644 --- a/openpgp-ffi/src/serialize.rs +++ b/openpgp-ffi/src/serialize.rs @@ -232,7 +232,7 @@ pub extern "C" fn pgp_literal_writer_new { ffi_make_fry_from_errp!(errp); let inner = ffi_param_move!(inner); - ffi_try_box!(LiteralWriter::new(*inner, None, None, None)) + ffi_try_box!(LiteralWriter::new(*inner).build()) } /// A recipient of an encrypted message. diff --git a/openpgp/examples/encrypt-for.rs b/openpgp/examples/encrypt-for.rs index 7b1f48e7..3076c7a4 100644 --- a/openpgp/examples/encrypt-for.rs +++ b/openpgp/examples/encrypt-for.rs @@ -56,7 +56,7 @@ fn main() { &recipients, None, None) .expect("Failed to create encryptor"); - let mut literal_writer = LiteralWriter::new(encryptor, None, None, None) + let mut literal_writer = LiteralWriter::new(encryptor).build() .expect("Failed to create literal writer"); // Copy stdin to our writer stack to encrypt the data. diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index f24eba1f..f8eeb05f 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -59,7 +59,7 @@ fn encrypt(sink: &mut dyn Write, plaintext: &str, recipient: &openpgp::TPK) None, None)?; // Emit a literal data packet. - let mut literal_writer = LiteralWriter::new(encryptor, None, None, None)?; + let mut literal_writer = LiteralWriter::new(encryptor).build()?; // Encrypt the data. literal_writer.write_all(plaintext.as_bytes())?; diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs index e22e5760..98e94f21 100644 --- a/openpgp/examples/generate-sign-verify.rs +++ b/openpgp/examples/generate-sign-verify.rs @@ -50,7 +50,7 @@ fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::TPK) let signer = Signer::new(message, keypair).build()?; // Emit a literal data packet. - let mut literal_writer = LiteralWriter::new(signer, None, None, None)?; + let mut literal_writer = LiteralWriter::new(signer).build()?; // Sign the data. literal_writer.write_all(plaintext.as_bytes())?; diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs index c627d4f1..d17aec44 100644 --- a/openpgp/examples/notarize.rs +++ b/openpgp/examples/notarize.rs @@ -87,7 +87,7 @@ fn main() { // Then, create a literal writer to wrap the data in a // literal message packet. let mut literal = - LiteralWriter::new(signer, None, None, None) + LiteralWriter::new(signer).build() .expect("Failed to create literal writer"); // Copy all the data. diff --git a/openpgp/examples/pad.rs b/openpgp/examples/pad.rs index eaaaeba8..76d4ebc0 100644 --- a/openpgp/examples/pad.rs +++ b/openpgp/examples/pad.rs @@ -62,7 +62,7 @@ fn main() { let padder = Padder::new(encryptor, padme) .expect("Failed to create padder"); - let mut literal_writer = LiteralWriter::new(padder, None, None, None) + let mut literal_writer = LiteralWriter::new(padder).build() .expect("Failed to create literal writer"); // Copy stdin to our writer stack to encrypt the data. diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs index 2304865f..523c9e26 100644 --- a/openpgp/examples/sign.rs +++ b/openpgp/examples/sign.rs @@ -64,7 +64,7 @@ fn main() { // Then, create a literal writer to wrap the data in a literal // message packet. - let mut literal = LiteralWriter::new(signer, None, None, None) + let mut literal = LiteralWriter::new(signer).build() .expect("Failed to create literal writer"); // Copy all the data. diff --git a/openpgp/examples/wrap-literal.rs b/openpgp/examples/wrap-literal.rs index d3eed376..567ba3b5 100644 --- a/openpgp/examples/wrap-literal.rs +++ b/openpgp/examples/wrap-literal.rs @@ -28,7 +28,7 @@ fn main() { // Then, create a literal writer to wrap the data in a literal // message packet. - let mut literal = LiteralWriter::new(message, None, None, None) + let mut literal = LiteralWriter::new(message).build() .expect("Failed to create literal writer"); // Copy all the data. diff --git a/openpgp/src/autocrypt.rs b/openpgp/src/autocrypt.rs index 93661166..4f7596bb 100644 --- a/openpgp/src/autocrypt.rs +++ b/openpgp/src/autocrypt.rs @@ -471,8 +471,7 @@ impl AutocryptSetupMessage { vec![ self.passcode.as_ref().unwrap() ], &[], None, None)?; - let mut w = LiteralWriter::new(w, None, - /* filename*/ None, /* date */ None)?; + let mut w = LiteralWriter::new(w).build()?; // The inner message is an ASCII-armored encoded TPK. let mut w = armor::Writer::new( diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index fff01171..e1678d10 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -1905,7 +1905,7 @@ mod test { let m = Message::new(&mut buf); let signer = Signer::new(m, keypair).build().unwrap(); - let mut ls = LiteralWriter::new(signer, None, None, None).unwrap(); + let mut ls = LiteralWriter::new(signer).build().unwrap(); ls.write_all(&mut vec![42u8; 30 * 1024 * 1024]).unwrap(); ls.finalize().unwrap(); diff --git a/openpgp/src/serialize/padding.rs b/openpgp/src/serialize/padding.rs index 0c9c4ee0..d30374a0 100644 --- a/openpgp/src/serialize/padding.rs +++ b/openpgp/src/serialize/padding.rs @@ -102,7 +102,7 @@ use crate::constants::{ /// let message = Message::new(&mut unpadded); /// // XXX: Insert Encryptor here. /// // XXX: Insert Signer here. -/// let mut w = LiteralWriter::new(message, None, None, None)?; +/// let mut w = LiteralWriter::new(message).build()?; /// w.write_all(b"Hello world.")?; /// w.finalize()?; /// } @@ -113,7 +113,7 @@ use crate::constants::{ /// // XXX: Insert Encryptor here. /// let padder = Padder::new(message, padme)?; /// // XXX: Insert Signer here. -/// let mut w = LiteralWriter::new(padder, None, None, None)?; +/// let mut w = LiteralWriter::new(padder).build()?; /// w.write_all(b"Hello world.")?; /// w.finalize()?; /// } @@ -341,9 +341,7 @@ mod test { { let message = Message::new(&mut padded); let padder = Padder::new(message, padme).unwrap(); - let mut w = - LiteralWriter::new(padder, None, None, None) - .unwrap(); + let mut w = LiteralWriter::new(padder).build().unwrap(); w.write_all(&msg).unwrap(); w.finalize().unwrap(); } @@ -366,8 +364,7 @@ mod test { { let message = Message::new(&mut padded); let padder = Padder::new(message, padme).unwrap(); - let mut w = LiteralWriter::new(padder, None, None, None) - .unwrap(); + let mut w = LiteralWriter::new(padder).build().unwrap(); w.write_all(MSG).unwrap(); w.finalize().unwrap(); } diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 38c14fa7..201df920 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -240,7 +240,7 @@ impl<'a> Signer<'a> { /// { /// let message = Message::new(&mut o); /// let signer = Signer::new(message, signing_keypair).build()?; - /// let mut ls = LiteralWriter::new(signer, None, None, None)?; + /// let mut ls = LiteralWriter::new(signer).build()?; /// ls.write_all(b"Make it so, number one!")?; /// ls.finalize()?; /// } @@ -544,7 +544,7 @@ impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { /// let mut o = vec![]; /// { /// let message = Message::new(&mut o); -/// let mut w = LiteralWriter::new(message, None, None, None)?; +/// let mut w = LiteralWriter::new(message).build()?; /// w.write_all(b"Hello world.")?; /// w.finalize()?; /// } @@ -553,47 +553,52 @@ impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { /// # } /// ``` pub struct LiteralWriter<'a> { + template: Literal, inner: writer::BoxStack<'a, Cookie>, signature_writer: Option<writer::BoxStack<'a, Cookie>>, } impl<'a> LiteralWriter<'a> { /// Creates a new literal writer. + pub fn new(inner: writer::Stack<'a, Cookie>) -> Self { + LiteralWriter { + template: Literal::new(DataFormat::default()), + inner: writer::BoxStack::from(inner), + signature_writer: None, + } + } + + /// Sets the data format. + pub fn format(mut self, format: DataFormat) -> Self { + self.template.set_format(format); + self + } + + /// Sets the filename. + /// + /// The standard does not specify the encoding. Filenames must + /// not be longer than 255 bytes. + pub fn filename<B: AsRef<[u8]>>(mut self, filename: B) -> Result<Self> { + self.template.set_filename_from_bytes(filename.as_ref())?; + Ok(self) + } + + /// Sets the data format. + pub fn date(mut self, timestamp: time::Tm) -> Result<Self> + { + self.template.set_date(Some(timestamp)); + Ok(self) + } + + /// Finalizes the literal writer, returning the writer stack. /// /// `format`, `filename`, and `date` will be emitted as part of /// the literal packets headers. Note that these headers will not /// be authenticated by signatures (but will be authenticated by a /// SEIP/MDC container), and are therefore unreliable and should /// not be trusted. - /// - /// If `date` is `None`, then the earliest representable time will - /// be used as a dummy value. - pub fn new<'f, D, F, T>(inner: writer::Stack<'a, Cookie>, - format: D, filename: F, date: T) - -> Result<writer::Stack<'a, Cookie>> - where D: Into<Option<DataFormat>>, - F: Into<Option<&'f [u8]>>, - T: Into<Option<time::Tm>> - { - Self::make(inner, - format.into().unwrap_or_default(), - filename.into(), date.into()) - } - - fn make(inner: writer::Stack<'a, Cookie>, - format: DataFormat, - filename: Option<&[u8]>, - date: Option<time::Tm>) - -> Result<writer::Stack<'a, Cookie>> { - let mut inner = writer::BoxStack::from(inner); - let level = inner.cookie_ref().level + 1; - - let mut template = Literal::new(format); - template.set_date(date); - - if let Some(f) = filename { - template.set_filename_from_bytes(f)?; - } + pub fn build(mut self) -> Result<writer::Stack<'a, Cookie>> { + let level = self.inner.cookie_ref().level + 1; // For historical reasons, signatures over literal data // packets only include the body without metadata or framing. @@ -604,35 +609,32 @@ impl<'a> LiteralWriter<'a> { if let &Cookie { private: Private::Signer{..}, .. - } = inner.cookie_ref() { + } = self.inner.cookie_ref() { true } else { false }; - let mut signature_writer = None; if signer_above { - let stack = inner.pop()?; + let stack = self.inner.pop()?; // We know a signer has an inner stackable. let stack = stack.unwrap(); - signature_writer = Some(inner); - inner = stack; + self.signature_writer = Some(self.inner); + self.inner = stack; } // Not hashed by the signature_writer (see above). - CTB::new(Tag::Literal).serialize(&mut inner)?; + CTB::new(Tag::Literal).serialize(&mut self.inner)?; // Neither is any framing added by the PartialBodyFilter. - let mut inner - = PartialBodyFilter::new(writer::Stack::from(inner), Cookie::new(level)); + self.inner + = PartialBodyFilter::new(writer::Stack::from(self.inner), + Cookie::new(level)).into(); // Nor the headers. - template.serialize_headers(&mut inner, false)?; + self.template.serialize_headers(&mut self.inner, false)?; - Ok(writer::Stack::from(Box::new(Self { - inner: inner.into(), - signature_writer: signature_writer, - }))) + Ok(writer::Stack::from(Box::new(self))) } } @@ -726,7 +728,7 @@ impl<'a> writer::Stackable<'a, Cookie> for LiteralWriter<'a> { /// let message = Message::new(&mut o); /// let w = Compressor::new(message, /// CompressionAlgorithm::Uncompressed, None)?; -/// let mut w = LiteralWriter::new(w, None, None, None)?; +/// let mut w = LiteralWriter::new(w).build()?; /// w.write_all(b"Hello world.")?; /// w.finalize()?; /// } @@ -966,7 +968,7 @@ impl<'a> Encryptor<'a> { /// &["совершенно секретно".into()], /// &recipients, None, None) /// .expect("Failed to create encryptor"); - /// let mut w = LiteralWriter::new(encryptor, None, None, None)?; + /// let mut w = LiteralWriter::new(encryptor).build()?; /// w.write_all(b"Hello world.")?; /// w.finalize()?; /// # Ok(()) @@ -1266,14 +1268,14 @@ mod test { let m = Message::new(&mut o); let c = Compressor::new( m, CompressionAlgorithm::Uncompressed, None).unwrap(); - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "one").unwrap(); let c = ls.finalize_one().unwrap().unwrap(); // Pop the LiteralWriter. - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "two").unwrap(); let c = ls.finalize_one().unwrap().unwrap(); // Pop the LiteralWriter. let c = c.finalize_one().unwrap().unwrap(); // Pop the Compressor. - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "three").unwrap(); } @@ -1327,19 +1329,19 @@ mod test { m, CompressionAlgorithm::Uncompressed, None).unwrap(); let c = Compressor::new( c0, CompressionAlgorithm::Uncompressed, None).unwrap(); - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "one").unwrap(); let c = ls.finalize_one().unwrap().unwrap(); - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "two").unwrap(); let c = ls.finalize_one().unwrap().unwrap(); let c0 = c.finalize_one().unwrap().unwrap(); let c = Compressor::new( c0, CompressionAlgorithm::Uncompressed, None).unwrap(); - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "three").unwrap(); let c = ls.finalize_one().unwrap().unwrap(); - let mut ls = LiteralWriter::new(c, T, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).format(T).build().unwrap(); write!(ls, "four").unwrap(); } @@ -1363,7 +1365,7 @@ mod test { let m = Message::new(&mut o); let c = Compressor::new(m, CompressionAlgorithm::BZip2, None).unwrap(); - let mut ls = LiteralWriter::new(c, None, None, None).unwrap(); + let mut ls = LiteralWriter::new(c).build().unwrap(); // Write 64 megabytes of zeroes. for _ in 0 .. 16 { ls.write_all(&zeros).unwrap(); @@ -1402,7 +1404,7 @@ mod test { signer = signer.add_signer(s); } let signer = signer.build().unwrap(); - let mut ls = LiteralWriter::new(signer, None, None, None).unwrap(); + let mut ls = LiteralWriter::new(signer).build().unwrap(); ls.write_all(b"Tis, tis, tis. Tis is important.").unwrap(); let signer = ls.finalize_one().unwrap().unwrap(); let _ = signer.finalize_one().unwrap().unwrap(); @@ -1439,7 +1441,7 @@ mod test { m, &passwords, &[], None, None) .unwrap(); - let mut literal = LiteralWriter::new(encryptor, None, None, None) + let mut literal = LiteralWriter::new(encryptor).build() .unwrap(); literal.write_all(message).unwrap(); } @@ -1627,7 +1629,7 @@ mod test { let encryptor = Encryptor::new( m, &[], &recipients, None, AEADAlgorithm::EAX) .unwrap(); - let mut literal = LiteralWriter::new(encryptor, None, None, None) + let mut literal = LiteralWriter::new(encryptor).build() .unwrap(); literal.write_all(&content).unwrap(); // literal.finalize().unwrap(); diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs index f651756b..3e41b562 100644 --- a/tool/src/commands/mod.rs +++ b/tool/src/commands/mod.rs @@ -158,7 +158,7 @@ pub fn encrypt(mapping: &mut store::Mapping, sink = signer.build()?; } - let mut literal_writer = LiteralWriter::new(sink, None, None, None) + let mut literal_writer = LiteralWriter::new(sink).build() .context("Failed to create literal writer")?; // Finally, copy stdin to our writer stack to encrypt the data. diff --git a/tool/src/commands/sign.rs b/tool/src/commands/sign.rs index 51b098b7..59b1a3c1 100644 --- a/tool/src/commands/sign.rs +++ b/tool/src/commands/sign.rs @@ -109,7 +109,7 @@ fn sign_data(input: &mut dyn io::Read, output_path: Option<&str>, signer } else { // We want to wrap the data in a literal data packet. - LiteralWriter::new(signer, None, None, None) + LiteralWriter::new(signer).build() .context("Failed to create literal writer")? }; @@ -238,9 +238,15 @@ fn sign_message(input: &mut dyn io::Read, output_path: Option<&str>, }; / |