lofty/config/
parse_options.rs

1/// Options to control how Lofty parses a file
2#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3#[non_exhaustive]
4pub struct ParseOptions {
5	pub(crate) read_properties: bool,
6	pub(crate) read_tags: bool,
7	pub(crate) parsing_mode: ParsingMode,
8	pub(crate) max_junk_bytes: usize,
9	pub(crate) read_cover_art: bool,
10	pub(crate) implicit_conversions: bool,
11}
12
13impl Default for ParseOptions {
14	/// The default implementation for `ParseOptions`
15	///
16	/// The defaults are as follows:
17	///
18	/// ```rust,ignore
19	/// ParseOptions {
20	/// 	read_properties: true,
21	///     read_tags: true,
22	/// 	parsing_mode: ParsingMode::BestAttempt,
23	///     max_junk_bytes: 1024,
24	///     read_cover_art: true,
25	///     implicit_conversions: true,
26	/// }
27	/// ```
28	fn default() -> Self {
29		Self::new()
30	}
31}
32
33impl ParseOptions {
34	/// Default parsing mode
35	pub const DEFAULT_PARSING_MODE: ParsingMode = ParsingMode::BestAttempt;
36
37	/// Default number of junk bytes to read
38	pub const DEFAULT_MAX_JUNK_BYTES: usize = 1024;
39
40	/// Creates a new `ParseOptions`, alias for `Default` implementation
41	///
42	/// See also: [`ParseOptions::default`]
43	///
44	/// # Examples
45	///
46	/// ```rust
47	/// use lofty::config::ParseOptions;
48	///
49	/// let parsing_options = ParseOptions::new();
50	/// ```
51	#[must_use]
52	pub const fn new() -> Self {
53		Self {
54			read_properties: true,
55			read_tags: true,
56			parsing_mode: Self::DEFAULT_PARSING_MODE,
57			max_junk_bytes: Self::DEFAULT_MAX_JUNK_BYTES,
58			read_cover_art: true,
59			implicit_conversions: true,
60		}
61	}
62
63	/// Whether or not to read the audio properties
64	///
65	/// # Examples
66	///
67	/// ```rust
68	/// use lofty::config::ParseOptions;
69	///
70	/// // By default, `read_properties` is enabled. Here, we don't want to read them.
71	/// let parsing_options = ParseOptions::new().read_properties(false);
72	/// ```
73	pub fn read_properties(&mut self, read_properties: bool) -> Self {
74		self.read_properties = read_properties;
75		*self
76	}
77
78	/// Whether or not to read the tags
79	///
80	/// # Examples
81	///
82	/// ```rust
83	/// use lofty::config::ParseOptions;
84	///
85	/// // By default, `read_tags` is enabled. Here, we don't want to read them.
86	/// let parsing_options = ParseOptions::new().read_tags(false);
87	/// ```
88	pub fn read_tags(&mut self, read_tags: bool) -> Self {
89		self.read_tags = read_tags;
90		*self
91	}
92
93	/// The parsing mode to use, see [`ParsingMode`] for details
94	///
95	/// # Examples
96	///
97	/// ```rust
98	/// use lofty::config::{ParseOptions, ParsingMode};
99	///
100	/// // By default, `parsing_mode` is ParsingMode::BestAttempt. Here, we need absolute correctness.
101	/// let parsing_options = ParseOptions::new().parsing_mode(ParsingMode::Strict);
102	/// ```
103	pub fn parsing_mode(&mut self, parsing_mode: ParsingMode) -> Self {
104		self.parsing_mode = parsing_mode;
105		*self
106	}
107
108	/// The maximum number of allowed junk bytes to search
109	///
110	/// Some information may be surrounded by junk bytes, such as tag padding remnants. This sets the maximum
111	/// number of junk/unrecognized bytes Lofty will search for required information before giving up.
112	///
113	/// # Examples
114	///
115	/// ```rust
116	/// use lofty::config::ParseOptions;
117	///
118	/// // I have files full of junk, I'll double the search window!
119	/// let parsing_options = ParseOptions::new().max_junk_bytes(2048);
120	/// ```
121	pub fn max_junk_bytes(&mut self, max_junk_bytes: usize) -> Self {
122		self.max_junk_bytes = max_junk_bytes;
123		*self
124	}
125
126	/// Whether or not to read cover art
127	///
128	/// # Examples
129	///
130	/// ```rust
131	/// use lofty::config::ParseOptions;
132	///
133	/// // Reading cover art is expensive, and I do not need it!
134	/// let parsing_options = ParseOptions::new().read_cover_art(false);
135	/// ```
136	pub fn read_cover_art(&mut self, read_cover_art: bool) -> Self {
137		self.read_cover_art = read_cover_art;
138		*self
139	}
140
141	/// Whether or not to perform implicit conversions
142	///
143	/// Implicit conversions are conversions that are not explicitly defined by the spec, but are commonly used.
144	///
145	/// ⚠ **Warning** ⚠
146	///
147	/// Turning this off may cause some [`Accessor`](crate::tag::Accessor) methods to return nothing.
148	/// Lofty makes some assumptions about the data, if they are broken, the caller will have more
149	/// responsibility.
150	///
151	/// Examples include:
152	///
153	/// * Converting the outdated MP4 `gnre` atom to a `©gen` atom
154	/// * Combining the ID3v2.3 `TYER`, `TDAT`, and `TIME` frames into a single `TDRC` frame
155	///
156	/// Examples of what this does *not* include:
157	///
158	/// * Converting a Vorbis `COVERART` field to `METADATA_BLOCK_PICTURE`
159	///   * This is a non-standard field, with a well-defined conversion. Lofty will not support
160	///     the non-standard `COVERART` for [`Picture`](crate::picture::Picture)s.
161	pub fn implicit_conversions(&mut self, implicit_conversions: bool) -> Self {
162		self.implicit_conversions = implicit_conversions;
163		*self
164	}
165}
166
167/// The parsing strictness mode
168///
169/// This can be set with [`Probe::options`](crate::probe::Probe).
170///
171/// # Examples
172///
173/// ```rust,no_run
174/// use lofty::config::{ParseOptions, ParsingMode};
175/// use lofty::probe::Probe;
176///
177/// # fn main() -> lofty::error::Result<()> {
178/// // We only want to read spec-compliant inputs
179/// let parsing_options = ParseOptions::new().parsing_mode(ParsingMode::Strict);
180/// let tagged_file = Probe::open("foo.mp3")?.options(parsing_options).read()?;
181/// # Ok(()) }
182/// ```
183#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Default)]
184#[non_exhaustive]
185pub enum ParsingMode {
186	/// Will eagerly error on invalid input
187	///
188	/// This mode will eagerly error on any non spec-compliant input.
189	///
190	/// ## Examples of behavior
191	///
192	/// * Unable to decode text - The parser will error and the entire input is discarded
193	/// * Unable to determine the sample rate - The parser will error and the entire input is discarded
194	Strict,
195	/// Default mode, less eager to error on recoverably malformed input
196	///
197	/// This mode will attempt to fill in any holes where possible in otherwise valid, spec-compliant input.
198	///
199	/// NOTE: A readable input does *not* necessarily make it writeable.
200	///
201	/// ## Examples of behavior
202	///
203	/// * Unable to decode text - If valid otherwise, the field will be replaced by an empty string and the parser moves on
204	/// * Unable to determine the sample rate - The sample rate will be 0
205	#[default]
206	BestAttempt,
207	/// Least eager to error, may produce invalid/partial output
208	///
209	/// This mode will discard any invalid fields, and ignore the majority of non-fatal errors.
210	///
211	/// If the input is malformed, the resulting tags may be incomplete, and the properties zeroed.
212	///
213	/// ## Examples of behavior
214	///
215	/// * Unable to decode text - The entire item is discarded and the parser moves on
216	/// * Unable to determine the sample rate - The sample rate will be 0
217	Relaxed,
218}