Skip to main content

qobuz_api/metadata/
config.rs

1//! Configuration for which metadata fields to embed.
2
3use std::collections::HashSet;
4
5/// Configuration controlling which metadata fields to embed in audio files.
6///
7/// Uses a set of `MetadataField` variants. `Default` enables all fields except `Comment`.
8/// Use `is_enabled()` to check whether a field should be embedded.
9#[derive(Clone, Debug, PartialEq)]
10pub struct MetadataConfig {
11    /// Set of enabled metadata fields.
12    enabled: HashSet<MetadataField>,
13}
14
15impl MetadataConfig {
16    /// Creates a config with all fields enabled.
17    ///
18    /// # Returns
19    ///
20    /// A `MetadataConfig` with every `MetadataField` enabled.
21    #[must_use]
22    pub fn all() -> Self {
23        Self {
24            enabled: HashSet::from([
25                MetadataField::Title,
26                MetadataField::Artist,
27                MetadataField::Album,
28                MetadataField::AlbumArtist,
29                MetadataField::Genre,
30                MetadataField::ReleaseDate,
31                MetadataField::ReleaseYear,
32                MetadataField::Composer,
33                MetadataField::TrackNumber,
34                MetadataField::TrackTotal,
35                MetadataField::DiscNumber,
36                MetadataField::DiscTotal,
37                MetadataField::CoverArt,
38                MetadataField::Isrc,
39                MetadataField::Copyright,
40                MetadataField::Label,
41                MetadataField::MediaType,
42                MetadataField::Comment,
43                MetadataField::Producer,
44                MetadataField::InvolvedPeople,
45                MetadataField::Explicit,
46                MetadataField::Upc,
47                MetadataField::Url,
48            ]),
49        }
50    }
51
52    /// Returns whether a specific field is enabled for embedding.
53    ///
54    /// # Arguments
55    ///
56    /// * `field` - The metadata field to check
57    ///
58    /// # Returns
59    ///
60    /// `true` if the field is enabled.
61    #[must_use]
62    pub fn is_enabled(&self, field: MetadataField) -> bool {
63        self.enabled.contains(&field)
64    }
65
66    /// Enables or disables a specific field.
67    ///
68    /// # Arguments
69    ///
70    /// * `field` - The metadata field to toggle
71    /// * `enabled` - `true` to enable, `false` to disable
72    pub fn set(&mut self, field: MetadataField, enabled: bool) {
73        if enabled {
74            self.enabled.insert(field);
75        } else {
76            self.enabled.remove(&field);
77        }
78    }
79}
80
81impl Default for MetadataConfig {
82    fn default() -> Self {
83        let mut config = Self::all();
84        config.enabled.remove(&MetadataField::Comment);
85        config
86    }
87}
88
89/// Metadata fields that can be embedded in audio files.
90#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
91pub enum MetadataField {
92    /// Track title.
93    Title,
94    /// Artist name.
95    Artist,
96    /// Album title.
97    Album,
98    /// Album artist.
99    AlbumArtist,
100    /// Genre.
101    Genre,
102    /// Full release date (YYYY-MM-DD).
103    ReleaseDate,
104    /// Release year only.
105    ReleaseYear,
106    /// Composer.
107    Composer,
108    /// Track number.
109    TrackNumber,
110    /// Total tracks in album.
111    TrackTotal,
112    /// Disc number.
113    DiscNumber,
114    /// Total discs in album.
115    DiscTotal,
116    /// Cover art image.
117    CoverArt,
118    /// ISRC code.
119    Isrc,
120    /// Copyright notice.
121    Copyright,
122    /// Record label.
123    Label,
124    /// Original media type (album, compilation, etc.).
125    MediaType,
126    /// Comment field.
127    Comment,
128    /// Producer.
129    Producer,
130    /// Involved people / musician credits.
131    InvolvedPeople,
132    /// Explicit content flag.
133    Explicit,
134    /// Universal Product Code.
135    Upc,
136    /// Commercial URL.
137    Url,
138}
139
140#[cfg(test)]
141mod tests {
142    use anyhow::{Result, ensure};
143
144    use crate::metadata::config::{
145        MetadataConfig,
146        MetadataField::{Comment, Producer, Title},
147    };
148
149    #[test]
150    fn default_excludes_comment() -> Result<()> {
151        let config = MetadataConfig::default();
152        ensure!(config.is_enabled(Title));
153        ensure!(!config.is_enabled(Comment));
154        Ok(())
155    }
156
157    #[test]
158    fn all_enables_every_field() -> Result<()> {
159        let config = MetadataConfig::all();
160        ensure!(config.is_enabled(Comment));
161        ensure!(config.is_enabled(Producer));
162        Ok(())
163    }
164
165    #[test]
166    fn set_toggles_field() -> Result<()> {
167        let mut config = MetadataConfig::default();
168        ensure!(!config.is_enabled(Comment));
169        config.set(Comment, true);
170        ensure!(config.is_enabled(Comment));
171        config.set(Comment, false);
172        ensure!(!config.is_enabled(Comment));
173        Ok(())
174    }
175}