From aefae6aa2e6a20378a03b72ec83b5d6c6a13bb8f Mon Sep 17 00:00:00 2001 From: Jack Lavigne Date: Fri, 29 Dec 2023 15:27:58 -0500 Subject: [PATCH] feat: add into_inner for writer --- Cargo.lock | 58 ++++++++++----------- src/write.rs | 140 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 127 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad05d28..388d4f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,98 +1,100 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + [[package]] name = "alsa-sys" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9013f855a808ab924a4c08b5c1ec9bd6b04fdb2295b4d570fb723e0ed2802a4f" dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "pkg-config", ] [[package]] name = "bitflags" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" [[package]] name = "coreaudio-rs" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f97dd1cb4381fc1d3a80f2c63ce965c4c936befe7051fd33289a2dc45914bda" dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "coreaudio-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "coreaudio-sys", + "libc", ] [[package]] name = "coreaudio-sys" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31231897622a4cd14cb211af6f26d6fcf0c78078fa60c586ce9db8f0b581cd44" dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "cpal" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989df64d59c65f18776046436c3e50964699ec789e76b1af04f6fc32b6a2b713" dependencies = [ - "alsa-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "coreaudio-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "alsa-sys", + "coreaudio-rs", + "lazy_static", + "libc", + "ole32-sys", + "winapi", ] [[package]] name = "hound" version = "3.4.0" dependencies = [ - "cpal 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cpal", ] [[package]] name = "lazy_static" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" [[package]] name = "libc" version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" [[package]] name = "ole32-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", + "winapi-build", ] [[package]] name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum alsa-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9013f855a808ab924a4c08b5c1ec9bd6b04fdb2295b4d570fb723e0ed2802a4f" -"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" -"checksum coreaudio-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f97dd1cb4381fc1d3a80f2c63ce965c4c936befe7051fd33289a2dc45914bda" -"checksum coreaudio-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31231897622a4cd14cb211af6f26d6fcf0c78078fa60c586ce9db8f0b581cd44" -"checksum cpal 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "989df64d59c65f18776046436c3e50964699ec789e76b1af04f6fc32b6a2b713" -"checksum lazy_static 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" -"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" -"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/write.rs b/src/write.rs index db04287..4561454 100644 --- a/src/write.rs +++ b/src/write.rs @@ -237,7 +237,7 @@ impl ChunkWritingState { /// For simple out-of-the-box wav usage, prefer the `WavWriter` facade. pub struct ChunksWriter { /// underlying writer - writer: W, + writer: Option, /// wave spec, if known at that point pub spec_ex: Option, /// state of the data chunk, if currently writing it @@ -254,7 +254,7 @@ impl ChunksWriter { pub fn new(mut writer: W) -> Result> { try!(writer.write_all(b"RIFF\0\0\0\0WAVE")); Ok(ChunksWriter { - writer: writer, + writer: Some(writer), spec_ex: None, dirty: false, data_state: None, @@ -266,10 +266,14 @@ impl ChunksWriter { /// /// The writer is then repositioned at end of file. fn update_riff_header(&mut self) -> io::Result<()> { - let full_len = try!(self.writer.seek(io::SeekFrom::Current(0))); - try!(self.writer.seek(io::SeekFrom::Start(4))); - try!(self.writer.write_le_u32(full_len as u32 - 8)); - try!(self.writer.seek(io::SeekFrom::Current(full_len as i64 - 8))); + if let Some(writer) = &mut self.writer { + let full_len = try!(writer.seek(io::SeekFrom::Current(0))); + try!(writer.seek(io::SeekFrom::Start(4))); + try!(writer.write_le_u32(full_len as u32 - 8)); + try!(writer.seek(io::SeekFrom::Current(full_len as i64 - 8))); + } else { + panic!("Writer is not available"); + } Ok(()) } @@ -286,9 +290,13 @@ impl ChunksWriter { fn update_data_chunk_header(&mut self) -> Result<()> { let data_state = self.data_state.expect("Should only be called in data chunk"); let spec_ex = self.spec_ex.expect("Data chunk implies known format"); - try!(self.writer.seek(io::SeekFrom::End(-(data_state.len as i64 + 4)))); - try!(self.writer.write_le_u32(data_state.len)); - try!(self.writer.seek(io::SeekFrom::End(0))); + if let Some(writer) = &mut self.writer { + try!(writer.seek(io::SeekFrom::End(-(data_state.len as i64 + 4)))); + try!(writer.write_le_u32(data_state.len)); + try!(writer.seek(io::SeekFrom::End(0))); + } else { + panic!("Writer is not available"); + } // Signal error if the last sample was not finished, but do so after // everything has been written, so that no data is lost, even though @@ -306,13 +314,19 @@ impl ChunksWriter { /// The function returns an `EmbeddedWriter` that must be used to write /// the chunk content. It will take care of maintaining the chunk length in /// the chunk header. - pub fn start_chunk(&mut self, fourcc:[u8;4]) -> Result> { + pub fn start_chunk(&mut self, fourcc: [u8; 4]) -> Result> { self.data_state = None; self.dirty = true; - try!(self.writer.write_all(&fourcc)); - try!(self.writer.write_le_u32(0)); + + if let Some(writer) = &mut self.writer { + try!(writer.write_all(&fourcc)); + try!(writer.write_le_u32(0)); + } else { + panic!("Writer is not available"); + } + Ok(EmbeddedWriter { - writer: &mut self.writer, + writer: self.writer.as_mut().unwrap(), // Safe to unwrap here after the check above state: ChunkWritingState { len: 0 }, finalized: false, }) @@ -323,8 +337,13 @@ impl ChunksWriter { if self.spec_ex.is_none() { panic!("Format must be written before data"); } - try!(self.writer.write_all(b"data")); - try!(self.writer.write_le_u32(0)); + if let Some(writer) = &mut self.writer { + try!(writer.write_all(b"data")); + try!(writer.write_le_u32(0)); + } else { + panic!("Writer is not available"); + } + self.data_state = Some(ChunkWritingState { len: 0 }); self.dirty = true; Ok(()) @@ -348,7 +367,11 @@ impl ChunksWriter { /// header and the data chunk header if required. pub fn flush(&mut self) -> Result<()> { try!(self.update_headers()); - try!(self.writer.flush()); + if let Some(writer) = &mut self.writer { + try!(writer.flush()); + } else { + panic!("Writer is not available"); + } Ok(()) } @@ -396,20 +419,24 @@ impl ChunksWriter { } let mut header = [0u8; 48]; - try!(self.writer.write(b"fmt ")); - let written = { - let mut buffer = io::Cursor::new(&mut header[..]); - match fmt_kind { - FmtKind::PcmWaveFormat => { - try!(Self::write_pcmwaveformat(spec_ex, &mut buffer)); + if let Some(writer) = &mut self.writer { + try!(writer.write(b"fmt ")); + let written = { + let mut buffer = io::Cursor::new(&mut header[..]); + match fmt_kind { + FmtKind::PcmWaveFormat => { + try!(Self::write_pcmwaveformat(spec_ex, &mut buffer)); + } + FmtKind::WaveFormatExtensible => { + try!(Self::write_waveformatextensible(spec_ex, &mut buffer)); + } } - FmtKind::WaveFormatExtensible => { - try!(Self::write_waveformatextensible(spec_ex, &mut buffer)); - } - } - buffer.position() - }; - try!(self.writer.write_all(&header[..written as usize])); + buffer.position() + }; + try!(writer.write_all(&header[..written as usize])); + } else { + panic!("Writer is not available"); + } self.spec_ex = Some(spec_ex); @@ -533,11 +560,15 @@ impl ChunksWriter { #[inline] pub fn write_sample(&mut self, sample: S) -> Result<()> { let spec_ex = self.spec_ex.expect("Format should have written before this call"); - try!(sample.write_padded( - &mut self.writer, - spec_ex.spec.bits_per_sample, - spec_ex.bytes_per_sample - )); + if let Some(writer) = &mut self.writer { + try!(sample.write_padded( + writer, + spec_ex.spec.bits_per_sample, + spec_ex.bytes_per_sample + )); + } else { + panic!("Writer is not available"); + } let written = spec_ex.bytes_per_sample as u32; self.data_state.as_mut().expect("Can only be called positioned in data chunk").len += written; Ok(()) @@ -583,19 +614,37 @@ impl ChunksWriter { self.sample_writer_buffer = new_buffer; } - SampleWriter16 { - writer: &mut self.writer, - buffer: &mut self.sample_writer_buffer[..num_bytes], - data_bytes_written: - &mut self.data_state.as_mut().expect("Can only be called positioned in data chunk").len, - index: 0, + if let Some(writer) = &mut self.writer { + SampleWriter16 { + writer, + buffer: &mut self.sample_writer_buffer[..num_bytes], + data_bytes_written: + &mut self.data_state.as_mut().expect("Can only be called positioned in data chunk").len, + index: 0, + } + } else { + panic!("Writer is not available"); } } + + /// Destroys the `WavWriter` and returns the underlying writer. + pub fn into_inner(mut self) -> W { + // Flush the writer before taking (since drop will have a None writer) + if let Some(_) = &mut self.writer { + let _ = self.flush(); + } else { + panic!("Writer is not available"); + } + + self.writer.take().expect("ChunksWriter has no writer") + } } impl Drop for ChunksWriter { fn drop(&mut self) { - let _ = self.flush(); + if let Some(writer) = &mut self.writer { + let _ = self.flush(); + } } } @@ -747,6 +796,11 @@ impl WavWriter let writer_state = self.writer.data_state.expect("ChunkWriter in weird state"); writer_state.len / spec_ex.bytes_per_sample as u32 } + + /// Destroys the `WavWriter` and returns the underlying writer. + pub fn into_inner(self) -> W { + self.writer.into_inner() + } } /// Reads the relevant parts of the header required to support append. @@ -835,7 +889,7 @@ impl WavWriter> { let writer = WavWriter { writer: ChunksWriter { spec_ex: Some(spec_ex), - writer: buf_writer, + writer: Some(buf_writer), sample_writer_buffer: Vec::new(), dirty: true, data_state: Some(ChunkWritingState { len: data_len }), @@ -865,7 +919,7 @@ impl WavWriter where W: io::Read + io::Write + io::Seek { let writer = WavWriter { writer: ChunksWriter { spec_ex: Some(spec_ex), - writer: writer, + writer: Some(writer), sample_writer_buffer: Vec::new(), dirty: true, data_state: Some(ChunkWritingState { len: data_len }),