diff --git a/Cargo.toml b/Cargo.toml index 2fca7c7..16a458e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ mp1-mp2 = [] nightly-docs = [] # internal simd = [] std = [] +new-boxed = ["std"] [package.metadata.docs.rs] features = ["nightly-docs", "std"] diff --git a/README.md b/README.md index e83ac57..611f7be 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,4 @@ https://github.com/rust-lang/cargo/issues/4328#issuecomment-652075026).** - `mp1-mp2`: Includes MP1 and MP2 decoding code. - `simd` *(default)*: Enables handwritten SIMD optimizations on eligible targets. - `std`: Adds things that require `std`, +- `new-boxed`: Adds RawDecoder::new_boxed. Requires nightly and `std`. diff --git a/src/lib.rs b/src/lib.rs index 743fe29..a8c9afd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ #![cfg_attr(feature = "nightly-docs", feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "new-boxed", feature(new_uninit))] #[doc(hidden)] pub mod ffi; @@ -188,6 +189,7 @@ pub struct DecoderOwned { /// # Ok(()) /// # } /// ``` +#[repr(transparent)] pub struct RawDecoder(MaybeUninit); /// Conditional type used to represent one PCM sample in output data. @@ -374,6 +376,19 @@ impl RawDecoder { Self(decoder) } + /// Construct a new `RawDecoder` on the heap without copying from the stack. + /// + /// Currently requires nightly. + #[cfg(feature = "new-boxed")] + pub fn new_boxed() -> Box { + let mut decoder: Box> = Box::new_uninit(); + unsafe { + ffi::mp3dec_init(decoder.as_mut_ptr()); + } + let ptr = Box::into_raw(decoder) as *mut RawDecoder; + unsafe { Box::from_raw(ptr) } + } + /// Reads the next frame, skipping over potential garbage data. /// /// If the frame contains audio data, [`samples`](Audio::samples) should be used