Skip to content

Commit 151a7a2

Browse files
authored
fix: minimal build with no default features (#731)
* fix: add unreachable variant to DecoderImpl for no enabled decoders Co-authored-by: @renski-dev * fix: testing and compilation of tests and examples with no default features * fix: remove feature gates from FLAC duration checks * ci: check absolutely minimal build to prevent regression
1 parent 62c06fb commit 151a7a2

File tree

9 files changed

+203
-37
lines changed

9 files changed

+203
-37
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: CI
33
on:
44
pull_request:
55
push:
6-
branches: [ main, master ]
6+
branches: [main, master]
77

88
env:
99
RUSTFLAGS: "-C debuginfo=0 -D warnings"
@@ -18,8 +18,8 @@ jobs:
1818
strategy:
1919
fail-fast: false
2020
matrix:
21-
os: [ macos-latest, windows-latest, ubuntu-latest ]
22-
toolchain: [ stable, beta, nightly ]
21+
os: [macos-latest, windows-latest, ubuntu-latest]
22+
toolchain: [stable, beta, nightly]
2323
include:
2424
- os: macos-latest
2525
MACOS: true
@@ -49,6 +49,5 @@ jobs:
4949
# `cargo test` does not check benchmarks and `cargo test --all-targets` excludes
5050
# documentation tests. Therefore, we need an additional docs test command here.
5151
- run: cargo test --doc
52-
# Check minimal build. `tests/seek.rs` fails if there are no decoders at all,
53-
# adding one to make the tests check pass.
54-
- run: cargo check --tests --lib --no-default-features --features mp3
52+
# Check minimal build.
53+
- run: cargo check --tests --lib --no-default-features

Cargo.toml

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ minimp3_fixed = { version = "0.5.4", optional = true }
1919
symphonia = { version = "0.5.4", optional = true, default-features = false }
2020
crossbeam-channel = { version = "0.5.15", optional = true }
2121

22-
rand = { version = "0.9.0", features = ["small_rng", "os_rng"], optional = true }
22+
rand = { version = "0.9.0", features = [
23+
"small_rng",
24+
"os_rng",
25+
], optional = true }
2326
tracing = { version = "0.1.40", optional = true }
2427

2528
atomic_float = { version = "1.1.0", optional = true }
@@ -72,27 +75,91 @@ divan = "0.1.14"
7275
[[bench]]
7376
name = "effects"
7477
harness = false
78+
required-features = ["wav"]
7579

7680
[[bench]]
7781
name = "conversions"
7882
harness = false
83+
required-features = ["wav"]
7984

8085
[[bench]]
8186
name = "resampler"
8287
harness = false
88+
required-features = ["wav"]
8389

8490
[[bench]]
8591
name = "pipeline"
8692
harness = false
93+
required-features = ["wav"]
94+
95+
[[example]]
96+
name = "automatic_gain_control"
97+
required-features = ["playback", "flac"]
98+
99+
[[example]]
100+
name = "basic"
101+
required-features = ["playback", "vorbis"]
102+
103+
[[example]]
104+
name = "callback_on_end"
105+
required-features = ["playback", "wav"]
106+
107+
[[example]]
108+
name = "custom_config"
109+
required-features = ["playback", "wav"]
110+
111+
[[example]]
112+
name = "error_callback"
113+
required-features = ["playback"]
114+
115+
[[example]]
116+
name = "into_file"
117+
required-features = ["mp3", "wav"]
118+
119+
[[example]]
120+
name = "low_pass"
121+
required-features = ["playback", "wav"]
122+
123+
[[example]]
124+
name = "mix_multiple_sources"
125+
required-features = ["playback"]
87126

88127
[[example]]
89128
name = "music_m4a"
90-
required-features = ["symphonia-isomp4", "symphonia-aac"]
129+
required-features = ["playback", "symphonia-isomp4", "symphonia-aac"]
130+
131+
[[example]]
132+
name = "music_mp3"
133+
required-features = ["playback", "mp3"]
134+
135+
[[example]]
136+
name = "music_ogg"
137+
required-features = ["playback", "vorbis"]
138+
139+
[[example]]
140+
name = "music_wav"
141+
required-features = ["playback", "wav"]
91142

92143
[[example]]
93144
name = "noise_generator"
94-
required-features = ["noise"]
145+
required-features = ["playback", "noise"]
95146

96147
[[example]]
97-
name = "into_file"
98-
required-features = ["wav", "mp3"]
148+
name = "reverb"
149+
required-features = ["playback", "vorbis"]
150+
151+
[[example]]
152+
name = "seek_mp3"
153+
required-features = ["playback", "mp3"]
154+
155+
[[example]]
156+
name = "signal_generator"
157+
required-features = ["playback"]
158+
159+
[[example]]
160+
name = "spatial"
161+
required-features = ["playback", "vorbis"]
162+
163+
[[example]]
164+
name = "stereo"
165+
required-features = ["playback", "vorbis"]

examples/noise_generator.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::error::Error;
44

5-
#[cfg(feature = "noise")]
65
fn main() -> Result<(), Box<dyn Error>> {
76
use rodio::source::{pink, white, Source};
87
use std::thread;
@@ -29,9 +28,3 @@ fn main() -> Result<(), Box<dyn Error>> {
2928

3029
Ok(())
3130
}
32-
33-
#[cfg(not(feature = "noise"))]
34-
fn main() {
35-
println!("rodio has not been compiled with noise sources, use `--features noise` to enable this feature.");
36-
println!("Exiting...");
37-
}

src/decoder/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,14 @@ enum DecoderImpl<R: Read + Seek> {
119119
Mp3(mp3::Mp3Decoder<R>),
120120
#[cfg(feature = "symphonia")]
121121
Symphonia(symphonia::SymphoniaDecoder, PhantomData<R>),
122+
// This variant is here just to satisfy the compiler when there are no decoders enabled.
123+
// It is unreachable and should never be constructed.
124+
#[allow(dead_code)]
125+
None(Unreachable, PhantomData<R>),
122126
}
123127

128+
enum Unreachable {}
129+
124130
impl<R: Read + Seek> DecoderImpl<R> {
125131
#[inline]
126132
fn next(&mut self) -> Option<Sample> {
@@ -135,6 +141,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
135141
DecoderImpl::Mp3(source) => source.next(),
136142
#[cfg(feature = "symphonia")]
137143
DecoderImpl::Symphonia(source, PhantomData) => source.next(),
144+
DecoderImpl::None(_, _) => unreachable!(),
138145
}
139146
}
140147

@@ -151,6 +158,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
151158
DecoderImpl::Mp3(source) => source.size_hint(),
152159
#[cfg(feature = "symphonia")]
153160
DecoderImpl::Symphonia(source, PhantomData) => source.size_hint(),
161+
DecoderImpl::None(_, _) => unreachable!(),
154162
}
155163
}
156164

