Skip to content

Commit

Permalink
misc: Move {Parse,Write,Global}Options to new module
Browse files Browse the repository at this point in the history
  • Loading branch information
Serial-ATA committed Apr 13, 2024
1 parent c125f58 commit beda688
Show file tree
Hide file tree
Showing 85 changed files with 329 additions and 318 deletions.
5 changes: 3 additions & 2 deletions examples/custom_resolver/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use lofty::ape::ApeTag;
use lofty::config::{GlobalOptions, ParseOptions};
use lofty::error::Result as LoftyResult;
use lofty::id3::v2::Id3v2Tag;
use lofty::properties::FileProperties;
use lofty::resolve::FileResolver;
use lofty::{FileType, GlobalOptions, ParseOptions, TagType};
use lofty::{FileType, TagType};
use lofty_attr::LoftyFile;

use std::fs::File;
Expand Down Expand Up @@ -95,7 +96,7 @@ fn main() {
// By default, lofty will not check for custom files.
// We can enable this by updating our `GlobalOptions`.
let global_options = GlobalOptions::new().use_custom_resolvers(true);
lofty::apply_global_options(global_options);
lofty::config::apply_global_options(global_options);

// Now when using the following functions, your custom file will be checked

Expand Down
2 changes: 1 addition & 1 deletion examples/tag_reader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use lofty::prelude::*;
use lofty::{Probe, TaggedFileExt};
use lofty::Probe;

use std::path::Path;

Expand Down
3 changes: 2 additions & 1 deletion examples/tag_writer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use lofty::config::WriteOptions;
use lofty::prelude::*;
use lofty::{Probe, Tag, TaggedFileExt, WriteOptions};
use lofty::{Probe, Tag};

use structopt::StructOpt;

Expand Down
2 changes: 1 addition & 1 deletion lofty_attr/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub(crate) fn write_module(
quote! {
pub(crate) mod write {
#[allow(unused_variables)]
pub(crate) fn write_to(data: &mut ::std::fs::File, tag: &::lofty::Tag, write_options: ::lofty::WriteOptions) -> ::lofty::error::Result<()> {
pub(crate) fn write_to(data: &mut ::std::fs::File, tag: &::lofty::Tag, write_options: ::lofty::config::WriteOptions) -> ::lofty::error::Result<()> {
match tag.tag_type() {
#( #applicable_formats )*
_ => crate::macros::err!(UnsupportedTag),
Expand Down
4 changes: 2 additions & 2 deletions lofty_attr/src/lofty_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,14 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result<proc_macro2::TokenSt
impl ::lofty::prelude::AudioFile for #struct_name {
type Properties = #properties_field_ty;

fn read_from<R>(reader: &mut R, parse_options: ::lofty::ParseOptions) -> ::lofty::error::Result<Self>
fn read_from<R>(reader: &mut R, parse_options: ::lofty::config::ParseOptions) -> ::lofty::error::Result<Self>
where
R: std::io::Read + std::io::Seek,
{
#read_fn(reader, parse_options)
}

fn save_to(&self, file: &mut ::std::fs::File, write_options: ::lofty::WriteOptions) -> ::lofty::error::Result<()> {
fn save_to(&self, file: &mut ::std::fs::File, write_options: ::lofty::config::WriteOptions) -> ::lofty::error::Result<()> {
use ::lofty::prelude::TagExt as _;
use ::std::io::Seek as _;
#save_to_body
Expand Down
2 changes: 1 addition & 1 deletion src/aac/header.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::config::ParsingMode;
use crate::error::Result;
use crate::macros::decode_err;
use crate::mp4::{AudioObjectType, SAMPLE_RATES};
use crate::mpeg::MpegVersion;
use crate::probe::ParsingMode;

use std::io::{Read, Seek, SeekFrom};

Expand Down
2 changes: 1 addition & 1 deletion src/aac/read.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use super::header::{ADTSHeader, HEADER_MASK};
use super::AacFile;
use crate::config::{ParseOptions, ParsingMode};
use crate::error::Result;
use crate::id3::v2::header::Id3v2Header;
use crate::id3::v2::read::parse_id3v2;
use crate::id3::{find_id3v1, ID3FindResults};
use crate::macros::{decode_err, parse_mode_choice};
use crate::mpeg::header::{cmp_header, search_for_frame_sync, HeaderCmpResult};
use crate::probe::{ParseOptions, ParsingMode};

use std::io::{Read, Seek, SeekFrom};

Expand Down
2 changes: 1 addition & 1 deletion src/ape/properties.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::config::ParsingMode;
use crate::error::Result;
use crate::macros::decode_err;
use crate::probe::ParsingMode;
use crate::properties::FileProperties;

use std::io::{Read, Seek, SeekFrom};
Expand Down
2 changes: 1 addition & 1 deletion src/ape/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use super::header::read_ape_header;
use super::tag::ApeTag;
use super::{ApeFile, ApeProperties};
use crate::ape::tag::read::{read_ape_tag, read_ape_tag_with_header};
use crate::config::ParseOptions;
use crate::error::Result;
use crate::id3::v1::tag::Id3v1Tag;
use crate::id3::v2::read::parse_id3v2;
use crate::id3::v2::tag::Id3v2Tag;
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, FindId3v2Config, ID3FindResults};
use crate::macros::decode_err;
use crate::probe::ParseOptions;

use std::io::{Read, Seek, SeekFrom};

Expand Down
5 changes: 3 additions & 2 deletions src/ape/tag/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ pub(crate) mod read;
mod write;

use crate::ape::tag::item::{ApeItem, ApeItemRef};
use crate::config::WriteOptions;
use crate::error::{LoftyError, Result};
use crate::id3::v2::util::pairs::{format_number_pair, set_number, NUMBER_PAIR_KEYS};
use crate::tag::item::{ItemKey, ItemValue, ItemValueRef, TagItem};
use crate::tag::{try_parse_year, Tag, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag, TagExt};
use crate::write_options::WriteOptions;

use std::borrow::Cow;
use std::fs::File;
Expand Down Expand Up @@ -544,9 +544,10 @@ pub(crate) fn tagitems_into_ape(tag: &Tag) -> impl Iterator<Item = ApeItemRef<'_
#[cfg(test)]
mod tests {
use crate::ape::{ApeItem, ApeTag};
use crate::config::WriteOptions;
use crate::id3::v2::util::pairs::DEFAULT_NUMBER_IN_PAIR;
use crate::prelude::*;
use crate::{ItemKey, ItemValue, Tag, TagItem, TagType, WriteOptions};
use crate::{ItemValue, Tag, TagItem, TagType};

use std::io::Cursor;

Expand Down
2 changes: 1 addition & 1 deletion src/ape/tag/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use super::item::ApeItemRef;
use super::ApeTagRef;
use crate::ape::constants::APE_PREAMBLE;
use crate::ape::tag::read;
use crate::config::WriteOptions;
use crate::error::Result;
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, FindId3v2Config};
use crate::macros::{decode_err, err};
use crate::probe::Probe;
use crate::tag::item::ItemValueRef;
use crate::write_options::WriteOptions;

use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
Expand Down
18 changes: 9 additions & 9 deletions src/global_options.rs → src/config/global_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ pub(crate) unsafe fn global_options() -> &'static GlobalOptions {
/// # Examples
///
/// ```rust
/// use lofty::GlobalOptions;
/// use lofty::config::{apply_global_options, GlobalOptions};
///
/// // I have a custom resolver that I need checked
/// let global_options = GlobalOptions::new().use_custom_resolvers(true);
/// lofty::apply_global_options(global_options);
/// apply_global_options(global_options);
/// ```
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
#[non_exhaustive]
Expand All @@ -37,7 +37,7 @@ impl GlobalOptions {
/// # Examples
///
/// ```rust
/// use lofty::GlobalOptions;
/// use lofty::config::GlobalOptions;
///
/// let global_options = GlobalOptions::new();
/// ```
Expand All @@ -56,11 +56,11 @@ impl GlobalOptions {
/// # Examples
///
/// ```rust
/// use lofty::GlobalOptions;
/// use lofty::config::{apply_global_options, GlobalOptions};
///
/// // By default, `use_custom_resolvers` is enabled. Here, we don't want to use them.
/// let global_options = GlobalOptions::new().use_custom_resolvers(false);
/// lofty::apply_global_options(global_options);
/// apply_global_options(global_options);
/// ```
pub fn use_custom_resolvers(&mut self, use_custom_resolvers: bool) -> Self {
self.use_custom_resolvers = use_custom_resolvers;
Expand All @@ -75,11 +75,11 @@ impl GlobalOptions {
/// # Examples
///
/// ```rust
/// use lofty::GlobalOptions;
/// use lofty::config::{apply_global_options, GlobalOptions};
///
/// // I have files with gigantic images, I'll double the allocation limit!
/// let global_options = GlobalOptions::new().allocation_limit(32 * 1024 * 1024);
/// lofty::apply_global_options(global_options);
/// apply_global_options(global_options);
/// ```
pub fn allocation_limit(&mut self, allocation_limit: usize) -> Self {
self.allocation_limit = allocation_limit;
Expand Down Expand Up @@ -108,11 +108,11 @@ impl Default for GlobalOptions {
/// # Examples
///
/// ```rust
/// use lofty::GlobalOptions;
/// use lofty::config::{apply_global_options, GlobalOptions};
///
/// // I have a custom resolver that I need checked
/// let global_options = GlobalOptions::new().use_custom_resolvers(true);
/// lofty::apply_global_options(global_options);
/// apply_global_options(global_options);
/// ```
pub fn apply_global_options(options: GlobalOptions) {
GLOBAL_OPTIONS.with(|global_options| unsafe {
Expand Down
11 changes: 11 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Various configuration options to control Lofty

mod global_options;
mod parse_options;
mod write_options;

pub use global_options::{apply_global_options, GlobalOptions};
pub use parse_options::{ParseOptions, ParsingMode};
pub use write_options::WriteOptions;

pub(crate) use global_options::global_options;
154 changes: 154 additions & 0 deletions src/config/parse_options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/// Options to control how Lofty parses a file
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct ParseOptions {
pub(crate) read_properties: bool,
pub(crate) parsing_mode: ParsingMode,
pub(crate) max_junk_bytes: usize,
}

impl Default for ParseOptions {
/// The default implementation for `ParseOptions`
///
/// The defaults are as follows:
///
/// ```rust,ignore
/// ParseOptions {
/// read_properties: true,
/// parsing_mode: ParsingMode::BestAttempt,
/// max_junk_bytes: 1024
/// }
/// ```
fn default() -> Self {
Self::new()
}
}

impl ParseOptions {
/// Default parsing mode
pub const DEFAULT_PARSING_MODE: ParsingMode = ParsingMode::BestAttempt;

/// Default number of junk bytes to read
pub const DEFAULT_MAX_JUNK_BYTES: usize = 1024;

/// Creates a new `ParseOptions`, alias for `Default` implementation
///
/// See also: [`ParseOptions::default`]
///
/// # Examples
///
/// ```rust
/// use lofty::config::ParseOptions;
///
/// let parsing_options = ParseOptions::new();
/// ```
#[must_use]
pub const fn new() -> Self {
Self {
read_properties: true,
parsing_mode: Self::DEFAULT_PARSING_MODE,
max_junk_bytes: Self::DEFAULT_MAX_JUNK_BYTES,
}
}

/// Whether or not to read the audio properties
///
/// # Examples
///
/// ```rust
/// use lofty::config::ParseOptions;
///
/// // By default, `read_properties` is enabled. Here, we don't want to read them.
/// let parsing_options = ParseOptions::new().read_properties(false);
/// ```
pub fn read_properties(&mut self, read_properties: bool) -> Self {
self.read_properties = read_properties;
*self
}

/// The parsing mode to use, see [`ParsingMode`] for details
///
/// # Examples
///
/// ```rust
/// use lofty::config::{ParseOptions, ParsingMode};
///
/// // By default, `parsing_mode` is ParsingMode::BestAttempt. Here, we need absolute correctness.
/// let parsing_options = ParseOptions::new().parsing_mode(ParsingMode::Strict);
/// ```
pub fn parsing_mode(&mut self, parsing_mode: ParsingMode) -> Self {
self.parsing_mode = parsing_mode;
*self
}

/// The maximum number of allowed junk bytes to search
///
/// Some information may be surrounded by junk bytes, such as tag padding remnants. This sets the maximum
/// number of junk/unrecognized bytes Lofty will search for required information before giving up.
///
/// # Examples
///
/// ```rust
/// use lofty::config::ParseOptions;
///
/// // I have files full of junk, I'll double the search window!
/// let parsing_options = ParseOptions::new().max_junk_bytes(2048);
/// ```
pub fn max_junk_bytes(&mut self, max_junk_bytes: usize) -> Self {
self.max_junk_bytes = max_junk_bytes;
*self
}
}

/// The parsing strictness mode
///
/// This can be set with [`Probe::options`].
///
/// # Examples
///
/// ```rust,no_run
/// use lofty::config::{ParseOptions, ParsingMode};
/// use lofty::Probe;
///
/// # fn main() -> lofty::error::Result<()> {
/// // We only want to read spec-compliant inputs
/// let parsing_options = ParseOptions::new().parsing_mode(ParsingMode::Strict);
/// let tagged_file = Probe::open("foo.mp3")?.options(parsing_options).read()?;
/// # Ok(()) }
/// ```
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum ParsingMode {
/// Will eagerly error on invalid input
///
/// This mode will eagerly error on any non spec-compliant input.
///
/// ## Examples of behavior
///
/// * Unable to decode text - The parser will error and the entire input is discarded
/// * Unable to determine the sample rate - The parser will error and the entire input is discarded
Strict,
/// Default mode, less eager to error on recoverably malformed input
///
/// This mode will attempt to fill in any holes where possible in otherwise valid, spec-compliant input.
///
/// NOTE: A readable input does *not* necessarily make it writeable.
///
/// ## Examples of behavior
///
/// * Unable to decode text - If valid otherwise, the field will be replaced by an empty string and the parser moves on
/// * Unable to determine the sample rate - The sample rate will be 0
#[default]
BestAttempt,
/// Least eager to error, may produce invalid/partial output
///
/// This mode will discard any invalid fields, and ignore the majority of non-fatal errors.
///
/// If the input is malformed, the resulting tags may be incomplete, and the properties zeroed.
///
/// ## Examples of behavior
///
/// * Unable to decode text - The entire item is discarded and the parser moves on
/// * Unable to determine the sample rate - The sample rate will be 0
Relaxed,
}
Loading

0 comments on commit beda688

Please sign in to comment.