@@ -167,6 +175,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
167175
DecoderImpl::Mp3(source) => source.current_span_len(),
168176
#[cfg(feature = "symphonia")]
169177
DecoderImpl::Symphonia(source, PhantomData) => source.current_span_len(),
178+
DecoderImpl::None(_, _) => unreachable!(),
170179
}
171180
}
172181

@@ -183,6 +192,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
183192
DecoderImpl::Mp3(source) => source.channels(),
184193
#[cfg(feature = "symphonia")]
185194
DecoderImpl::Symphonia(source, PhantomData) => source.channels(),
195+
DecoderImpl::None(_, _) => unreachable!(),
186196
}
187197
}
188198

@@ -199,6 +209,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
199209
DecoderImpl::Mp3(source) => source.sample_rate(),
200210
#[cfg(feature = "symphonia")]
201211
DecoderImpl::Symphonia(source, PhantomData) => source.sample_rate(),
212+
DecoderImpl::None(_, _) => unreachable!(),
202213
}
203214
}
204215

@@ -221,6 +232,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
221232
DecoderImpl::Mp3(source) => source.total_duration(),
222233
#[cfg(feature = "symphonia")]
223234
DecoderImpl::Symphonia(source, PhantomData) => source.total_duration(),
235+
DecoderImpl::None(_, _) => unreachable!(),
224236
}
225237
}
226238

@@ -237,6 +249,7 @@ impl<R: Read + Seek> DecoderImpl<R> {
237249
DecoderImpl::Mp3(source) => source.try_seek(pos),
238250
#[cfg(feature = "symphonia")]
239251
DecoderImpl::Symphonia(source, PhantomData) => source.try_seek(pos),
252+
DecoderImpl::None(_, _) => unreachable!(),
240253
}
241254
}
242255
}

src/lib.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
//!
1313
//! Here is a complete example of how you would play an audio file:
1414
//!
15-
//! ```no_run
15+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
16+
#![cfg_attr(feature = "playback", doc = "```no_run")]
1617
//! use std::fs::File;
1718
//! use rodio::{Decoder, OutputStream, source::Source};
1819
//!
@@ -34,7 +35,8 @@
3435
//! ```
3536
//!
3637
//! [`rodio::play()`](crate::play) helps to simplify the above
37-
//! ```no_run
38+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
39+
#![cfg_attr(feature = "playback", doc = "```no_run")]
3840
//! use std::fs::File;
3941
//! use std::io::BufReader;
4042
//! use rodio::{Decoder, OutputStream, source::Source};
@@ -63,7 +65,8 @@
6365
//! To play a soung Create a [`Sink`] connect it to the output stream,
6466
//! and [`.append()`](Sink::append) your sound to it.
6567
//!
66-
//! ```no_run
68+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
69+
#![cfg_attr(feature = "playback", doc = "```no_run")]
6770
//! use std::time::Duration;
6871
//! use rodio::{OutputStream, Sink};
6972
//! use rodio::source::{SineWave, Source};
@@ -96,7 +99,8 @@
9699
//!
97100
//! Example:
98101
//!
99-
//! ```
102+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
103+
#![cfg_attr(feature = "playback", doc = "```")]
100104
//! use rodio::Source;
101105
//! use std::time::Duration;
102106
//!
@@ -147,7 +151,15 @@
147151
//! on the number of sinks that can be created (except for the fact that creating too many will slow
148152
//! down your program).
149153
150-
#![cfg_attr(test, deny(missing_docs))]
154+
#![cfg_attr(
155+
any(test, not(feature = "playback")),
156+
deny(missing_docs),
157+
allow(dead_code),
158+
allow(unused_imports),
159+
allow(unused_variables),
160+
allow(unreachable_code)
161+
)]
162+
151163
#[cfg(feature = "playback")]
152164
pub use cpal::{
153165
self, traits::DeviceTrait, Device, Devices, DevicesError, InputDevices, OutputDevices,

src/source/speed.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! To speed up a source from sink all you need to do is call the `set_speed(factor: f32)` function
1212
//! For example, here is how you speed up your sound by using sink or playing raw:
1313
//!
14-
//! ```no_run
14+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
15+
#![cfg_attr(feature = "playback", doc = "```no_run")]
1516
//!# use std::fs::File;
1617
//!# use rodio::{Decoder, Sink, OutputStream, source::{Source, SineWave}};
1718
//!
@@ -28,7 +29,8 @@
2829
//! std::thread::sleep(std::time::Duration::from_secs(5));
2930
//! ```
3031
//! Here is how you would do it using the sink:
31-
//!```no_run
32+
#![cfg_attr(not(feature = "playback"), doc = "```ignore")]
33+
#![cfg_attr(feature = "playback", doc = "```no_run")]
3234
//! use rodio::source::{Source, SineWave};
3335
//! let source = SineWave::new(440.0)
3436
//! .take_duration(std::time::Duration::from_secs_f32(20.25))

tests/flac_test.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
1+
#[cfg(any(feature = "flac", feature = "symphonia-flac"))]
22
use rodio::Source;
3-
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
3+
#[cfg(any(feature = "flac", feature = "symphonia-flac"))]
44
use std::time::Duration;
55

66
#[cfg(any(feature = "flac", feature = "symphonia-flac"))]
@@ -12,16 +12,13 @@ fn test_flac_encodings() {
1212

1313
// File is not just silence
1414
assert!(decoder.any(|x| x != 0.0));
15-
// Symphonia does not expose functionality to get the duration so this check must be disabled
16-
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
1715
assert_eq!(decoder.total_duration(), Some(Duration::from_secs(3))); // duration is calculated correctly
1816

1917
// 24 bit FLAC file exported from Audacity (2 channels, various compression levels)
2018
for level in &[0, 5, 8] {
2119
let file = std::fs::File::open(format!("assets/audacity24bit_level{level}.flac")).unwrap();
2220
let mut decoder = rodio::Decoder::try_from(file).unwrap();
2321
assert!(!decoder.all(|x| x != 0.0));
24-
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
2522
assert_eq!(decoder.total_duration(), Some(Duration::from_secs(3)));
2623
}
2724
}

0 commit comments

Comments
 (0)