From c125f5839c7e8d8216b454c40e24f940df0a14b5 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:08:28 -0400 Subject: [PATCH 01/22] misc: Introduce prelude --- examples/tag_reader.rs | 4 +++- examples/tag_writer.rs | 3 ++- lofty_attr/src/lofty_file.rs | 8 ++++---- src/ape/tag/mod.rs | 5 +++-- src/id3/v1/tag.rs | 3 ++- src/id3/v2/read.rs | 4 +++- src/id3/v2/write/mod.rs | 3 ++- src/iff/aiff/tag.rs | 5 +++-- src/iff/wav/tag/mod.rs | 6 ++++-- src/lib.rs | 21 ++++++++++++++++----- src/mp4/ilst/mod.rs | 5 +++-- src/ogg/tag.rs | 6 ++---- src/properties/tests.rs | 2 +- src/tag/mod.rs | 4 +++- tests/files/aac.rs | 7 +++---- tests/files/aiff.rs | 6 +++--- tests/files/ape.rs | 6 +++--- tests/files/flac.rs | 3 ++- tests/files/mp4.rs | 6 +++--- tests/files/mpc.rs | 5 +++-- tests/files/mpeg.rs | 9 +++++---- tests/files/ogg.rs | 6 +++--- tests/files/wav.rs | 6 +++--- tests/files/wavpack.rs | 6 +++--- tests/files/zero_sized.rs | 3 ++- tests/fuzz/main.rs | 4 +++- tests/fuzz/mpegfile_read_from.rs | 3 ++- tests/hound.rs | 11 +++++++---- 28 files changed, 96 insertions(+), 64 deletions(-) diff --git a/examples/tag_reader.rs b/examples/tag_reader.rs index d486241e2..96bfb369f 100644 --- a/examples/tag_reader.rs +++ b/examples/tag_reader.rs @@ -1,4 +1,6 @@ -use lofty::{Accessor, AudioFile, Probe, TaggedFileExt}; +use lofty::prelude::*; +use lofty::{Probe, TaggedFileExt}; + use std::path::Path; fn main() { diff --git a/examples/tag_writer.rs b/examples/tag_writer.rs index f72a9ce7f..9a08844b3 100644 --- a/examples/tag_writer.rs +++ b/examples/tag_writer.rs @@ -1,4 +1,5 @@ -use lofty::{Accessor, Probe, Tag, TagExt, TaggedFileExt, WriteOptions}; +use lofty::prelude::*; +use lofty::{Probe, Tag, TaggedFileExt, WriteOptions}; use structopt::StructOpt; diff --git a/lofty_attr/src/lofty_file.rs b/lofty_attr/src/lofty_file.rs index 12bd8137a..50bf7d039 100644 --- a/lofty_attr/src/lofty_file.rs +++ b/lofty_attr/src/lofty_file.rs @@ -178,7 +178,7 @@ impl LoftyFile { let name = format_ident!("_AssertTagExt{}", i); let field_ty = &f.ty; quote_spanned! {field_ty.span()=> - struct #name where #field_ty: lofty::TagExt; + struct #name where #field_ty: ::lofty::prelude::TagExt; } }); @@ -435,7 +435,7 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result(reader: &mut R, parse_options: ::lofty::ParseOptions) -> ::lofty::error::Result @@ -446,7 +446,7 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result ::lofty::error::Result<()> { - use ::lofty::TagExt as _; + use ::lofty::prelude::TagExt as _; use ::std::io::Seek as _; #save_to_body } @@ -533,7 +533,7 @@ fn generate_from_taggedfile_impl(file: &LoftyFile) -> proc_macro2::TokenStream { quote! { impl ::std::convert::From<#struct_name> for ::lofty::TaggedFile { fn from(input: #struct_name) -> Self { - use ::lofty::TaggedFileExt as _; + use ::lofty::prelude::TaggedFileExt as _; ::lofty::TaggedFile::new( #file_type_variant, diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index ec2d76f24..e4a4e8a3e 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -544,9 +544,10 @@ pub(crate) fn tagitems_into_ape(tag: &Tag) -> impl Iterator Id3v1TagRef<'a> { #[cfg(test)] mod tests { use crate::id3::v1::Id3v1Tag; - use crate::{Tag, TagExt, TagType, WriteOptions}; + use crate::prelude::*; + use crate::{Tag, TagType, WriteOptions}; #[test] fn parse_id3v1() { diff --git a/src/id3/v2/read.rs b/src/id3/v2/read.rs index 3bb369bc8..622b8ed7b 100644 --- a/src/id3/v2/read.rs +++ b/src/id3/v2/read.rs @@ -116,7 +116,9 @@ fn zero_size_id3v2() { #[test] fn bad_frame_id_relaxed_id3v2() { use crate::id3::v2::header::Id3v2Header; - use crate::{Accessor, ParsingMode, TagExt}; + use crate::prelude::*; + use crate::ParsingMode; + use std::io::Cursor; // Contains a frame with a "+" in the ID, which is invalid. diff --git a/src/id3/v2/write/mod.rs b/src/id3/v2/write/mod.rs index 008648f40..b2b07e034 100644 --- a/src/id3/v2/write/mod.rs +++ b/src/id3/v2/write/mod.rs @@ -284,7 +284,8 @@ fn calculate_crc(content: &[u8]) -> [u8; 5] { #[cfg(test)] mod tests { use crate::id3::v2::{Id3v2Tag, Id3v2TagFlags}; - use crate::{Accessor, TagExt, WriteOptions}; + use crate::prelude::*; + use crate::WriteOptions; #[test] fn id3v2_write_crc32() { diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 0b607e882..5bbc0f07c 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -484,9 +484,10 @@ where #[cfg(test)] mod tests { use crate::iff::aiff::{AIFFTextChunks, Comment}; - use crate::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType, WriteOptions}; - + use crate::prelude::*; use crate::probe::ParseOptions; + use crate::{ItemKey, ItemValue, Tag, TagItem, TagType, WriteOptions}; + use std::io::Cursor; #[test] diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index 5906239f3..8e732bd3c 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -348,11 +348,13 @@ pub(crate) fn tagitems_into_riff<'a>( #[cfg(test)] mod tests { + use crate::iff::chunk::Chunks; use crate::iff::wav::RIFFInfoList; - use crate::{Tag, TagExt, TagType, WriteOptions}; + use crate::prelude::*; + use crate::{Tag, TagType, WriteOptions}; - use crate::iff::chunk::Chunks; use byteorder::LittleEndian; + use std::io::Cursor; #[test] diff --git a/src/lib.rs b/src/lib.rs index 904643f40..8bbe9166d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -174,21 +174,32 @@ mod util; pub mod wavpack; mod write_options; -pub use crate::error::{LoftyError, Result}; - pub use crate::probe::{read_from, read_from_path, ParseOptions, ParsingMode, Probe}; pub use crate::write_options::WriteOptions; -pub use crate::file::{AudioFile, BoundTaggedFile, FileType, TaggedFile, TaggedFileExt}; +pub use crate::file::{BoundTaggedFile, FileType, TaggedFile, TaggedFileExt}; pub use crate::picture::{MimeType, Picture, PictureType}; pub use crate::tag::{Tag, TagType}; pub use tag::item::{ItemKey, ItemValue, TagItem}; pub use util::text::TextEncoding; -pub use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; - pub use picture::PictureInformation; pub use global_options::{apply_global_options, GlobalOptions}; pub use lofty_attr::LoftyFile; + +pub mod prelude { + //! A prelude for commonly used items in the library. + //! + //! This module is intended to be glob imported. + //! + //! ```rust + //! use lofty::prelude::*; + //! ``` + + pub use crate::error::LoftyError; + pub use crate::file::{AudioFile, TaggedFileExt}; + pub use crate::tag::item::ItemKey; + pub use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +} diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 7fd00d022..3ab103b45 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -763,12 +763,13 @@ mod tests { use crate::mp4::ilst::TITLE; use crate::mp4::read::AtomReader; use crate::mp4::{AdvisoryRating, Atom, AtomData, AtomIdent, Ilst, Mp4File}; + use crate::prelude::*; use crate::tag::utils::test_utils; use crate::tag::utils::test_utils::read_path; use crate::{ - Accessor as _, AudioFile, ItemKey, ItemValue, ParseOptions, ParsingMode, SplitTag as _, - Tag, TagExt as _, TagItem, TagType, WriteOptions, + ItemKey, ItemValue, ParseOptions, ParsingMode, Tag, TagItem, TagType, WriteOptions, }; + use std::io::{Cursor, Read as _, Seek as _, Write as _}; fn read_ilst(path: &str, parse_mode: ParsingMode) -> Ilst { diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index a4567e906..e5a6b9c5a 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -694,10 +694,8 @@ pub(crate) fn create_vorbis_comments_ref( #[cfg(test)] mod tests { use crate::ogg::{OggPictureStorage, VorbisComments}; - use crate::{ - ItemKey, ItemValue, MergeTag as _, ParsingMode, SplitTag as _, Tag, TagExt as _, TagItem, - TagType, WriteOptions, - }; + use crate::prelude::*; + use crate::{ItemKey, ItemValue, ParsingMode, Tag, TagItem, TagType, WriteOptions}; fn read_tag(tag: &[u8]) -> VorbisComments { let mut reader = std::io::Cursor::new(tag); diff --git a/src/properties/tests.rs b/src/properties/tests.rs index 27489472c..7112bf3d1 100644 --- a/src/properties/tests.rs +++ b/src/properties/tests.rs @@ -1,5 +1,6 @@ use crate::aac::{AACProperties, AacFile}; use crate::ape::{ApeFile, ApeProperties}; +use crate::file::AudioFile; use crate::flac::{FlacFile, FlacProperties}; use crate::iff::aiff::{AiffFile, AiffProperties}; use crate::iff::wav::{WavFile, WavFormat, WavProperties}; @@ -15,7 +16,6 @@ use crate::ogg::{ use crate::probe::ParseOptions; use crate::properties::ChannelMask; use crate::wavpack::{WavPackFile, WavPackProperties}; -use crate::AudioFile; use std::fs::File; use std::time::Duration; diff --git a/src/tag/mod.rs b/src/tag/mod.rs index 7a6b05136..b61158755 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -663,8 +663,10 @@ impl TagType { #[cfg(test)] mod tests { use super::try_parse_year; + use crate::prelude::*; use crate::tag::utils::test_utils::read_path; - use crate::{Accessor, Picture, PictureType, Tag, TagExt, TagType, WriteOptions}; + use crate::{Picture, PictureType, Tag, TagType, WriteOptions}; + use std::io::{Seek, Write}; use std::process::Command; diff --git a/tests/files/aac.rs b/tests/files/aac.rs index 5af2445a3..13a0a9d21 100644 --- a/tests/files/aac.rs +++ b/tests/files/aac.rs @@ -1,8 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - Accessor, FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, - TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/aiff.rs b/tests/files/aiff.rs index df459f375..30a3316bf 100644 --- a/tests/files/aiff.rs +++ b/tests/files/aiff.rs @@ -1,7 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/ape.rs b/tests/files/ape.rs index 502189f8d..32b48e064 100644 --- a/tests/files/ape.rs +++ b/tests/files/ape.rs @@ -1,7 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/flac.rs b/tests/files/flac.rs index 6d17b6286..954938b13 100644 --- a/tests/files/flac.rs +++ b/tests/files/flac.rs @@ -1,5 +1,6 @@ use lofty::flac::FlacFile; -use lofty::{Accessor, AudioFile, ParseOptions, ParsingMode}; +use lofty::prelude::*; +use lofty::{ParseOptions, ParsingMode}; use std::fs::File; use std::io::Seek; diff --git a/tests/files/mp4.rs b/tests/files/mp4.rs index 946a6af6e..abff918b8 100644 --- a/tests/files/mp4.rs +++ b/tests/files/mp4.rs @@ -1,7 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/mpc.rs b/tests/files/mpc.rs index 36484fa16..69cee5528 100644 --- a/tests/files/mpc.rs +++ b/tests/files/mpc.rs @@ -1,9 +1,10 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::musepack::MpcFile; +use lofty::prelude::*; use lofty::{ - AudioFile, FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, - TaggedFile, TaggedFileExt, + FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFile, TaggedFileExt, }; + use std::io::{Seek, Write}; // Marker test so IntelliJ Rust recognizes this as a test module diff --git a/tests/files/mpeg.rs b/tests/files/mpeg.rs index 9bc9aa267..6b9c40407 100644 --- a/tests/files/mpeg.rs +++ b/tests/files/mpeg.rs @@ -1,12 +1,13 @@ use crate::{set_artist, temp_file, verify_artist}; -use std::borrow::Cow; - use lofty::id3::v2::{Frame, FrameFlags, FrameId, FrameValue, Id3v2Tag, KeyValueFrame}; use lofty::mpeg::MpegFile; +use lofty::prelude::*; use lofty::{ - Accessor, AudioFile, FileType, ItemKey, ItemValue, ParseOptions, Probe, Tag, TagExt, TagItem, - TagType, TaggedFileExt, WriteOptions, + FileType, ItemKey, ItemValue, ParseOptions, Probe, Tag, TagItem, TagType, TaggedFileExt, + WriteOptions, }; + +use std::borrow::Cow; use std::io::{Seek, Write}; #[test] diff --git a/tests/files/ogg.rs b/tests/files/ogg.rs index b6c808f9a..9528eb361 100644 --- a/tests/files/ogg.rs +++ b/tests/files/ogg.rs @@ -1,8 +1,10 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::prelude::*; use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, + FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt, WriteOptions, }; + use std::io::{Seek, Write}; // The tests for OGG Opus/Vorbis are nearly identical @@ -151,7 +153,6 @@ fn remove(path: &str, tag_type: TagType) { #[test] fn flac_with_id3v2() { use lofty::flac::FlacFile; - use lofty::{Accessor, AudioFile}; let file = std::fs::read("tests/files/assets/flac_with_id3v2.flac").unwrap(); let flac_file = @@ -174,7 +175,6 @@ fn flac_remove_id3v2() { #[test] fn flac_try_write_non_empty_id3v2() { use lofty::id3::v2::Id3v2Tag; - use lofty::Accessor; let mut tag = Id3v2Tag::default(); tag.set_artist(String::from("Foo artist")); diff --git a/tests/files/wav.rs b/tests/files/wav.rs index 0bbf2422e..1bf888a12 100644 --- a/tests/files/wav.rs +++ b/tests/files/wav.rs @@ -1,7 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index ae4c3b504..8e11de576 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -1,7 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagExt, TagItem, TagType, TaggedFileExt, -}; +use lofty::prelude::*; +use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; + use std::io::{Seek, Write}; #[test] diff --git a/tests/files/zero_sized.rs b/tests/files/zero_sized.rs index 876dd2e77..075985010 100644 --- a/tests/files/zero_sized.rs +++ b/tests/files/zero_sized.rs @@ -4,7 +4,8 @@ use lofty::iff::aiff::AiffFile; use lofty::iff::wav::WavFile; use lofty::mp4::Mp4File; use lofty::mpeg::MpegFile; -use lofty::{AudioFile, ParseOptions, ParsingMode}; +use lofty::prelude::*; +use lofty::{ParseOptions, ParsingMode}; fn read_file_with_properties(path: &str) -> bool { let res = ::read_from( diff --git a/tests/fuzz/main.rs b/tests/fuzz/main.rs index 1404e48b4..2141671c8 100644 --- a/tests/fuzz/main.rs +++ b/tests/fuzz/main.rs @@ -1,4 +1,6 @@ -use lofty::{AudioFile, ParseOptions}; +use lofty::prelude::*; +use lofty::ParseOptions; + use std::io::Cursor; use std::path::Path; use std::thread; diff --git a/tests/fuzz/mpegfile_read_from.rs b/tests/fuzz/mpegfile_read_from.rs index 197f6e47e..d51b48af0 100644 --- a/tests/fuzz/mpegfile_read_from.rs +++ b/tests/fuzz/mpegfile_read_from.rs @@ -1,6 +1,7 @@ use crate::{get_reader, oom_test}; use lofty::mpeg::MpegFile; -use lofty::{AudioFile, ParseOptions}; +use lofty::prelude::*; +use lofty::ParseOptions; #[test] fn crash1() { diff --git a/tests/hound.rs b/tests/hound.rs index 2f8dd5d26..ad9b7f5a0 100644 --- a/tests/hound.rs +++ b/tests/hound.rs @@ -1,11 +1,14 @@ +use lofty::error::Result; +use lofty::iff::wav::WavFile; +use lofty::prelude::*; +use lofty::ParseOptions; + +use hound::WavReader; + use std::fs; use std::fs::File; use std::path::Path; -use hound::WavReader; -use lofty::iff::wav::WavFile; -use lofty::{AudioFile, ParseOptions, Result}; - fn get_properties(path: &Path) -> Result<::Properties> { let mut f = File::open(path).unwrap(); let wav_file = WavFile::read_from(&mut f, ParseOptions::new())?; From beda6883c2ae6b3b281a83c1974043afcd4dde3e Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 12:50:28 -0400 Subject: [PATCH 02/22] misc: Move {Parse,Write,Global}Options to new module --- examples/custom_resolver/src/main.rs | 5 +- examples/tag_reader.rs | 2 +- examples/tag_writer.rs | 3 +- lofty_attr/src/internal.rs | 2 +- lofty_attr/src/lofty_file.rs | 4 +- src/aac/header.rs | 2 +- src/aac/read.rs | 2 +- src/ape/properties.rs | 2 +- src/ape/read.rs | 2 +- src/ape/tag/mod.rs | 5 +- src/ape/tag/write.rs | 2 +- src/{ => config}/global_options.rs | 18 +- src/config/mod.rs | 11 ++ src/config/parse_options.rs | 154 ++++++++++++++++ src/{ => config}/write_options.rs | 22 ++- src/file.rs | 4 +- src/flac/mod.rs | 2 +- src/flac/read.rs | 2 +- src/flac/write.rs | 2 +- src/id3/v1/tag.rs | 5 +- src/id3/v1/write.rs | 2 +- src/id3/v2/frame/content.rs | 2 +- src/id3/v2/frame/read.rs | 2 +- .../items/relative_volume_adjustment_frame.rs | 4 +- src/id3/v2/items/unique_file_identifier.rs | 4 +- src/id3/v2/read.rs | 7 +- src/id3/v2/tag.rs | 2 +- src/id3/v2/tag/tests.rs | 2 +- src/id3/v2/write/chunk_file.rs | 2 +- src/id3/v2/write/mod.rs | 4 +- src/iff/aiff/read.rs | 2 +- src/iff/aiff/tag.rs | 6 +- src/iff/chunk.rs | 2 +- src/iff/wav/read.rs | 2 +- src/iff/wav/tag/mod.rs | 5 +- src/iff/wav/tag/write.rs | 2 +- src/lib.rs | 8 +- src/macros.rs | 12 +- src/mp4/atom_info.rs | 2 +- src/mp4/ilst/mod.rs | 38 ++-- src/mp4/ilst/read.rs | 2 +- src/mp4/ilst/ref.rs | 2 +- src/mp4/ilst/write.rs | 3 +- src/mp4/moov.rs | 2 +- src/mp4/properties.rs | 2 +- src/mp4/read.rs | 2 +- src/mp4/write.rs | 2 +- src/mpeg/read.rs | 2 +- src/musepack/read.rs | 2 +- src/musepack/sv4to6/properties.rs | 2 +- src/musepack/sv8/properties.rs | 2 +- src/musepack/sv8/read.rs | 2 +- src/ogg/opus/mod.rs | 2 +- src/ogg/read.rs | 2 +- src/ogg/speex/mod.rs | 2 +- src/ogg/tag.rs | 5 +- src/ogg/vorbis/mod.rs | 2 +- src/ogg/write.rs | 2 +- src/picture.rs | 2 +- src/probe.rs | 164 +----------------- src/properties/tests.rs | 2 +- src/resolve.rs | 7 +- src/tag/mod.rs | 5 +- src/tag/utils.rs | 2 +- src/traits.rs | 2 +- src/util/alloc.rs | 2 +- src/wavpack/properties.rs | 2 +- src/wavpack/read.rs | 2 +- tests/files/aac.rs | 3 +- tests/files/aiff.rs | 3 +- tests/files/ape.rs | 3 +- tests/files/flac.rs | 2 +- tests/files/mp4.rs | 3 +- tests/files/mpc.rs | 5 +- tests/files/mpeg.rs | 6 +- tests/files/ogg.rs | 6 +- tests/files/util/mod.rs | 6 +- tests/files/wav.rs | 3 +- tests/files/wavpack.rs | 3 +- tests/files/zero_sized.rs | 2 +- tests/fuzz/id3v2.rs | 2 +- tests/fuzz/main.rs | 2 +- tests/fuzz/mpegfile_read_from.rs | 2 +- tests/hound.rs | 2 +- tests/picture/format_parsers.rs | 3 +- 85 files changed, 329 insertions(+), 318 deletions(-) rename src/{ => config}/global_options.rs (86%) create mode 100644 src/config/mod.rs create mode 100644 src/config/parse_options.rs rename src/{ => config}/write_options.rs (89%) diff --git a/examples/custom_resolver/src/main.rs b/examples/custom_resolver/src/main.rs index fdd18a5d7..1ac3b3e4a 100644 --- a/examples/custom_resolver/src/main.rs +++ b/examples/custom_resolver/src/main.rs @@ -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; @@ -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 diff --git a/examples/tag_reader.rs b/examples/tag_reader.rs index 96bfb369f..4849529a0 100644 --- a/examples/tag_reader.rs +++ b/examples/tag_reader.rs @@ -1,5 +1,5 @@ use lofty::prelude::*; -use lofty::{Probe, TaggedFileExt}; +use lofty::Probe; use std::path::Path; diff --git a/examples/tag_writer.rs b/examples/tag_writer.rs index 9a08844b3..745283e18 100644 --- a/examples/tag_writer.rs +++ b/examples/tag_writer.rs @@ -1,5 +1,6 @@ +use lofty::config::WriteOptions; use lofty::prelude::*; -use lofty::{Probe, Tag, TaggedFileExt, WriteOptions}; +use lofty::{Probe, Tag}; use structopt::StructOpt; diff --git a/lofty_attr/src/internal.rs b/lofty_attr/src/internal.rs index d0f9aaf5e..e46158f7a 100644 --- a/lofty_attr/src/internal.rs +++ b/lofty_attr/src/internal.rs @@ -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), diff --git a/lofty_attr/src/lofty_file.rs b/lofty_attr/src/lofty_file.rs index 50bf7d039..df78837ac 100644 --- a/lofty_attr/src/lofty_file.rs +++ b/lofty_attr/src/lofty_file.rs @@ -438,14 +438,14 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result(reader: &mut R, parse_options: ::lofty::ParseOptions) -> ::lofty::error::Result + fn read_from(reader: &mut R, parse_options: ::lofty::config::ParseOptions) -> ::lofty::error::Result 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 diff --git a/src/aac/header.rs b/src/aac/header.rs index 57c8765a2..5b456eb0b 100644 --- a/src/aac/header.rs +++ b/src/aac/header.rs @@ -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}; diff --git a/src/aac/read.rs b/src/aac/read.rs index 4194853da..43c04b75f 100644 --- a/src/aac/read.rs +++ b/src/aac/read.rs @@ -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}; diff --git a/src/ape/properties.rs b/src/ape/properties.rs index 3fa509d02..3836bc750 100644 --- a/src/ape/properties.rs +++ b/src/ape/properties.rs @@ -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}; diff --git a/src/ape/read.rs b/src/ape/read.rs index 02a1e2c81..4b01e996b 100644 --- a/src/ape/read.rs +++ b/src/ape/read.rs @@ -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}; diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index e4a4e8a3e..b0056f812 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -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; @@ -544,9 +544,10 @@ pub(crate) fn tagitems_into_ape(tag: &Tag) -> impl Iterator &'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] @@ -37,7 +37,7 @@ impl GlobalOptions { /// # Examples /// /// ```rust - /// use lofty::GlobalOptions; + /// use lofty::config::GlobalOptions; /// /// let global_options = GlobalOptions::new(); /// ``` @@ -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; @@ -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; @@ -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 { diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 000000000..3a998d2ad --- /dev/null +++ b/src/config/mod.rs @@ -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; diff --git a/src/config/parse_options.rs b/src/config/parse_options.rs new file mode 100644 index 000000000..12a1857ac --- /dev/null +++ b/src/config/parse_options.rs @@ -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, +} diff --git a/src/write_options.rs b/src/config/write_options.rs similarity index 89% rename from src/write_options.rs rename to src/config/write_options.rs index 2fbf2d628..de90df2c2 100644 --- a/src/write_options.rs +++ b/src/config/write_options.rs @@ -22,7 +22,7 @@ impl WriteOptions { /// # Examples /// /// ```rust - /// use lofty::WriteOptions; + /// use lofty::config::WriteOptions; /// /// let write_options = WriteOptions::new(); /// ``` @@ -48,7 +48,7 @@ impl WriteOptions { /// # Examples /// /// ```rust - /// use lofty::WriteOptions; + /// use lofty::config::WriteOptions; /// /// // I really don't want my files rewritten, so I'll double the padding size! /// let options = WriteOptions::new().preferred_padding(2048); @@ -71,9 +71,11 @@ impl WriteOptions { /// # Examples /// /// ```rust,no_run - /// use lofty::{Tag, TagExt, TagType, WriteOptions}; + /// use lofty::config::WriteOptions; + /// use lofty::prelude::*; + /// use lofty::{Tag, TagType}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); /// /// // ... @@ -99,9 +101,11 @@ impl WriteOptions { /// # Examples /// /// ```rust,no_run - /// use lofty::{Tag, TagExt, TagType, WriteOptions}; + /// use lofty::config::WriteOptions; + /// use lofty::prelude::*; + /// use lofty::{Tag, TagType}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); /// /// // ... @@ -127,9 +131,11 @@ impl WriteOptions { /// # Examples /// /// ```rust,no_run - /// use lofty::{Tag, TagExt, TagType, WriteOptions}; + /// use lofty::config::WriteOptions; + /// use lofty::prelude::*; + /// use lofty::{Tag, TagType}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); /// /// // ... diff --git a/src/file.rs b/src/file.rs index 859a0304b..fb6f70fd4 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,11 +1,9 @@ +use crate::config::{global_options, ParseOptions, WriteOptions}; use crate::error::Result; -use crate::global_options::global_options; -use crate::probe::ParseOptions; use crate::properties::FileProperties; use crate::resolve::custom_resolvers; use crate::tag::{Tag, TagType}; use crate::traits::TagExt; -use crate::write_options::WriteOptions; use std::ffi::OsStr; use std::fs::{File, OpenOptions}; diff --git a/src/flac/mod.rs b/src/flac/mod.rs index 46f21b988..4ff7642c8 100644 --- a/src/flac/mod.rs +++ b/src/flac/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod properties; mod read; pub(crate) mod write; +use crate::config::WriteOptions; use crate::error::Result; use crate::file::{FileType, TaggedFile}; use crate::id3::v2::tag::Id3v2Tag; @@ -16,7 +17,6 @@ use crate::ogg::tag::VorbisCommentsRef; use crate::ogg::{OggPictureStorage, VorbisComments}; use crate::picture::{Picture, PictureInformation}; use crate::traits::TagExt; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::Seek; diff --git a/src/flac/read.rs b/src/flac/read.rs index 97282d851..db961d3a9 100644 --- a/src/flac/read.rs +++ b/src/flac/read.rs @@ -1,6 +1,7 @@ use super::block::Block; use super::properties::FlacProperties; use super::FlacFile; +use crate::config::{ParseOptions, ParsingMode}; use crate::error::Result; use crate::flac::block::{ BLOCK_ID_PADDING, BLOCK_ID_PICTURE, BLOCK_ID_SEEKTABLE, BLOCK_ID_STREAMINFO, @@ -11,7 +12,6 @@ use crate::id3::{find_id3v2, FindId3v2Config, ID3FindResults}; use crate::macros::decode_err; use crate::ogg::read::read_comments; use crate::picture::Picture; -use crate::probe::{ParseOptions, ParsingMode}; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/flac/write.rs b/src/flac/write.rs index 321e2d750..d043c53be 100644 --- a/src/flac/write.rs +++ b/src/flac/write.rs @@ -1,12 +1,12 @@ use super::block::Block; use super::read::verify_flac; +use crate::config::WriteOptions; use crate::error::Result; use crate::macros::{err, try_vec}; use crate::ogg::tag::VorbisCommentsRef; use crate::ogg::write::create_comments; use crate::picture::{Picture, PictureInformation}; use crate::tag::{Tag, TagType}; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Cursor, Read, Seek, SeekFrom, Write}; diff --git a/src/id3/v1/tag.rs b/src/id3/v1/tag.rs index 6dbae3925..84f88f08f 100644 --- a/src/id3/v1/tag.rs +++ b/src/id3/v1/tag.rs @@ -1,9 +1,9 @@ +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::id3::v1::constants::GENRES; use crate::tag::item::{ItemKey, ItemValue, TagItem}; use crate::tag::{Tag, TagType}; use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; -use crate::write_options::WriteOptions; use std::borrow::Cow; use std::fs::File; @@ -440,9 +440,10 @@ impl<'a> Id3v1TagRef<'a> { #[cfg(test)] mod tests { + use crate::config::WriteOptions; use crate::id3::v1::Id3v1Tag; use crate::prelude::*; - use crate::{Tag, TagType, WriteOptions}; + use crate::{Tag, TagType}; #[test] fn parse_id3v1() { diff --git a/src/id3/v1/write.rs b/src/id3/v1/write.rs index 0efd21d2d..188ea3b24 100644 --- a/src/id3/v1/write.rs +++ b/src/id3/v1/write.rs @@ -1,9 +1,9 @@ use super::tag::Id3v1TagRef; +use crate::config::WriteOptions; use crate::error::Result; use crate::id3::{find_id3v1, ID3FindResults}; use crate::macros::err; use crate::probe::Probe; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Cursor, Seek, Write}; diff --git a/src/id3/v2/frame/content.rs b/src/id3/v2/frame/content.rs index e7607356f..6c8d84ead 100644 --- a/src/id3/v2/frame/content.rs +++ b/src/id3/v2/frame/content.rs @@ -1,3 +1,4 @@ +use crate::config::ParsingMode; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::frame::FrameValue; use crate::id3::v2::header::Id3v2Version; @@ -7,7 +8,6 @@ use crate::id3::v2::items::{ TextInformationFrame, UniqueFileIdentifierFrame, UnsynchronizedTextFrame, UrlLinkFrame, }; use crate::macros::err; -use crate::probe::ParsingMode; use crate::util::text::TextEncoding; use std::io::Read; diff --git a/src/id3/v2/frame/read.rs b/src/id3/v2/frame/read.rs index b0b570958..8ba2aa128 100644 --- a/src/id3/v2/frame/read.rs +++ b/src/id3/v2/frame/read.rs @@ -1,12 +1,12 @@ use super::header::{parse_header, parse_v2_header}; use super::Frame; +use crate::config::ParsingMode; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::frame::content::parse_content; use crate::id3::v2::header::Id3v2Version; use crate::id3::v2::util::synchsafe::{SynchsafeInteger, UnsynchronizedStream}; use crate::id3::v2::{FrameFlags, FrameId, FrameValue}; use crate::macros::try_vec; -use crate::probe::ParsingMode; use std::io::Read; diff --git a/src/id3/v2/items/relative_volume_adjustment_frame.rs b/src/id3/v2/items/relative_volume_adjustment_frame.rs index 9aa8c10dc..effbd17db 100644 --- a/src/id3/v2/items/relative_volume_adjustment_frame.rs +++ b/src/id3/v2/items/relative_volume_adjustment_frame.rs @@ -1,6 +1,6 @@ +use crate::config::ParsingMode; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::macros::try_vec; -use crate::probe::ParsingMode; use crate::util::text::{decode_text, encode_text, TextDecodeOptions, TextEncoding}; use std::collections::HashMap; @@ -202,8 +202,8 @@ impl RelativeVolumeAdjustmentFrame { #[cfg(test)] mod tests { + use crate::config::ParsingMode; use crate::id3::v2::{ChannelInformation, ChannelType, RelativeVolumeAdjustmentFrame}; - use crate::ParsingMode; use std::collections::HashMap; use std::io::Read; diff --git a/src/id3/v2/items/unique_file_identifier.rs b/src/id3/v2/items/unique_file_identifier.rs index ca3a75d0c..cb373d43d 100644 --- a/src/id3/v2/items/unique_file_identifier.rs +++ b/src/id3/v2/items/unique_file_identifier.rs @@ -1,6 +1,6 @@ +use crate::config::ParsingMode; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::macros::parse_mode_choice; -use crate::probe::ParsingMode; use crate::util::text::{decode_text, encode_text, TextDecodeOptions, TextEncoding}; use std::hash::{Hash, Hasher}; @@ -78,8 +78,8 @@ impl Hash for UniqueFileIdentifierFrame { mod tests { #[test] fn issue_204_invalid_ufid_parsing_mode_best_attempt() { + use crate::config::ParsingMode; use crate::id3::v2::UniqueFileIdentifierFrame; - use crate::ParsingMode; let ufid_no_owner = UniqueFileIdentifierFrame { owner: String::new(), diff --git a/src/id3/v2/read.rs b/src/id3/v2/read.rs index 622b8ed7b..d0775301a 100644 --- a/src/id3/v2/read.rs +++ b/src/id3/v2/read.rs @@ -1,9 +1,9 @@ use super::frame::read::ParsedFrame; use super::header::Id3v2Header; use super::tag::Id3v2Tag; +use crate::config::ParsingMode; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::util::synchsafe::UnsynchronizedStream; -use crate::probe::ParsingMode; use std::io::Read; @@ -104,8 +104,9 @@ where #[test] fn zero_size_id3v2() { + use crate::config::ParsingMode; use crate::id3::v2::header::Id3v2Header; - use crate::ParsingMode; + use std::io::Cursor; let mut f = Cursor::new(std::fs::read("tests/tags/assets/id3v2/zero.id3v2").unwrap()); @@ -115,9 +116,9 @@ fn zero_size_id3v2() { #[test] fn bad_frame_id_relaxed_id3v2() { + use crate::config::ParsingMode; use crate::id3::v2::header::Id3v2Header; use crate::prelude::*; - use crate::ParsingMode; use std::io::Cursor; diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 144e3c022..81feae692 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -4,6 +4,7 @@ mod tests; use super::frame::id::FrameId; use super::frame::{Frame, FrameFlags, FrameValue, EMPTY_CONTENT_DESCRIPTOR, UNKNOWN_LANGUAGE}; use super::header::{Id3v2TagFlags, Id3v2Version}; +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::id3::v1::GENRES; use crate::id3::v2::frame::{FrameRef, MUSICBRAINZ_UFID_OWNER}; @@ -21,7 +22,6 @@ use crate::tag::item::{ItemKey, ItemValue, TagItem}; use crate::tag::{try_parse_year, Tag, TagType}; use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding}; -use crate::write_options::WriteOptions; use std::borrow::Cow; use std::fs::File; diff --git a/src/id3/v2/tag/tests.rs b/src/id3/v2/tag/tests.rs index 12183e8f4..940a7f5df 100644 --- a/src/id3/v2/tag/tests.rs +++ b/src/id3/v2/tag/tests.rs @@ -1,8 +1,8 @@ +use crate::config::ParsingMode; use crate::id3::v2::header::Id3v2Header; use crate::id3::v2::items::Popularimeter; use crate::id3::v2::util::pairs::DEFAULT_NUMBER_IN_PAIR; use crate::picture::MimeType; -use crate::probe::ParsingMode; use crate::tag::utils::test_utils::read_path; use super::*; diff --git a/src/id3/v2/write/chunk_file.rs b/src/id3/v2/write/chunk_file.rs index 1ee318edd..f0d383d66 100644 --- a/src/id3/v2/write/chunk_file.rs +++ b/src/id3/v2/write/chunk_file.rs @@ -1,6 +1,6 @@ +use crate::config::WriteOptions; use crate::error::Result; use crate::iff::chunk::Chunks; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Read, Seek, SeekFrom, Write}; diff --git a/src/id3/v2/write/mod.rs b/src/id3/v2/write/mod.rs index b2b07e034..ef6a21b5a 100644 --- a/src/id3/v2/write/mod.rs +++ b/src/id3/v2/write/mod.rs @@ -2,6 +2,7 @@ mod chunk_file; mod frame; use super::Id3v2TagFlags; +use crate::config::WriteOptions; use crate::error::Result; use crate::file::FileType; use crate::id3::v2::frame::FrameRef; @@ -11,7 +12,6 @@ use crate::id3::v2::Id3v2Tag; use crate::id3::{find_id3v2, FindId3v2Config}; use crate::macros::{err, try_vec}; use crate::probe::Probe; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Cursor, Read, Seek, SeekFrom, Write}; @@ -283,9 +283,9 @@ fn calculate_crc(content: &[u8]) -> [u8; 5] { #[cfg(test)] mod tests { + use crate::config::WriteOptions; use crate::id3::v2::{Id3v2Tag, Id3v2TagFlags}; use crate::prelude::*; - use crate::WriteOptions; #[test] fn id3v2_write_crc32() { diff --git a/src/iff/aiff/read.rs b/src/iff/aiff/read.rs index 450ec73e3..c8ffbe033 100644 --- a/src/iff/aiff/read.rs +++ b/src/iff/aiff/read.rs @@ -1,11 +1,11 @@ use super::properties::AiffProperties; use super::tag::{AIFFTextChunks, Comment}; use super::AiffFile; +use crate::config::ParseOptions; use crate::error::Result; use crate::id3::v2::tag::Id3v2Tag; use crate::iff::chunk::Chunks; use crate::macros::{decode_err, err}; -use crate::probe::ParseOptions; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 5bbc0f07c..42bb48fb6 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -1,10 +1,10 @@ +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::iff::chunk::Chunks; use crate::macros::err; use crate::tag::item::{ItemKey, ItemValue, TagItem}; use crate::tag::{Tag, TagType}; use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; -use crate::write_options::WriteOptions; use std::borrow::Cow; use std::fs::File; @@ -483,10 +483,10 @@ where #[cfg(test)] mod tests { + use crate::config::{ParseOptions, WriteOptions}; use crate::iff::aiff::{AIFFTextChunks, Comment}; use crate::prelude::*; - use crate::probe::ParseOptions; - use crate::{ItemKey, ItemValue, Tag, TagItem, TagType, WriteOptions}; + use crate::{ItemValue, Tag, TagItem, TagType}; use std::io::Cursor; diff --git a/src/iff/chunk.rs b/src/iff/chunk.rs index 01719284b..9c59a3c2c 100644 --- a/src/iff/chunk.rs +++ b/src/iff/chunk.rs @@ -1,7 +1,7 @@ +use crate::config::ParsingMode; use crate::error::Result; use crate::id3::v2::tag::Id3v2Tag; use crate::macros::{err, try_vec}; -use crate::probe::ParsingMode; use crate::util::text::utf8_decode; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/iff/wav/read.rs b/src/iff/wav/read.rs index 59e6b4d8e..ceaa033ea 100644 --- a/src/iff/wav/read.rs +++ b/src/iff/wav/read.rs @@ -1,11 +1,11 @@ use super::properties::WavProperties; use super::tag::RIFFInfoList; use super::WavFile; +use crate::config::ParseOptions; use crate::error::Result; use crate::id3::v2::tag::Id3v2Tag; use crate::iff::chunk::Chunks; use crate::macros::decode_err; -use crate::probe::ParseOptions; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index 8e732bd3c..10cd663e8 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -1,11 +1,11 @@ pub(super) mod read; mod write; +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::tag::item::{ItemKey, ItemValue, 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; @@ -348,10 +348,11 @@ pub(crate) fn tagitems_into_riff<'a>( #[cfg(test)] mod tests { + use crate::config::WriteOptions; use crate::iff::chunk::Chunks; use crate::iff::wav::RIFFInfoList; use crate::prelude::*; - use crate::{Tag, TagType, WriteOptions}; + use crate::{Tag, TagType}; use byteorder::LittleEndian; diff --git a/src/iff/wav/tag/write.rs b/src/iff/wav/tag/write.rs index 58f727f3a..5fb38a63f 100644 --- a/src/iff/wav/tag/write.rs +++ b/src/iff/wav/tag/write.rs @@ -1,9 +1,9 @@ use super::RIFFInfoListRef; +use crate::config::WriteOptions; use crate::error::Result; use crate::iff::chunk::Chunks; use crate::iff::wav::read::verify_wav; use crate::macros::err; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Read, Seek, SeekFrom, Write}; diff --git a/src/lib.rs b/src/lib.rs index 8bbe9166d..96899c0ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,10 +152,10 @@ pub(crate) mod _this_is_internal {} pub mod aac; pub mod ape; +pub mod config; pub mod error; pub(crate) mod file; pub mod flac; -pub(crate) mod global_options; pub mod id3; pub mod iff; pub(crate) mod macros; @@ -172,10 +172,8 @@ pub(crate) mod tag; mod traits; mod util; pub mod wavpack; -mod write_options; -pub use crate::probe::{read_from, read_from_path, ParseOptions, ParsingMode, Probe}; -pub use crate::write_options::WriteOptions; +pub use crate::probe::{read_from, read_from_path, Probe}; pub use crate::file::{BoundTaggedFile, FileType, TaggedFile, TaggedFileExt}; pub use crate::picture::{MimeType, Picture, PictureType}; @@ -185,8 +183,6 @@ pub use util::text::TextEncoding; pub use picture::PictureInformation; -pub use global_options::{apply_global_options, GlobalOptions}; - pub use lofty_attr::LoftyFile; pub mod prelude { diff --git a/src/macros.rs b/src/macros.rs index 1a2ededd0..2ec5ff582 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -73,9 +73,9 @@ macro_rules! parse_mode_choice { DEFAULT: $default:expr ) => { match $parse_mode { - $(crate::probe::ParsingMode::Strict => { $strict_handler },)? - $(crate::probe::ParsingMode::BestAttempt => { $best_attempt_handler },)? - $(crate::probe::ParsingMode::Relaxed => { $relaxed_handler },)? + $(crate::config::ParsingMode::Strict => { $strict_handler },)? + $(crate::config::ParsingMode::BestAttempt => { $best_attempt_handler },)? + $(crate::config::ParsingMode::Relaxed => { $relaxed_handler },)? _ => { $default } } }; @@ -86,9 +86,9 @@ macro_rules! parse_mode_choice { $(RELAXED: $relaxed_handler:expr $(,)?)? ) => { match $parse_mode { - $(crate::probe::ParsingMode::Strict => { $strict_handler },)? - $(crate::probe::ParsingMode::BestAttempt => { $best_attempt_handler },)? - $(crate::probe::ParsingMode::Relaxed => { $relaxed_handler },)? + $(crate::config::ParsingMode::Strict => { $strict_handler },)? + $(crate::config::ParsingMode::BestAttempt => { $best_attempt_handler },)? + $(crate::config::ParsingMode::Relaxed => { $relaxed_handler },)? #[allow(unreachable_patterns)] _ => {} } diff --git a/src/mp4/atom_info.rs b/src/mp4/atom_info.rs index 980d0d75a..90085bb65 100644 --- a/src/mp4/atom_info.rs +++ b/src/mp4/atom_info.rs @@ -1,6 +1,6 @@ +use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{err, try_vec}; -use crate::probe::ParsingMode; use crate::tag::item::ItemKey; use crate::tag::TagType; use crate::util::text::utf8_decode; diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 3ab103b45..5520bd128 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -5,13 +5,13 @@ mod r#ref; pub(crate) mod write; use super::AtomIdent; +use crate::config::WriteOptions; use crate::error::LoftyError; use crate::mp4::ilst::atom::AtomDataStorage; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; use crate::tag::item::{ItemKey, ItemValue, TagItem}; use crate::tag::{try_parse_year, Tag, TagType}; use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; -use crate::write_options::WriteOptions; use atom::{AdvisoryRating, Atom, AtomData}; use std::borrow::Cow; @@ -759,6 +759,7 @@ impl From for Ilst { #[cfg(test)] mod tests { + use crate::config::{ParseOptions, ParsingMode, WriteOptions}; use crate::mp4::ilst::atom::AtomDataStorage; use crate::mp4::ilst::TITLE; use crate::mp4::read::AtomReader; @@ -766,9 +767,7 @@ mod tests { use crate::prelude::*; use crate::tag::utils::test_utils; use crate::tag::utils::test_utils::read_path; - use crate::{ - ItemKey, ItemValue, ParseOptions, ParsingMode, Tag, TagItem, TagType, WriteOptions, - }; + use crate::{ItemValue, Tag, TagItem, TagType}; use std::io::{Cursor, Read as _, Seek as _, Write as _}; @@ -853,10 +852,10 @@ mod tests { let len = tag.len(); let cursor = Cursor::new(tag); - let mut reader = AtomReader::new(cursor, crate::ParsingMode::Strict).unwrap(); + let mut reader = AtomReader::new(cursor, ParsingMode::Strict).unwrap(); let parsed_tag = - super::read::parse_ilst(&mut reader, crate::ParsingMode::Strict, len as u64).unwrap(); + super::read::parse_ilst(&mut reader, ParsingMode::Strict, len as u64).unwrap(); assert_eq!(expected_tag, parsed_tag); } @@ -871,15 +870,12 @@ mod tests { .unwrap(); let cursor = Cursor::new(&writer[8..]); - let mut reader = AtomReader::new(cursor, crate::ParsingMode::Strict).unwrap(); + let mut reader = AtomReader::new(cursor, ParsingMode::Strict).unwrap(); // Remove the ilst identifier and size - let temp_parsed_tag = super::read::parse_ilst( - &mut reader, - crate::ParsingMode::Strict, - (writer.len() - 8) as u64, - ) - .unwrap(); + let temp_parsed_tag = + super::read::parse_ilst(&mut reader, ParsingMode::Strict, (writer.len() - 8) as u64) + .unwrap(); assert_eq!(parsed_tag, temp_parsed_tag); } @@ -890,10 +886,9 @@ mod tests { let len = tag.len(); let cursor = Cursor::new(tag); - let mut reader = AtomReader::new(cursor, crate::ParsingMode::Strict).unwrap(); + let mut reader = AtomReader::new(cursor, ParsingMode::Strict).unwrap(); - let ilst = - super::read::parse_ilst(&mut reader, crate::ParsingMode::Strict, len as u64).unwrap(); + let ilst = super::read::parse_ilst(&mut reader, ParsingMode::Strict, len as u64).unwrap(); let tag: Tag = ilst.into(); @@ -1010,14 +1005,11 @@ mod tests { assert_eq!(old_free_size, PADDING_SIZE as u32); let cursor = Cursor::new(ilst_bytes); - let mut reader = AtomReader::new(cursor, crate::ParsingMode::Strict).unwrap(); + let mut reader = AtomReader::new(cursor, ParsingMode::Strict).unwrap(); - ilst = super::read::parse_ilst( - &mut reader, - crate::ParsingMode::Strict, - ilst_bytes.len() as u64, - ) - .unwrap(); + ilst = + super::read::parse_ilst(&mut reader, ParsingMode::Strict, ilst_bytes.len() as u64) + .unwrap(); } let mut file = tempfile::tempfile().unwrap(); diff --git a/src/mp4/ilst/read.rs b/src/mp4/ilst/read.rs index eea7faa69..f07cecabd 100644 --- a/src/mp4/ilst/read.rs +++ b/src/mp4/ilst/read.rs @@ -2,6 +2,7 @@ use super::constants::{ BE_SIGNED_INTEGER, BE_UNSIGNED_INTEGER, BMP, JPEG, PNG, RESERVED, UTF16, UTF8, }; use super::{Atom, AtomData, AtomIdent, Ilst}; +use crate::config::ParsingMode; use crate::error::{LoftyError, Result}; use crate::id3::v1::constants::GENRES; use crate::macros::{err, try_vec}; @@ -10,7 +11,6 @@ use crate::mp4::ilst::atom::AtomDataStorage; use crate::mp4::read::{skip_unneeded, AtomReader}; use crate::picture::{MimeType, Picture, PictureType}; use crate::util::text::{utf16_decode_bytes, utf8_decode}; -use crate::ParsingMode; use std::borrow::Cow; use std::io::{Cursor, Read, Seek, SeekFrom}; diff --git a/src/mp4/ilst/ref.rs b/src/mp4/ilst/ref.rs index 0bd44a999..0e0c5505c 100644 --- a/src/mp4/ilst/ref.rs +++ b/src/mp4/ilst/ref.rs @@ -2,9 +2,9 @@ // Reference Conversions // ********************* +use crate::config::WriteOptions; use crate::error::Result; use crate::mp4::{Atom, AtomData, AtomIdent, Ilst}; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::Write; diff --git a/src/mp4/ilst/write.rs b/src/mp4/ilst/write.rs index f129da726..a49215263 100644 --- a/src/mp4/ilst/write.rs +++ b/src/mp4/ilst/write.rs @@ -1,4 +1,5 @@ use super::r#ref::IlstRef; +use crate::config::{ParseOptions, WriteOptions}; use crate::error::{FileEncodingError, Result}; use crate::file::FileType; use crate::macros::{decode_err, err, try_vec}; @@ -8,8 +9,6 @@ use crate::mp4::read::{atom_tree, meta_is_full, nested_atom, verify_mp4, AtomRea use crate::mp4::write::{AtomWriter, AtomWriterCompanion, ContextualAtom}; use crate::mp4::AtomData; use crate::picture::{MimeType, Picture}; -use crate::probe::ParseOptions; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Cursor, Seek, SeekFrom, Write}; diff --git a/src/mp4/moov.rs b/src/mp4/moov.rs index 885d42cfe..6d2536fa7 100644 --- a/src/mp4/moov.rs +++ b/src/mp4/moov.rs @@ -2,9 +2,9 @@ use super::atom_info::{AtomIdent, AtomInfo}; use super::ilst::read::parse_ilst; use super::ilst::Ilst; use super::read::{meta_is_full, nested_atom, skip_unneeded, AtomReader}; +use crate::config::ParsingMode; use crate::error::Result; use crate::macros::decode_err; -use crate::ParsingMode; use std::io::{Read, Seek}; diff --git a/src/mp4/properties.rs b/src/mp4/properties.rs index 4c27bd79a..7d458d151 100644 --- a/src/mp4/properties.rs +++ b/src/mp4/properties.rs @@ -1,9 +1,9 @@ use super::atom_info::{AtomIdent, AtomInfo}; use super::read::{nested_atom, skip_unneeded, AtomReader}; +use crate::config::ParsingMode; use crate::error::{LoftyError, Result}; use crate::macros::{decode_err, err, try_vec}; use crate::math::RoundedDivision; -use crate::probe::ParsingMode; use crate::properties::FileProperties; use std::io::{Cursor, Read, Seek, SeekFrom}; diff --git a/src/mp4/read.rs b/src/mp4/read.rs index ffe7aa563..457132b7a 100644 --- a/src/mp4/read.rs +++ b/src/mp4/read.rs @@ -2,9 +2,9 @@ use super::atom_info::{AtomIdent, AtomInfo}; use super::moov::Moov; use super::properties::Mp4Properties; use super::Mp4File; +use crate::config::{ParseOptions, ParsingMode}; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{decode_err, err}; -use crate::probe::{ParseOptions, ParsingMode}; use crate::traits::SeekStreamLen; use crate::util::text::utf8_decode_str; diff --git a/src/mp4/write.rs b/src/mp4/write.rs index 6ca52c12c..e5bd7de43 100644 --- a/src/mp4/write.rs +++ b/src/mp4/write.rs @@ -1,7 +1,7 @@ +use crate::config::ParsingMode; use crate::error::Result; use crate::mp4::atom_info::{AtomIdent, AtomInfo, IDENTIFIER_LEN}; use crate::mp4::read::skip_unneeded; -use crate::probe::ParsingMode; use std::cell::{RefCell, RefMut}; use std::fs::File; diff --git a/src/mpeg/read.rs b/src/mpeg/read.rs index 54d36ebba..628e23684 100644 --- a/src/mpeg/read.rs +++ b/src/mpeg/read.rs @@ -1,13 +1,13 @@ use super::header::{cmp_header, search_for_frame_sync, Header, HeaderCmpResult, XingHeader}; use super::{MpegFile, MpegProperties}; use crate::ape::header::read_ape_header; +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, find_lyrics3v2, FindId3v2Config, ID3FindResults}; use crate::macros::{decode_err, err}; use crate::mpeg::header::HEADER_MASK; -use crate::probe::{ParseOptions, ParsingMode}; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/musepack/read.rs b/src/musepack/read.rs index a9365460e..09fd525d7 100644 --- a/src/musepack/read.rs +++ b/src/musepack/read.rs @@ -2,10 +2,10 @@ use super::sv4to6::MpcSv4to6Properties; use super::sv7::MpcSv7Properties; use super::sv8::MpcSv8Properties; use super::{MpcFile, MpcProperties, MpcStreamVersion}; +use crate::config::ParseOptions; use crate::error::Result; use crate::id3::v2::read::parse_id3v2; use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, FindId3v2Config, ID3FindResults}; -use crate::probe::ParseOptions; use crate::traits::SeekStreamLen; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/musepack/sv4to6/properties.rs b/src/musepack/sv4to6/properties.rs index 18f60f66c..9f5b1c786 100644 --- a/src/musepack/sv4to6/properties.rs +++ b/src/musepack/sv4to6/properties.rs @@ -1,7 +1,7 @@ +use crate::config::ParsingMode; use crate::error::Result; use crate::macros::{decode_err, parse_mode_choice}; use crate::musepack::constants::{MPC_DECODER_SYNTH_DELAY, MPC_FRAME_LENGTH}; -use crate::probe::ParsingMode; use crate::properties::FileProperties; use std::io::Read; diff --git a/src/musepack/sv8/properties.rs b/src/musepack/sv8/properties.rs index bc26fcb59..4ad1fa184 100644 --- a/src/musepack/sv8/properties.rs +++ b/src/musepack/sv8/properties.rs @@ -1,7 +1,7 @@ use super::read::PacketReader; +use crate::config::ParsingMode; use crate::error::Result; use crate::musepack::constants::FREQUENCY_TABLE; -use crate::probe::ParsingMode; use crate::properties::FileProperties; use std::io::Read; diff --git a/src/musepack/sv8/read.rs b/src/musepack/sv8/read.rs index 913b89580..93c745b04 100644 --- a/src/musepack/sv8/read.rs +++ b/src/musepack/sv8/read.rs @@ -1,7 +1,7 @@ use super::properties::{EncoderInfo, MpcSv8Properties, ReplayGain, StreamHeader}; +use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{decode_err, parse_mode_choice}; -use crate::probe::ParsingMode; use std::io::Read; use std::time::Duration; diff --git a/src/ogg/opus/mod.rs b/src/ogg/opus/mod.rs index a30c197b2..4aa883346 100644 --- a/src/ogg/opus/mod.rs +++ b/src/ogg/opus/mod.rs @@ -2,9 +2,9 @@ pub(super) mod properties; use super::find_last_page; use super::tag::VorbisComments; +use crate::config::ParseOptions; use crate::error::Result; use crate::ogg::constants::{OPUSHEAD, OPUSTAGS}; -use crate::probe::ParseOptions; use properties::OpusProperties; use std::io::{Read, Seek}; diff --git a/src/ogg/read.rs b/src/ogg/read.rs index 0e9ba680f..17c26364b 100644 --- a/src/ogg/read.rs +++ b/src/ogg/read.rs @@ -1,9 +1,9 @@ use super::tag::VorbisComments; use super::verify_signature; +use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{decode_err, err, parse_mode_choice}; use crate::picture::{MimeType, Picture, PictureInformation, PictureType}; -use crate::probe::ParsingMode; use crate::util::text::{utf16_decode, utf8_decode, utf8_decode_str}; use std::borrow::Cow; diff --git a/src/ogg/speex/mod.rs b/src/ogg/speex/mod.rs index 9a79398e9..4af2b333d 100644 --- a/src/ogg/speex/mod.rs +++ b/src/ogg/speex/mod.rs @@ -1,9 +1,9 @@ pub(super) mod properties; use super::tag::VorbisComments; +use crate::config::ParseOptions; use crate::error::Result; use crate::ogg::constants::SPEEXHEADER; -use crate::probe::ParseOptions; use properties::SpeexProperties; use std::io::{Read, Seek}; diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index e5a6b9c5a..d9b2291c6 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -1,3 +1,4 @@ +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::file::FileType; use crate::macros::err; @@ -8,7 +9,6 @@ use crate::probe::Probe; use crate::tag::item::{ItemKey, ItemValue, 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; @@ -693,9 +693,10 @@ pub(crate) fn create_vorbis_comments_ref( #[cfg(test)] mod tests { + use crate::config::{ParsingMode, WriteOptions}; use crate::ogg::{OggPictureStorage, VorbisComments}; use crate::prelude::*; - use crate::{ItemKey, ItemValue, ParsingMode, Tag, TagItem, TagType, WriteOptions}; + use crate::{ItemValue, Tag, TagItem, TagType}; fn read_tag(tag: &[u8]) -> VorbisComments { let mut reader = std::io::Cursor::new(tag); diff --git a/src/ogg/vorbis/mod.rs b/src/ogg/vorbis/mod.rs index b01adeac4..6f401be8e 100644 --- a/src/ogg/vorbis/mod.rs +++ b/src/ogg/vorbis/mod.rs @@ -2,9 +2,9 @@ pub(super) mod properties; use super::find_last_page; use super::tag::VorbisComments; +use crate::config::ParseOptions; use crate::error::Result; use crate::ogg::constants::{VORBIS_COMMENT_HEAD, VORBIS_IDENT_HEAD}; -use crate::probe::ParseOptions; use properties::VorbisProperties; use std::io::{Read, Seek}; diff --git a/src/ogg/write.rs b/src/ogg/write.rs index f3a945e21..194c7886e 100644 --- a/src/ogg/write.rs +++ b/src/ogg/write.rs @@ -1,4 +1,5 @@ use super::verify_signature; +use crate::config::WriteOptions; use crate::error::Result; use crate::file::FileType; use crate::macros::{decode_err, err, try_vec}; @@ -6,7 +7,6 @@ use crate::ogg::constants::{OPUSTAGS, VORBIS_COMMENT_HEAD}; use crate::ogg::tag::{create_vorbis_comments_ref, VorbisCommentsRef}; use crate::picture::{Picture, PictureInformation}; use crate::tag::{Tag, TagType}; -use crate::write_options::WriteOptions; use std::fs::File; use std::io::{Cursor, Read, Seek, SeekFrom, Write}; diff --git a/src/picture.rs b/src/picture.rs index e9d5b6851..9686ea294 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -1,6 +1,6 @@ +use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::err; -use crate::probe::ParsingMode; use crate::util::text::utf8_decode_str; use std::borrow::Cow; diff --git a/src/probe.rs b/src/probe.rs index 6e691dfd7..d59ffbabe 100644 --- a/src/probe.rs +++ b/src/probe.rs @@ -1,9 +1,9 @@ use crate::aac::AacFile; use crate::ape::ApeFile; +use crate::config::{global_options, ParseOptions}; use crate::error::Result; use crate::file::{AudioFile, FileType, FileTypeGuessResult, TaggedFile}; use crate::flac::FlacFile; -use crate::global_options::global_options; use crate::iff::aiff::AiffFile; use crate::iff::wav::WavFile; use crate::macros::err; @@ -21,160 +21,6 @@ use std::fs::File; use std::io::{BufReader, Cursor, Read, Seek, SeekFrom}; use std::path::Path; -/// 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::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::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::{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::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::{ParseOptions, ParsingMode, Probe}; -/// -/// # fn main() -> lofty::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, -} - /// A format agnostic reader /// /// This provides a way to determine the [`FileType`] of a reader, for when a concrete @@ -687,9 +533,9 @@ where #[cfg(test)] mod tests { - use crate::{FileType, GlobalOptions, Probe}; + use crate::config::{GlobalOptions, ParseOptions}; + use crate::{FileType, Probe}; - use lofty::ParseOptions; use std::fs::File; #[test] @@ -784,7 +630,7 @@ mod tests { let parse_options = ParseOptions::new().read_properties(false); let mut global_options = GlobalOptions::new().allocation_limit(50); - crate::global_options::apply_global_options(global_options); + crate::config::apply_global_options(global_options); // An allocation with a size of 40 bytes should be ok let within_limits = create_fake_mp3(40); @@ -802,7 +648,7 @@ mod tests { // Now test the default allocation limit (16MB), which should of course be ok with 60 bytes global_options.allocation_limit = GlobalOptions::DEFAULT_ALLOCATION_LIMIT; - crate::global_options::apply_global_options(global_options); + crate::config::apply_global_options(global_options); let probe = Probe::new(std::io::Cursor::new(&too_big)) .set_file_type(FileType::Mpeg) diff --git a/src/properties/tests.rs b/src/properties/tests.rs index 7112bf3d1..1a06c2bd7 100644 --- a/src/properties/tests.rs +++ b/src/properties/tests.rs @@ -1,5 +1,6 @@ use crate::aac::{AACProperties, AacFile}; use crate::ape::{ApeFile, ApeProperties}; +use crate::config::ParseOptions; use crate::file::AudioFile; use crate::flac::{FlacFile, FlacProperties}; use crate::iff::aiff::{AiffFile, AiffProperties}; @@ -13,7 +14,6 @@ use crate::musepack::{MpcFile, MpcProperties}; use crate::ogg::{ OpusFile, OpusProperties, SpeexFile, SpeexProperties, VorbisFile, VorbisProperties, }; -use crate::probe::ParseOptions; use crate::properties::ChannelMask; use crate::wavpack::{WavPackFile, WavPackProperties}; diff --git a/src/resolve.rs b/src/resolve.rs index fb759e95f..321fe62fb 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -1,9 +1,9 @@ //! Tools to create custom file resolvers //! //! For a full example of a custom resolver, see [this](https://github.com/Serial-ATA/lofty-rs/tree/main/examples/custom_resolver). +use crate::config::ParseOptions; use crate::error::Result; use crate::file::{AudioFile, FileType, TaggedFile}; -use crate::probe::ParseOptions; use crate::tag::TagType; use std::collections::HashMap; @@ -129,10 +129,9 @@ pub fn register_custom_resolver(name: &'static str) { #[cfg(test)] mod tests { + use crate::config::{GlobalOptions, ParseOptions}; use crate::file::{FileType, TaggedFileExt}; - use crate::global_options::GlobalOptions; use crate::id3::v2::Id3v2Tag; - use crate::probe::ParseOptions; use crate::properties::FileProperties; use crate::resolve::{register_custom_resolver, FileResolver}; use crate::tag::TagType; @@ -196,7 +195,7 @@ mod tests { register_custom_resolver::("MyFile"); let global_options = GlobalOptions::new().use_custom_resolvers(true); - crate::apply_global_options(global_options); + crate::config::apply_global_options(global_options); let path = "examples/custom_resolver/test_asset.myfile"; let read = crate::read_from_path(path).unwrap(); diff --git a/src/tag/mod.rs b/src/tag/mod.rs index b61158755..87cd00afa 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -1,6 +1,7 @@ pub(crate) mod item; pub(crate) mod utils; +use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::file::FileType; use crate::macros::err; @@ -9,7 +10,6 @@ use crate::probe::Probe; use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; use item::{ItemKey, ItemValue, TagItem}; -use crate::WriteOptions; use std::borrow::Cow; use std::fs::{File, OpenOptions}; use std::io::Write; @@ -663,9 +663,10 @@ impl TagType { #[cfg(test)] mod tests { use super::try_parse_year; + use crate::config::WriteOptions; use crate::prelude::*; use crate::tag::utils::test_utils::read_path; - use crate::{Picture, PictureType, Tag, TagType, WriteOptions}; + use crate::{Picture, PictureType, Tag, TagType}; use std::io::{Seek, Write}; use std::process::Command; diff --git a/src/tag/utils.rs b/src/tag/utils.rs index 9ecc7c279..10673b523 100644 --- a/src/tag/utils.rs +++ b/src/tag/utils.rs @@ -1,8 +1,8 @@ +use crate::config::WriteOptions; use crate::error::Result; use crate::file::FileType; use crate::macros::err; use crate::tag::{Tag, TagType}; -use crate::write_options::WriteOptions; use crate::{aac, ape, flac, iff, mpeg, musepack, wavpack}; use crate::id3::v1::tag::Id3v1TagRef; diff --git a/src/traits.rs b/src/traits.rs index ec9e66641..973dfb81b 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -118,8 +118,8 @@ accessor_trait! { [year ], [comment ], String>, } +use crate::config::WriteOptions; use crate::tag::Tag; -use crate::write_options::WriteOptions; use std::fs::File; use std::path::Path; diff --git a/src/util/alloc.rs b/src/util/alloc.rs index 0fe53c912..42fd6b1db 100644 --- a/src/util/alloc.rs +++ b/src/util/alloc.rs @@ -1,7 +1,7 @@ use crate::error::Result; use crate::macros::err; -use crate::global_options::global_options; +use crate::config::global_options; /// Provides the `fallible_repeat` method on `Vec` /// diff --git a/src/wavpack/properties.rs b/src/wavpack/properties.rs index 1f01799b4..5eb5792cd 100644 --- a/src/wavpack/properties.rs +++ b/src/wavpack/properties.rs @@ -1,6 +1,6 @@ +use crate::config::ParsingMode; use crate::error::Result; use crate::macros::{decode_err, err, parse_mode_choice, try_vec}; -use crate::probe::ParsingMode; use crate::properties::{ChannelMask, FileProperties}; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/wavpack/read.rs b/src/wavpack/read.rs index 2d402fe20..b2ab8817f 100644 --- a/src/wavpack/read.rs +++ b/src/wavpack/read.rs @@ -1,8 +1,8 @@ use super::properties::WavPackProperties; use super::WavPackFile; +use crate::config::ParseOptions; use crate::error::Result; use crate::id3::{find_id3v1, find_lyrics3v2, ID3FindResults}; -use crate::probe::ParseOptions; use std::io::{Read, Seek, SeekFrom}; diff --git a/tests/files/aac.rs b/tests/files/aac.rs index 13a0a9d21..4f6170e20 100644 --- a/tests/files/aac.rs +++ b/tests/files/aac.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/aiff.rs b/tests/files/aiff.rs index 30a3316bf..a1d495161 100644 --- a/tests/files/aiff.rs +++ b/tests/files/aiff.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/ape.rs b/tests/files/ape.rs index 32b48e064..9ed0961ef 100644 --- a/tests/files/ape.rs +++ b/tests/files/ape.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/flac.rs b/tests/files/flac.rs index 954938b13..a9401280d 100644 --- a/tests/files/flac.rs +++ b/tests/files/flac.rs @@ -1,6 +1,6 @@ +use lofty::config::{ParseOptions, ParsingMode}; use lofty::flac::FlacFile; use lofty::prelude::*; -use lofty::{ParseOptions, ParsingMode}; use std::fs::File; use std::io::Seek; diff --git a/tests/files/mp4.rs b/tests/files/mp4.rs index abff918b8..eccb6e753 100644 --- a/tests/files/mp4.rs +++ b/tests/files/mp4.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/mpc.rs b/tests/files/mpc.rs index 69cee5528..cf7d707bd 100644 --- a/tests/files/mpc.rs +++ b/tests/files/mpc.rs @@ -1,9 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::musepack::MpcFile; use lofty::prelude::*; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFile, TaggedFileExt, -}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType, TaggedFile}; use std::io::{Seek, Write}; diff --git a/tests/files/mpeg.rs b/tests/files/mpeg.rs index 6b9c40407..e7ebd5857 100644 --- a/tests/files/mpeg.rs +++ b/tests/files/mpeg.rs @@ -1,11 +1,9 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::{ParseOptions, WriteOptions}; use lofty::id3::v2::{Frame, FrameFlags, FrameId, FrameValue, Id3v2Tag, KeyValueFrame}; use lofty::mpeg::MpegFile; use lofty::prelude::*; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, Tag, TagItem, TagType, TaggedFileExt, - WriteOptions, -}; +use lofty::{FileType, ItemValue, Probe, Tag, TagItem, TagType}; use std::borrow::Cow; use std::io::{Seek, Write}; diff --git a/tests/files/ogg.rs b/tests/files/ogg.rs index 9528eb361..aaaef0714 100644 --- a/tests/files/ogg.rs +++ b/tests/files/ogg.rs @@ -1,9 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::{ParseOptions, WriteOptions}; use lofty::prelude::*; -use lofty::{ - FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt, - WriteOptions, -}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/util/mod.rs b/tests/files/util/mod.rs index 802612b66..29138282b 100644 --- a/tests/files/util/mod.rs +++ b/tests/files/util/mod.rs @@ -69,7 +69,7 @@ macro_rules! set_artist { $file_write.rewind().unwrap(); - $tag.save_to(&mut $file_write, lofty::WriteOptions::default()) + $tag.save_to(&mut $file_write, lofty::config::WriteOptions::default()) .unwrap(); }; } @@ -80,7 +80,7 @@ macro_rules! remove_tag { let mut file = temp_file!($path); let tagged_file = lofty::Probe::new(&mut file) - .options(lofty::ParseOptions::new().read_properties(false)) + .options(lofty::config::ParseOptions::new().read_properties(false)) .guess_file_type() .unwrap() .read() @@ -94,7 +94,7 @@ macro_rules! remove_tag { file.rewind().unwrap(); let tagged_file = lofty::Probe::new(&mut file) - .options(lofty::ParseOptions::new().read_properties(false)) + .options(lofty::config::ParseOptions::new().read_properties(false)) .guess_file_type() .unwrap() .read() diff --git a/tests/files/wav.rs b/tests/files/wav.rs index 1bf888a12..9e3ccf094 100644 --- a/tests/files/wav.rs +++ b/tests/files/wav.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index 8e11de576..93a4b141a 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -1,6 +1,7 @@ use crate::{set_artist, temp_file, verify_artist}; +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::{FileType, ItemKey, ItemValue, ParseOptions, Probe, TagItem, TagType, TaggedFileExt}; +use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/zero_sized.rs b/tests/files/zero_sized.rs index 075985010..518945d12 100644 --- a/tests/files/zero_sized.rs +++ b/tests/files/zero_sized.rs @@ -1,11 +1,11 @@ use lofty::ape::ApeFile; +use lofty::config::{ParseOptions, ParsingMode}; use lofty::flac::FlacFile; use lofty::iff::aiff::AiffFile; use lofty::iff::wav::WavFile; use lofty::mp4::Mp4File; use lofty::mpeg::MpegFile; use lofty::prelude::*; -use lofty::{ParseOptions, ParsingMode}; fn read_file_with_properties(path: &str) -> bool { let res = ::read_from( diff --git a/tests/fuzz/id3v2.rs b/tests/fuzz/id3v2.rs index f66b5c2e8..33cc7b1ca 100644 --- a/tests/fuzz/id3v2.rs +++ b/tests/fuzz/id3v2.rs @@ -18,7 +18,7 @@ fn overflow1() { 50, 5, 5, 5, 26, 5, 5, 25, 6, 6, 25, 26, 246, 25, 25, 129, 6, 151, 3, 252, 56, 0, 53, 56, 55, 52, ]; - let _local0 = ::default(); + let _local0 = ::default(); let _local1_param0_helper1 = &mut (&data[..]); let _: lofty::error::Result< std::option::Option, diff --git a/tests/fuzz/main.rs b/tests/fuzz/main.rs index 2141671c8..4d0383b4c 100644 --- a/tests/fuzz/main.rs +++ b/tests/fuzz/main.rs @@ -1,5 +1,5 @@ +use lofty::config::ParseOptions; use lofty::prelude::*; -use lofty::ParseOptions; use std::io::Cursor; use std::path::Path; diff --git a/tests/fuzz/mpegfile_read_from.rs b/tests/fuzz/mpegfile_read_from.rs index d51b48af0..ff9f89c71 100644 --- a/tests/fuzz/mpegfile_read_from.rs +++ b/tests/fuzz/mpegfile_read_from.rs @@ -1,7 +1,7 @@ use crate::{get_reader, oom_test}; +use lofty::config::ParseOptions; use lofty::mpeg::MpegFile; use lofty::prelude::*; -use lofty::ParseOptions; #[test] fn crash1() { diff --git a/tests/hound.rs b/tests/hound.rs index ad9b7f5a0..83846c961 100644 --- a/tests/hound.rs +++ b/tests/hound.rs @@ -1,7 +1,7 @@ +use lofty::config::ParseOptions; use lofty::error::Result; use lofty::iff::wav::WavFile; use lofty::prelude::*; -use lofty::ParseOptions; use hound::WavReader; diff --git a/tests/picture/format_parsers.rs b/tests/picture/format_parsers.rs index b963c028c..6265f9663 100644 --- a/tests/picture/format_parsers.rs +++ b/tests/picture/format_parsers.rs @@ -1,5 +1,6 @@ +use lofty::config::ParsingMode; use lofty::id3::v2::{AttachedPictureFrame, Id3v2Version}; -use lofty::{ParsingMode, Picture, PictureInformation, PictureType, TextEncoding}; +use lofty::{Picture, PictureInformation, PictureType, TextEncoding}; use std::fs::File; use std::io::Read; From 11f6d44e1e82d017ae09d7e02d49746938e84930 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 12:54:10 -0400 Subject: [PATCH 03/22] misc: Separate module definitions --- src/lib.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 96899c0ed..b766a6a7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,20 +150,11 @@ extern crate self as lofty; pub(crate) mod _this_is_internal {} -pub mod aac; -pub mod ape; pub mod config; pub mod error; pub(crate) mod file; -pub mod flac; -pub mod id3; -pub mod iff; pub(crate) mod macros; mod math; -pub mod mp4; -pub mod mpeg; -pub mod musepack; -pub mod ogg; pub(crate) mod picture; mod probe; pub mod properties; @@ -171,6 +162,16 @@ pub mod resolve; pub(crate) mod tag; mod traits; mod util; + +pub mod aac; +pub mod ape; +pub mod flac; +pub mod id3; +pub mod iff; +pub mod mp4; +pub mod mpeg; +pub mod musepack; +pub mod ogg; pub mod wavpack; pub use crate::probe::{read_from, read_from_path, Probe}; From 1f7b64a1fdaea01750c81782a07df378ca31982a Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 13:08:51 -0400 Subject: [PATCH 04/22] file: Split up `file` module --- src/file/audio_file.rs | 87 ++++++ src/file/file_type.rs | 320 +++++++++++++++++++++ src/file/mod.rs | 11 + src/{file.rs => file/tagged_file.rs} | 401 +-------------------------- src/lib.rs | 2 +- 5 files changed, 423 insertions(+), 398 deletions(-) create mode 100644 src/file/audio_file.rs create mode 100644 src/file/file_type.rs create mode 100644 src/file/mod.rs rename src/{file.rs => file/tagged_file.rs} (58%) diff --git a/src/file/audio_file.rs b/src/file/audio_file.rs new file mode 100644 index 000000000..3f47b397d --- /dev/null +++ b/src/file/audio_file.rs @@ -0,0 +1,87 @@ +use super::tagged_file::TaggedFile; +use crate::config::{ParseOptions, WriteOptions}; +use crate::error::Result; +use crate::tag::TagType; + +use std::fs::{File, OpenOptions}; +use std::io::{Read, Seek}; +use std::path::Path; + +/// Provides various methods for interaction with a file +pub trait AudioFile: Into { + /// The struct the file uses for audio properties + /// + /// Not all formats can use [`FileProperties`] since they may contain additional information + type Properties; + + /// Read a file from a reader + /// + /// # Errors + /// + /// Errors depend on the file and tags being read. See [`LoftyError`](crate::LoftyError) + fn read_from(reader: &mut R, parse_options: ParseOptions) -> Result + where + R: Read + Seek, + Self: Sized; + + /// Attempts to write all tags to a path + /// + /// # Errors + /// + /// * `path` does not exist + /// * `path` is not writable + /// * See [`AudioFile::save_to`] + /// + /// # Examples + /// + /// ```rust,no_run + /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; + /// + /// # fn main() -> lofty::Result<()> { + /// # let path = "tests/files/assets/minimal/full_test.mp3"; + /// let mut tagged_file = lofty::read_from_path(path)?; + /// + /// // Edit the tags + /// + /// tagged_file.save_to_path(path, WriteOptions::default())?; + /// # Ok(()) } + /// ``` + fn save_to_path(&self, path: impl AsRef, write_options: WriteOptions) -> Result<()> { + self.save_to( + &mut OpenOptions::new().read(true).write(true).open(path)?, + write_options, + ) + } + + /// Attempts to write all tags to a file + /// + /// # Errors + /// + /// See [`Tag::save_to`], however this is applicable to every tag in the file. + /// + /// # Examples + /// + /// ```rust,no_run + /// use lofty::config::WriteOptions; + /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; + /// use std::fs::OpenOptions; + /// + /// # fn main() -> lofty::error::Result<()> { + /// # let path = "tests/files/assets/minimal/full_test.mp3"; + /// let mut tagged_file = lofty::read_from_path(path)?; + /// + /// // Edit the tags + /// + /// let mut file = OpenOptions::new().read(true).write(true).open(path)?; + /// tagged_file.save_to(&mut file, WriteOptions::default())?; + /// # Ok(()) } + /// ``` + fn save_to(&self, file: &mut File, write_options: WriteOptions) -> Result<()>; + + /// Returns a reference to the file's properties + fn properties(&self) -> &Self::Properties; + /// Checks if the file contains any tags + fn contains_tag(&self) -> bool; + /// Checks if the file contains the given [`TagType`] + fn contains_tag_type(&self, tag_type: TagType) -> bool; +} diff --git a/src/file/file_type.rs b/src/file/file_type.rs new file mode 100644 index 000000000..2f03f2b6d --- /dev/null +++ b/src/file/file_type.rs @@ -0,0 +1,320 @@ +use crate::config::global_options; +use crate::resolve::custom_resolvers; +use crate::tag::TagType; + +use std::ffi::OsStr; +use std::path::Path; + +/// The type of file read +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +#[allow(missing_docs)] +#[non_exhaustive] +pub enum FileType { + Aac, + Aiff, + Ape, + Flac, + Mpeg, + Mp4, + Mpc, + Opus, + Vorbis, + Speex, + Wav, + WavPack, + Custom(&'static str), +} + +impl FileType { + /// Returns the file type's "primary" [`TagType`], or the one most likely to be used in the target format + /// + /// | [`FileType`] | [`TagType`] | + /// |-----------------------------------|------------------| + /// | `Aac`, `Aiff`, `Mp3`, `Wav` | `Id3v2` | + /// | `Ape` , `Mpc`, `WavPack` | `Ape` | + /// | `Flac`, `Opus`, `Vorbis`, `Speex` | `VorbisComments` | + /// | `Mp4` | `Mp4Ilst` | + /// + /// # Panics + /// + /// If an unregistered `FileType` ([`FileType::Custom`]) is encountered. See [`register_custom_resolver`](crate::resolve::register_custom_resolver). + /// + /// # Examples + /// + /// ```rust + /// use lofty::{FileType, TagType}; + /// + /// let file_type = FileType::Mpeg; + /// assert_eq!(file_type.primary_tag_type(), TagType::Id3v2); + /// ``` + pub fn primary_tag_type(&self) -> TagType { + match self { + FileType::Aac | FileType::Aiff | FileType::Mpeg | FileType::Wav => TagType::Id3v2, + FileType::Ape | FileType::Mpc | FileType::WavPack => TagType::Ape, + FileType::Flac | FileType::Opus | FileType::Vorbis | FileType::Speex => { + TagType::VorbisComments + }, + FileType::Mp4 => TagType::Mp4Ilst, + FileType::Custom(c) => { + let resolver = crate::resolve::lookup_resolver(c); + resolver.primary_tag_type() + }, + } + } + + /// Returns if the target `FileType` supports a [`TagType`] + /// + /// NOTE: This is feature dependent, meaning if you do not have the + /// `id3v2` feature enabled, [`FileType::Mpeg`] will return `false` for + /// [`TagType::Id3v2`]. + /// + /// # Panics + /// + /// If an unregistered `FileType` ([`FileType::Custom`]) is encountered. See [`register_custom_resolver`](crate::resolve::register_custom_resolver). + /// + /// # Examples + /// + /// ```rust + /// use lofty::{FileType, TagType}; + /// + /// let file_type = FileType::Mpeg; + /// assert!(file_type.supports_tag_type(TagType::Id3v2)); + /// ``` + pub fn supports_tag_type(&self, tag_type: TagType) -> bool { + if let FileType::Custom(c) = self { + let resolver = crate::resolve::lookup_resolver(c); + return resolver.supported_tag_types().contains(&tag_type); + } + + match tag_type { + TagType::Ape => crate::ape::ApeTag::SUPPORTED_FORMATS.contains(self), + TagType::Id3v1 => crate::id3::v1::Id3v1Tag::SUPPORTED_FORMATS.contains(self), + TagType::Id3v2 => crate::id3::v2::Id3v2Tag::SUPPORTED_FORMATS.contains(self), + TagType::Mp4Ilst => crate::mp4::Ilst::SUPPORTED_FORMATS.contains(self), + TagType::VorbisComments => crate::ogg::VorbisComments::SUPPORTED_FORMATS.contains(self), + TagType::RiffInfo => crate::iff::wav::RIFFInfoList::SUPPORTED_FORMATS.contains(self), + TagType::AiffText => crate::iff::aiff::AIFFTextChunks::SUPPORTED_FORMATS.contains(self), + } + } + + /// Attempts to extract a [`FileType`] from an extension + /// + /// # Examples + /// + /// ```rust + /// use lofty::FileType; + /// + /// let extension = "mp3"; + /// assert_eq!(FileType::from_ext(extension), Some(FileType::Mpeg)); + /// ``` + pub fn from_ext(ext: E) -> Option + where + E: AsRef, + { + let ext = ext.as_ref().to_str()?.to_ascii_lowercase(); + + // Give custom resolvers priority + if unsafe { global_options().use_custom_resolvers } { + if let Some((ty, _)) = custom_resolvers() + .lock() + .ok()? + .iter() + .find(|(_, f)| f.extension() == Some(ext.as_str())) + { + return Some(Self::Custom(ty)); + } + } + + match ext.as_str() { + "aac" => Some(Self::Aac), + "ape" => Some(Self::Ape), + "aiff" | "aif" | "afc" | "aifc" => Some(Self::Aiff), + "mp3" | "mp2" | "mp1" => Some(Self::Mpeg), + "wav" | "wave" => Some(Self::Wav), + "wv" => Some(Self::WavPack), + "opus" => Some(Self::Opus), + "flac" => Some(Self::Flac), + "ogg" => Some(Self::Vorbis), + "mp4" | "m4a" | "m4b" | "m4p" | "m4r" | "m4v" | "3gp" => Some(Self::Mp4), + "mpc" | "mp+" | "mpp" => Some(Self::Mpc), + "spx" => Some(Self::Speex), + _ => None, + } + } + + /// Attempts to determine a [`FileType`] from a path + /// + /// # Examples + /// + /// ```rust + /// use lofty::FileType; + /// use std::path::Path; + /// + /// let path = Path::new("path/to/my.mp3"); + /// assert_eq!(FileType::from_path(path), Some(FileType::Mpeg)); + /// ``` + pub fn from_path

(path: P) -> Option + where + P: AsRef, + { + let ext = path.as_ref().extension(); + ext.and_then(Self::from_ext) + } + + /// Attempts to extract a [`FileType`] from a buffer + /// + /// NOTES: + /// + /// * This is for use in [`Probe::guess_file_type`], it + /// is recommended to use it that way + /// * This **will not** search past tags at the start of the buffer. + /// For this behavior, use [`Probe::guess_file_type`]. + /// + /// [`Probe::guess_file_type`]: crate::Probe::guess_file_type + /// + /// # Examples + /// + /// ```rust + /// use lofty::FileType; + /// use std::fs::File; + /// use std::io::Read; + /// + /// # fn main() -> lofty::Result<()> { + /// # let path_to_opus = "tests/files/assets/minimal/full_test.opus"; + /// let mut file = File::open(path_to_opus)?; + /// + /// let mut buf = [0; 50]; // Search the first 50 bytes of the file + /// file.read_exact(&mut buf)?; + /// + /// assert_eq!(FileType::from_buffer(&buf), Some(FileType::Opus)); + /// # Ok(()) } + /// ``` + pub fn from_buffer(buf: &[u8]) -> Option { + match Self::from_buffer_inner(buf) { + Some(FileTypeGuessResult::Determined(file_ty)) => Some(file_ty), + // We make no attempt to search past an ID3v2 tag or junk here, since + // we only provided a fixed-sized buffer to search from. + // + // That case is handled in `Probe::guess_file_type` + _ => None, + } + } + + // TODO: APE tags in the beginning of the file + pub(crate) fn from_buffer_inner(buf: &[u8]) -> Option { + use crate::id3::v2::util::synchsafe::SynchsafeInteger; + + // Start out with an empty return + let mut ret = None; + + if buf.is_empty() { + return ret; + } + + match Self::quick_type_guess(buf) { + Some(f_ty) => ret = Some(FileTypeGuessResult::Determined(f_ty)), + // Special case for ID3, gets checked in `Probe::guess_file_type` + // The bare minimum size for an ID3v2 header is 10 bytes + None if buf.len() >= 10 && &buf[..3] == b"ID3" => { + // This is infallible, but preferable to an unwrap + if let Ok(arr) = buf[6..10].try_into() { + // Set the ID3v2 size + ret = Some(FileTypeGuessResult::MaybePrecededById3( + u32::from_be_bytes(arr).unsynch(), + )); + } + }, + None => ret = Some(FileTypeGuessResult::MaybePrecededByJunk), + } + + ret + } + + fn quick_type_guess(buf: &[u8]) -> Option { + use crate::mpeg::header::verify_frame_sync; + + // Safe to index, since we return early on an empty buffer + match buf[0] { + 77 if buf.starts_with(b"MAC") => Some(Self::Ape), + 255 if buf.len() >= 2 && verify_frame_sync([buf[0], buf[1]]) => { + // ADTS and MPEG frame headers are way too similar + + // ADTS (https://wiki.multimedia.cx/index.php/ADTS#Header): + // + // AAAAAAAA AAAABCCX + // + // Letter Length (bits) Description + // A 12 Syncword, all bits must be set to 1. + // B 1 MPEG Version, set to 0 for MPEG-4 and 1 for MPEG-2. + // C 2 Layer, always set to 0. + + // MPEG (http://www.mp3-tech.org/programmer/frame_header.html): + // + // AAAAAAAA AAABBCCX + // + // Letter Length (bits) Description + // A 11 Syncword, all bits must be set to 1. + // B 2 MPEG Audio version ID + // C 2 Layer description + + // The subtle overlap in the ADTS header's frame sync and MPEG's version ID + // is the first condition to check. However, since 0b10 and 0b11 are valid versions + // in MPEG, we have to also check the layer. + + // So, if we have a version 1 (0b11) or version 2 (0b10) MPEG frame AND a layer of 0b00, + // we can assume we have an ADTS header. Awesome! + + if buf[1] & 0b10000 > 0 && buf[1] & 0b110 == 0 { + return Some(Self::Aac); + } + + Some(Self::Mpeg) + }, + 70 if buf.len() >= 12 && &buf[..4] == b"FORM" => { + let id = &buf[8..12]; + + if id == b"AIFF" || id == b"AIFC" { + return Some(Self::Aiff); + } + + None + }, + 79 if buf.len() >= 36 && &buf[..4] == b"OggS" => { + if &buf[29..35] == b"vorbis" { + return Some(Self::Vorbis); + } else if &buf[28..36] == b"OpusHead" { + return Some(Self::Opus); + } else if &buf[28..36] == b"Speex " { + return Some(Self::Speex); + } + + None + }, + 102 if buf.starts_with(b"fLaC") => Some(Self::Flac), + 82 if buf.len() >= 12 && &buf[..4] == b"RIFF" => { + if &buf[8..12] == b"WAVE" { + return Some(Self::Wav); + } + + None + }, + 119 if buf.len() >= 4 && &buf[..4] == b"wvpk" => Some(Self::WavPack), + _ if buf.len() >= 8 && &buf[4..8] == b"ftyp" => Some(Self::Mp4), + _ if buf.starts_with(b"MPCK") || buf.starts_with(b"MP+") => Some(Self::Mpc), + _ => None, + } + } +} + +/// The result of a `FileType` guess +/// +/// External callers of `FileType::from_buffer()` will only ever see `Determined` cases. +/// The remaining cases are used internally in `Probe::guess_file_type()`. +pub(crate) enum FileTypeGuessResult { + /// The `FileType` was guessed + Determined(FileType), + /// The stream starts with an ID3v2 tag + MaybePrecededById3(u32), + /// The stream starts with potential junk data + MaybePrecededByJunk, +} diff --git a/src/file/mod.rs b/src/file/mod.rs new file mode 100644 index 000000000..2e6156fe8 --- /dev/null +++ b/src/file/mod.rs @@ -0,0 +1,11 @@ +//! Generic file handling utilities + +mod audio_file; +mod file_type; +mod tagged_file; + +pub use audio_file::AudioFile; +pub use file_type::FileType; +pub use tagged_file::{BoundTaggedFile, TaggedFile, TaggedFileExt}; + +pub(crate) use file_type::FileTypeGuessResult; diff --git a/src/file.rs b/src/file/tagged_file.rs similarity index 58% rename from src/file.rs rename to src/file/tagged_file.rs index fb6f70fd4..65624540e 100644 --- a/src/file.rs +++ b/src/file/tagged_file.rs @@ -1,92 +1,13 @@ -use crate::config::{global_options, ParseOptions, WriteOptions}; +use super::audio_file::AudioFile; +use super::file_type::FileType; +use crate::config::{ParseOptions, WriteOptions}; use crate::error::Result; use crate::properties::FileProperties; -use crate::resolve::custom_resolvers; use crate::tag::{Tag, TagType}; use crate::traits::TagExt; -use std::ffi::OsStr; -use std::fs::{File, OpenOptions}; +use std::fs::File; use std::io::{Read, Seek}; -use std::path::Path; - -/// Provides various methods for interaction with a file -pub trait AudioFile: Into { - /// The struct the file uses for audio properties - /// - /// Not all formats can use [`FileProperties`] since they may contain additional information - type Properties; - - /// Read a file from a reader - /// - /// # Errors - /// - /// Errors depend on the file and tags being read. See [`LoftyError`](crate::LoftyError) - fn read_from(reader: &mut R, parse_options: ParseOptions) -> Result - where - R: Read + Seek, - Self: Sized; - - /// Attempts to write all tags to a path - /// - /// # Errors - /// - /// * `path` does not exist - /// * `path` is not writable - /// * See [`AudioFile::save_to`] - /// - /// # Examples - /// - /// ```rust,no_run - /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; - /// - /// # fn main() -> lofty::Result<()> { - /// # let path = "tests/files/assets/minimal/full_test.mp3"; - /// let mut tagged_file = lofty::read_from_path(path)?; - /// - /// // Edit the tags - /// - /// tagged_file.save_to_path(path, WriteOptions::default())?; - /// # Ok(()) } - /// ``` - fn save_to_path(&self, path: impl AsRef, write_options: WriteOptions) -> Result<()> { - self.save_to( - &mut OpenOptions::new().read(true).write(true).open(path)?, - write_options, - ) - } - - /// Attempts to write all tags to a file - /// - /// # Errors - /// - /// See [`Tag::save_to`], however this is applicable to every tag in the file. - /// - /// # Examples - /// - /// ```rust,no_run - /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; - /// use std::fs::OpenOptions; - /// - /// # fn main() -> lofty::Result<()> { - /// # let path = "tests/files/assets/minimal/full_test.mp3"; - /// let mut tagged_file = lofty::read_from_path(path)?; - /// - /// // Edit the tags - /// - /// let mut file = OpenOptions::new().read(true).write(true).open(path)?; - /// tagged_file.save_to(&mut file, WriteOptions::default())?; - /// # Ok(()) } - /// ``` - fn save_to(&self, file: &mut File, write_options: WriteOptions) -> Result<()>; - - /// Returns a reference to the file's properties - fn properties(&self) -> &Self::Properties; - /// Checks if the file contains any tags - fn contains_tag(&self) -> bool; - /// Checks if the file contains the given [`TagType`] - fn contains_tag_type(&self, tag_type: TagType) -> bool; -} /// Provides a common interface between [`TaggedFile`] and [`BoundTaggedFile`] pub trait TaggedFileExt { @@ -714,317 +635,3 @@ impl AudioFile for BoundTaggedFile { self.inner.contains_tag_type(tag_type) } } - -/// The type of file read -#[derive(PartialEq, Eq, Copy, Clone, Debug)] -#[allow(missing_docs)] -#[non_exhaustive] -pub enum FileType { - Aac, - Aiff, - Ape, - Flac, - Mpeg, - Mp4, - Mpc, - Opus, - Vorbis, - Speex, - Wav, - WavPack, - Custom(&'static str), -} - -impl FileType { - /// Returns the file type's "primary" [`TagType`], or the one most likely to be used in the target format - /// - /// | [`FileType`] | [`TagType`] | - /// |-----------------------------------|------------------| - /// | `Aac`, `Aiff`, `Mp3`, `Wav` | `Id3v2` | - /// | `Ape` , `Mpc`, `WavPack` | `Ape` | - /// | `Flac`, `Opus`, `Vorbis`, `Speex` | `VorbisComments` | - /// | `Mp4` | `Mp4Ilst` | - /// - /// # Panics - /// - /// If an unregistered `FileType` ([`FileType::Custom`]) is encountered. See [`register_custom_resolver`](crate::resolve::register_custom_resolver). - /// - /// # Examples - /// - /// ```rust - /// use lofty::{FileType, TagType}; - /// - /// let file_type = FileType::Mpeg; - /// assert_eq!(file_type.primary_tag_type(), TagType::Id3v2); - /// ``` - pub fn primary_tag_type(&self) -> TagType { - match self { - FileType::Aac | FileType::Aiff | FileType::Mpeg | FileType::Wav => TagType::Id3v2, - FileType::Ape | FileType::Mpc | FileType::WavPack => TagType::Ape, - FileType::Flac | FileType::Opus | FileType::Vorbis | FileType::Speex => { - TagType::VorbisComments - }, - FileType::Mp4 => TagType::Mp4Ilst, - FileType::Custom(c) => { - let resolver = crate::resolve::lookup_resolver(c); - resolver.primary_tag_type() - }, - } - } - - /// Returns if the target `FileType` supports a [`TagType`] - /// - /// NOTE: This is feature dependent, meaning if you do not have the - /// `id3v2` feature enabled, [`FileType::Mpeg`] will return `false` for - /// [`TagType::Id3v2`]. - /// - /// # Panics - /// - /// If an unregistered `FileType` ([`FileType::Custom`]) is encountered. See [`register_custom_resolver`](crate::resolve::register_custom_resolver). - /// - /// # Examples - /// - /// ```rust - /// use lofty::{FileType, TagType}; - /// - /// let file_type = FileType::Mpeg; - /// assert!(file_type.supports_tag_type(TagType::Id3v2)); - /// ``` - pub fn supports_tag_type(&self, tag_type: TagType) -> bool { - if let FileType::Custom(c) = self { - let resolver = crate::resolve::lookup_resolver(c); - return resolver.supported_tag_types().contains(&tag_type); - } - - match tag_type { - TagType::Ape => crate::ape::ApeTag::SUPPORTED_FORMATS.contains(self), - TagType::Id3v1 => crate::id3::v1::Id3v1Tag::SUPPORTED_FORMATS.contains(self), - TagType::Id3v2 => crate::id3::v2::Id3v2Tag::SUPPORTED_FORMATS.contains(self), - TagType::Mp4Ilst => crate::mp4::Ilst::SUPPORTED_FORMATS.contains(self), - TagType::VorbisComments => crate::ogg::VorbisComments::SUPPORTED_FORMATS.contains(self), - TagType::RiffInfo => crate::iff::wav::RIFFInfoList::SUPPORTED_FORMATS.contains(self), - TagType::AiffText => crate::iff::aiff::AIFFTextChunks::SUPPORTED_FORMATS.contains(self), - } - } - - /// Attempts to extract a [`FileType`] from an extension - /// - /// # Examples - /// - /// ```rust - /// use lofty::FileType; - /// - /// let extension = "mp3"; - /// assert_eq!(FileType::from_ext(extension), Some(FileType::Mpeg)); - /// ``` - pub fn from_ext(ext: E) -> Option - where - E: AsRef, - { - let ext = ext.as_ref().to_str()?.to_ascii_lowercase(); - - // Give custom resolvers priority - if unsafe { global_options().use_custom_resolvers } { - if let Some((ty, _)) = custom_resolvers() - .lock() - .ok()? - .iter() - .find(|(_, f)| f.extension() == Some(ext.as_str())) - { - return Some(Self::Custom(ty)); - } - } - - match ext.as_str() { - "aac" => Some(Self::Aac), - "ape" => Some(Self::Ape), - "aiff" | "aif" | "afc" | "aifc" => Some(Self::Aiff), - "mp3" | "mp2" | "mp1" => Some(Self::Mpeg), - "wav" | "wave" => Some(Self::Wav), - "wv" => Some(Self::WavPack), - "opus" => Some(Self::Opus), - "flac" => Some(Self::Flac), - "ogg" => Some(Self::Vorbis), - "mp4" | "m4a" | "m4b" | "m4p" | "m4r" | "m4v" | "3gp" => Some(Self::Mp4), - "mpc" | "mp+" | "mpp" => Some(Self::Mpc), - "spx" => Some(Self::Speex), - _ => None, - } - } - - /// Attempts to determine a [`FileType`] from a path - /// - /// # Examples - /// - /// ```rust - /// use lofty::FileType; - /// use std::path::Path; - /// - /// let path = Path::new("path/to/my.mp3"); - /// assert_eq!(FileType::from_path(path), Some(FileType::Mpeg)); - /// ``` - pub fn from_path

(path: P) -> Option - where - P: AsRef, - { - let ext = path.as_ref().extension(); - ext.and_then(Self::from_ext) - } - - /// Attempts to extract a [`FileType`] from a buffer - /// - /// NOTES: - /// - /// * This is for use in [`Probe::guess_file_type`], it - /// is recommended to use it that way - /// * This **will not** search past tags at the start of the buffer. - /// For this behavior, use [`Probe::guess_file_type`]. - /// - /// [`Probe::guess_file_type`]: crate::Probe::guess_file_type - /// - /// # Examples - /// - /// ```rust - /// use lofty::FileType; - /// use std::fs::File; - /// use std::io::Read; - /// - /// # fn main() -> lofty::Result<()> { - /// # let path_to_opus = "tests/files/assets/minimal/full_test.opus"; - /// let mut file = File::open(path_to_opus)?; - /// - /// let mut buf = [0; 50]; // Search the first 50 bytes of the file - /// file.read_exact(&mut buf)?; - /// - /// assert_eq!(FileType::from_buffer(&buf), Some(FileType::Opus)); - /// # Ok(()) } - /// ``` - pub fn from_buffer(buf: &[u8]) -> Option { - match Self::from_buffer_inner(buf) { - Some(FileTypeGuessResult::Determined(file_ty)) => Some(file_ty), - // We make no attempt to search past an ID3v2 tag or junk here, since - // we only provided a fixed-sized buffer to search from. - // - // That case is handled in `Probe::guess_file_type` - _ => None, - } - } - - // TODO: APE tags in the beginning of the file - pub(crate) fn from_buffer_inner(buf: &[u8]) -> Option { - use crate::id3::v2::util::synchsafe::SynchsafeInteger; - - // Start out with an empty return - let mut ret = None; - - if buf.is_empty() { - return ret; - } - - match Self::quick_type_guess(buf) { - Some(f_ty) => ret = Some(FileTypeGuessResult::Determined(f_ty)), - // Special case for ID3, gets checked in `Probe::guess_file_type` - // The bare minimum size for an ID3v2 header is 10 bytes - None if buf.len() >= 10 && &buf[..3] == b"ID3" => { - // This is infallible, but preferable to an unwrap - if let Ok(arr) = buf[6..10].try_into() { - // Set the ID3v2 size - ret = Some(FileTypeGuessResult::MaybePrecededById3( - u32::from_be_bytes(arr).unsynch(), - )); - } - }, - None => ret = Some(FileTypeGuessResult::MaybePrecededByJunk), - } - - ret - } - - fn quick_type_guess(buf: &[u8]) -> Option { - use crate::mpeg::header::verify_frame_sync; - - // Safe to index, since we return early on an empty buffer - match buf[0] { - 77 if buf.starts_with(b"MAC") => Some(Self::Ape), - 255 if buf.len() >= 2 && verify_frame_sync([buf[0], buf[1]]) => { - // ADTS and MPEG frame headers are way too similar - - // ADTS (https://wiki.multimedia.cx/index.php/ADTS#Header): - // - // AAAAAAAA AAAABCCX - // - // Letter Length (bits) Description - // A 12 Syncword, all bits must be set to 1. - // B 1 MPEG Version, set to 0 for MPEG-4 and 1 for MPEG-2. - // C 2 Layer, always set to 0. - - // MPEG (http://www.mp3-tech.org/programmer/frame_header.html): - // - // AAAAAAAA AAABBCCX - // - // Letter Length (bits) Description - // A 11 Syncword, all bits must be set to 1. - // B 2 MPEG Audio version ID - // C 2 Layer description - - // The subtle overlap in the ADTS header's frame sync and MPEG's version ID - // is the first condition to check. However, since 0b10 and 0b11 are valid versions - // in MPEG, we have to also check the layer. - - // So, if we have a version 1 (0b11) or version 2 (0b10) MPEG frame AND a layer of 0b00, - // we can assume we have an ADTS header. Awesome! - - if buf[1] & 0b10000 > 0 && buf[1] & 0b110 == 0 { - return Some(Self::Aac); - } - - Some(Self::Mpeg) - }, - 70 if buf.len() >= 12 && &buf[..4] == b"FORM" => { - let id = &buf[8..12]; - - if id == b"AIFF" || id == b"AIFC" { - return Some(Self::Aiff); - } - - None - }, - 79 if buf.len() >= 36 && &buf[..4] == b"OggS" => { - if &buf[29..35] == b"vorbis" { - return Some(Self::Vorbis); - } else if &buf[28..36] == b"OpusHead" { - return Some(Self::Opus); - } else if &buf[28..36] == b"Speex " { - return Some(Self::Speex); - } - - None - }, - 102 if buf.starts_with(b"fLaC") => Some(Self::Flac), - 82 if buf.len() >= 12 && &buf[..4] == b"RIFF" => { - if &buf[8..12] == b"WAVE" { - return Some(Self::Wav); - } - - None - }, - 119 if buf.len() >= 4 && &buf[..4] == b"wvpk" => Some(Self::WavPack), - _ if buf.len() >= 8 && &buf[4..8] == b"ftyp" => Some(Self::Mp4), - _ if buf.starts_with(b"MPCK") || buf.starts_with(b"MP+") => Some(Self::Mpc), - _ => None, - } - } -} - -/// The result of a `FileType` guess -/// -/// External callers of `FileType::from_buffer()` will only ever see `Determined` cases. -/// The remaining cases are used internally in `Probe::guess_file_type()`. -pub(crate) enum FileTypeGuessResult { - /// The `FileType` was guessed - Determined(FileType), - /// The stream starts with an ID3v2 tag - MaybePrecededById3(u32), - /// The stream starts with potential junk data - MaybePrecededByJunk, -} diff --git a/src/lib.rs b/src/lib.rs index b766a6a7e..27c3ae4d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,7 +152,7 @@ pub(crate) mod _this_is_internal {} pub mod config; pub mod error; -pub(crate) mod file; +pub mod file; pub(crate) mod macros; mod math; pub(crate) mod picture; From b41514982d5ddaa271a978c091bb6e2ee590b945 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 13:13:05 -0400 Subject: [PATCH 05/22] changelog: Update for changes so far --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca73aaf1..219ba7578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,10 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ChannelMask::from_{mp4, opus}_channels` - **Opus**: `OpusProperties` now contains the channel mask - **AAC**: `AacProperties` now contains the channel mask +- **Prelude**: `lofty::prelude` module to make trait imports easier ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) ### Changed - **Properties**: `FileProperties` and `ChannelMask` have been moved from the root to the new `lofty::properties` module ([PR](https://github.com/Serial-ATA/lofty-rs/pull/372)) +- **ParseOptions**/**WriteOptions**/**GlobalOptions**: + - ⚠️ Important ⚠️: Moved to `lofty::options` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) +- **AudioFile**/**TaggedFileExt**/**TaggedFile**/**BoundTaggedFile**: + - ⚠️ Important ⚠️: Moved to `lofty::file` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) ### Fixed - **Vorbis**: Fix panic when reading properties of zero-length files ([issue](https://github.com/Serial-ATA/lofty-rs/issues/342)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/365)) From ab36589b813fabce2e42c8793704d14115513869 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 13:24:14 -0400 Subject: [PATCH 06/22] misc: Remove root `file` re-exports --- examples/custom_resolver/src/main.rs | 3 ++- examples/tag_stripper.rs | 4 +++- lofty_attr/src/lofty_file.rs | 8 ++++---- lofty_attr/src/lofty_tag.rs | 8 ++++---- src/lib.rs | 1 - tests/files/aac.rs | 3 ++- tests/files/aiff.rs | 3 ++- tests/files/ape.rs | 3 ++- tests/files/mp4.rs | 3 ++- tests/files/mpc.rs | 3 ++- tests/files/mpeg.rs | 3 ++- tests/files/ogg.rs | 3 ++- tests/files/util/mod.rs | 14 +++++++------- tests/files/wav.rs | 3 ++- tests/files/wavpack.rs | 3 ++- 15 files changed, 38 insertions(+), 27 deletions(-) diff --git a/examples/custom_resolver/src/main.rs b/examples/custom_resolver/src/main.rs index 1ac3b3e4a..51f5c9044 100644 --- a/examples/custom_resolver/src/main.rs +++ b/examples/custom_resolver/src/main.rs @@ -1,10 +1,11 @@ use lofty::ape::ApeTag; use lofty::config::{GlobalOptions, ParseOptions}; use lofty::error::Result as LoftyResult; +use lofty::file::FileType; use lofty::id3::v2::Id3v2Tag; use lofty::properties::FileProperties; use lofty::resolve::FileResolver; -use lofty::{FileType, TagType}; +use lofty::TagType; use lofty_attr::LoftyFile; use std::fs::File; diff --git a/examples/tag_stripper.rs b/examples/tag_stripper.rs index 433cd98be..b59a85192 100644 --- a/examples/tag_stripper.rs +++ b/examples/tag_stripper.rs @@ -1,4 +1,6 @@ -use lofty::{Probe, TaggedFileExt}; +use lofty::file::TaggedFileExt; +use lofty::Probe; + use std::io::Write; fn main() { diff --git a/lofty_attr/src/lofty_file.rs b/lofty_attr/src/lofty_file.rs index df78837ac..85db78a4d 100644 --- a/lofty_attr/src/lofty_file.rs +++ b/lofty_attr/src/lofty_file.rs @@ -523,19 +523,19 @@ fn generate_from_taggedfile_impl(file: &LoftyFile) -> proc_macro2::TokenStream { let file_type = &file.file_type; let file_type_variant = if file.internal_details.has_internal_file_type { - quote! { ::lofty::FileType::#file_type } + quote! { ::lofty::file::FileType::#file_type } } else { let file_ty_str = file_type.to_string(); - quote! { ::lofty::FileType::Custom(#file_ty_str) } + quote! { ::lofty::file::FileType::Custom(#file_ty_str) } }; let struct_name = &file.struct_info.name; quote! { - impl ::std::convert::From<#struct_name> for ::lofty::TaggedFile { + impl ::std::convert::From<#struct_name> for ::lofty::file::TaggedFile { fn from(input: #struct_name) -> Self { use ::lofty::prelude::TaggedFileExt as _; - ::lofty::TaggedFile::new( + ::lofty::file::TaggedFile::new( #file_type_variant, ::lofty::properties::FileProperties::from(input.properties), { diff --git a/lofty_attr/src/lofty_tag.rs b/lofty_attr/src/lofty_tag.rs index 8d3712e5a..3e88d45c2 100644 --- a/lofty_attr/src/lofty_tag.rs +++ b/lofty_attr/src/lofty_tag.rs @@ -83,12 +83,12 @@ impl LoftyTag { #input impl #ident { - pub(crate) const SUPPORTED_FORMATS: &'static [::lofty::FileType] = &[ - #( ::lofty::FileType:: #flattened_file_types ),* + pub(crate) const SUPPORTED_FORMATS: &'static [::lofty::file::FileType] = &[ + #( ::lofty::file::FileType:: #flattened_file_types ),* ]; - pub(crate) const READ_ONLY_FORMATS: &'static [::lofty::FileType] = &[ - #( ::lofty::FileType:: #read_only_file_types ),* + pub(crate) const READ_ONLY_FORMATS: &'static [::lofty::file::FileType] = &[ + #( ::lofty::file::FileType:: #read_only_file_types ),* ]; } }) diff --git a/src/lib.rs b/src/lib.rs index 27c3ae4d1..70e1ddacd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,7 +176,6 @@ pub mod wavpack; pub use crate::probe::{read_from, read_from_path, Probe}; -pub use crate::file::{BoundTaggedFile, FileType, TaggedFile, TaggedFileExt}; pub use crate::picture::{MimeType, Picture, PictureType}; pub use crate::tag::{Tag, TagType}; pub use tag::item::{ItemKey, ItemValue, TagItem}; diff --git a/tests/files/aac.rs b/tests/files/aac.rs index 4f6170e20..0b9a448ef 100644 --- a/tests/files/aac.rs +++ b/tests/files/aac.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/aiff.rs b/tests/files/aiff.rs index a1d495161..92563b1b1 100644 --- a/tests/files/aiff.rs +++ b/tests/files/aiff.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/ape.rs b/tests/files/ape.rs index 9ed0961ef..5cf9648fd 100644 --- a/tests/files/ape.rs +++ b/tests/files/ape.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/mp4.rs b/tests/files/mp4.rs index eccb6e753..11a77ce13 100644 --- a/tests/files/mp4.rs +++ b/tests/files/mp4.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/mpc.rs b/tests/files/mpc.rs index cf7d707bd..971f27be0 100644 --- a/tests/files/mpc.rs +++ b/tests/files/mpc.rs @@ -1,8 +1,9 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::{FileType, TaggedFile}; use lofty::musepack::MpcFile; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType, TaggedFile}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/mpeg.rs b/tests/files/mpeg.rs index e7ebd5857..49acd59eb 100644 --- a/tests/files/mpeg.rs +++ b/tests/files/mpeg.rs @@ -1,9 +1,10 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::{ParseOptions, WriteOptions}; +use lofty::file::FileType; use lofty::id3::v2::{Frame, FrameFlags, FrameId, FrameValue, Id3v2Tag, KeyValueFrame}; use lofty::mpeg::MpegFile; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, Tag, TagItem, TagType}; +use lofty::{Probe, Tag, TagType}; use std::borrow::Cow; use std::io::{Seek, Write}; diff --git a/tests/files/ogg.rs b/tests/files/ogg.rs index aaaef0714..5b5fb6b9b 100644 --- a/tests/files/ogg.rs +++ b/tests/files/ogg.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::{ParseOptions, WriteOptions}; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/util/mod.rs b/tests/files/util/mod.rs index 29138282b..5f3f05ade 100644 --- a/tests/files/util/mod.rs +++ b/tests/files/util/mod.rs @@ -30,10 +30,10 @@ macro_rules! verify_artist { assert_eq!(tag.item_count(), $item_count); assert_eq!( - tag.get(&ItemKey::TrackArtist), - Some(&TagItem::new( - ItemKey::TrackArtist, - ItemValue::Text(String::from($expected_value)) + tag.get(&lofty::ItemKey::TrackArtist), + Some(&lofty::TagItem::new( + lofty::ItemKey::TrackArtist, + lofty::ItemValue::Text(String::from($expected_value)) )) ); @@ -62,9 +62,9 @@ macro_rules! set_artist { set_artist!($file_write, $new_value, tag) }; ($file_write:ident, $new_value:literal, $tag:ident) => { - $tag.insert_unchecked(TagItem::new( - ItemKey::TrackArtist, - ItemValue::Text(String::from($new_value)), + $tag.insert_unchecked(lofty::TagItem::new( + lofty::ItemKey::TrackArtist, + lofty::ItemValue::Text(String::from($new_value)), )); $file_write.rewind().unwrap(); diff --git a/tests/files/wav.rs b/tests/files/wav.rs index 9e3ccf094..7bda63a0f 100644 --- a/tests/files/wav.rs +++ b/tests/files/wav.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index 93a4b141a..fcd6fea6b 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -1,7 +1,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; +use lofty::file::FileType; use lofty::prelude::*; -use lofty::{FileType, ItemValue, Probe, TagItem, TagType}; +use lofty::{Probe, TagType}; use std::io::{Seek, Write}; From 859c4d3a052ca5a4993d3d26ff6262e63ff38360 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 13:33:54 -0400 Subject: [PATCH 07/22] doc: Fix a bunch of test imports --- src/error.rs | 14 +++--- src/file/audio_file.rs | 7 +-- src/file/file_type.rs | 14 +++--- src/file/tagged_file.rs | 93 ++++++++++++++++++++---------------- src/id3/v2/util/synchsafe.rs | 4 +- src/lib.rs | 22 ++++----- src/mp4/ilst/atom.rs | 2 +- src/mp4/mod.rs | 5 +- src/ogg/picture_storage.rs | 6 +-- src/probe.rs | 67 +++++++++++++++----------- 10 files changed, 129 insertions(+), 105 deletions(-) diff --git a/src/error.rs b/src/error.rs index 35d9dce74..0c2a01f0d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -299,7 +299,7 @@ impl FileEncodingError { /// /// ```rust /// use lofty::error::FileEncodingError; - /// use lofty::FileType; + /// use lofty::file::FileType; /// /// // This error is bounded to `FileType::Mpeg`, which will be displayed when the error is formatted /// let mpeg_error = @@ -319,7 +319,7 @@ impl FileEncodingError { /// /// ```rust /// use lofty::error::FileEncodingError; - /// use lofty::FileType; + /// use lofty::file::FileType; /// /// // The error isn't bounded to FileType::Mpeg, only the message will be displayed when the /// // error is formatted @@ -338,7 +338,7 @@ impl FileEncodingError { /// /// ```rust /// use lofty::error::FileEncodingError; - /// use lofty::FileType; + /// use lofty::file::FileType; /// /// let mpeg_error = /// FileEncodingError::new(FileType::Mpeg, "Something went wrong in the MPEG file!"); @@ -355,7 +355,7 @@ impl FileEncodingError { /// /// ```rust /// use lofty::error::FileEncodingError; - /// use lofty::FileType; + /// use lofty::file::FileType; /// /// let mpeg_error = /// FileEncodingError::new(FileType::Mpeg, "Something went wrong in the MPEG file!"); @@ -401,8 +401,7 @@ impl LoftyError { /// # Examples /// /// ```rust - /// use lofty::error::ErrorKind; - /// use lofty::LoftyError; + /// use lofty::error::{ErrorKind, LoftyError}; /// /// let unknown_format = LoftyError::new(ErrorKind::UnknownFormat); /// ``` @@ -416,8 +415,7 @@ impl LoftyError { /// # Examples /// /// ```rust - /// use lofty::error::ErrorKind; - /// use lofty::LoftyError; + /// use lofty::error::{ErrorKind, LoftyError}; /// /// let unknown_format = LoftyError::new(ErrorKind::UnknownFormat); /// if let ErrorKind::UnknownFormat = unknown_format.kind() { diff --git a/src/file/audio_file.rs b/src/file/audio_file.rs index 3f47b397d..ba403f37a 100644 --- a/src/file/audio_file.rs +++ b/src/file/audio_file.rs @@ -35,9 +35,10 @@ pub trait AudioFile: Into { /// # Examples /// /// ```rust,no_run - /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; + /// use lofty::config::WriteOptions; + /// use lofty::file::{AudioFile, TaggedFileExt}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// let mut tagged_file = lofty::read_from_path(path)?; /// @@ -63,7 +64,7 @@ pub trait AudioFile: Into { /// /// ```rust,no_run /// use lofty::config::WriteOptions; - /// use lofty::{AudioFile, TaggedFileExt, WriteOptions}; + /// use lofty::file::{AudioFile, TaggedFileExt}; /// use std::fs::OpenOptions; /// /// # fn main() -> lofty::error::Result<()> { diff --git a/src/file/file_type.rs b/src/file/file_type.rs index 2f03f2b6d..38a02fae4 100644 --- a/src/file/file_type.rs +++ b/src/file/file_type.rs @@ -42,7 +42,8 @@ impl FileType { /// # Examples /// /// ```rust - /// use lofty::{FileType, TagType}; + /// use lofty::file::FileType; + /// use lofty::TagType; /// /// let file_type = FileType::Mpeg; /// assert_eq!(file_type.primary_tag_type(), TagType::Id3v2); @@ -75,7 +76,8 @@ impl FileType { /// # Examples /// /// ```rust - /// use lofty::{FileType, TagType}; + /// use lofty::file::FileType; + /// use lofty::TagType; /// /// let file_type = FileType::Mpeg; /// assert!(file_type.supports_tag_type(TagType::Id3v2)); @@ -102,7 +104,7 @@ impl FileType { /// # Examples /// /// ```rust - /// use lofty::FileType; + /// use lofty::file::FileType; /// /// let extension = "mp3"; /// assert_eq!(FileType::from_ext(extension), Some(FileType::Mpeg)); @@ -147,7 +149,7 @@ impl FileType { /// # Examples /// /// ```rust - /// use lofty::FileType; + /// use lofty::file::FileType; /// use std::path::Path; /// /// let path = Path::new("path/to/my.mp3"); @@ -175,11 +177,11 @@ impl FileType { /// # Examples /// /// ```rust - /// use lofty::FileType; + /// use lofty::file::FileType; /// use std::fs::File; /// use std::io::Read; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_opus = "tests/files/assets/minimal/full_test.opus"; /// let mut file = File::open(path_to_opus)?; /// diff --git a/src/file/tagged_file.rs b/src/file/tagged_file.rs index 65624540e..c66262a5d 100644 --- a/src/file/tagged_file.rs +++ b/src/file/tagged_file.rs @@ -16,9 +16,9 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{FileType, TaggedFileExt}; + /// use lofty::file::{FileType, TaggedFileExt}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; /// @@ -32,9 +32,9 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{FileType, TaggedFileExt}; + /// use lofty::file::{FileType, TaggedFileExt}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // An MP3 file with 3 tags /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -53,9 +53,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; /// @@ -71,9 +72,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; /// @@ -89,9 +91,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file with an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -110,9 +113,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file with an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -135,9 +139,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file with an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -160,9 +165,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{TagType, TaggedFileExt}; + /// use lofty::file::TaggedFileExt; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file with an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -188,9 +194,9 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::TaggedFileExt; + /// use lofty::file::TaggedFileExt; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// // A file we know has tags /// let mut tagged_file = lofty::read_from_path(path)?; @@ -212,9 +218,9 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::TaggedFileExt; + /// use lofty::file::TaggedFileExt; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// // A file we know has tags /// let mut tagged_file = lofty::read_from_path(path)?; @@ -238,9 +244,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{AudioFile, Tag, TagType, TaggedFileExt}; + /// use lofty::file::{AudioFile, TaggedFileExt}; + /// use lofty::{Tag, TagType}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file without an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -262,9 +269,10 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::{AudioFile, TagType, TaggedFileExt}; + /// use lofty::file::{AudioFile, TaggedFileExt}; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file containing an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -284,9 +292,9 @@ pub trait TaggedFileExt { /// # Examples /// /// ```rust - /// use lofty::TaggedFileExt; + /// use lofty::file::TaggedFileExt; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// let mut tagged_file = lofty::read_from_path(path)?; /// @@ -332,9 +340,10 @@ impl TaggedFile { /// # Examples /// /// ```rust - /// use lofty::{AudioFile, FileType, TagType, TaggedFileExt}; + /// use lofty::file::{AudioFile, FileType, TaggedFileExt}; + /// use lofty::TagType; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; /// // Read an MP3 file containing an ID3v2 tag /// let mut tagged_file = lofty::read_from_path(path_to_mp3)?; @@ -451,8 +460,10 @@ impl From for TaggedFile { /// For example: /// /// ```rust,no_run -/// use lofty::{AudioFile, Tag, TagType, TaggedFileExt, WriteOptions}; -/// # fn main() -> lofty::Result<()> { +/// use lofty::config::WriteOptions; +/// use lofty::file::{AudioFile, TaggedFileExt}; +/// use lofty::{Tag, TagType}; +/// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// /// // We create an empty tag @@ -474,11 +485,11 @@ impl From for TaggedFile { /// However, when using `BoundTaggedFile`: /// /// ```rust,no_run -/// use lofty::{ -/// AudioFile, BoundTaggedFile, ParseOptions, Tag, TagType, TaggedFileExt, WriteOptions, -/// }; +/// use lofty::config::{ParseOptions, WriteOptions}; +/// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; +/// use lofty::{Tag, TagType}; /// use std::fs::OpenOptions; -/// # fn main() -> lofty::Result<()> { +/// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// /// // We create an empty tag @@ -514,9 +525,11 @@ impl BoundTaggedFile { /// # Examples /// /// ```rust - /// use lofty::{AudioFile, BoundTaggedFile, ParseOptions, Tag, TagType, TaggedFileExt}; + /// use lofty::config::ParseOptions; + /// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; + /// use lofty::{Tag, TagType}; /// use std::fs::OpenOptions; - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// /// // We'll need to open our file for reading *and* writing @@ -545,11 +558,11 @@ impl BoundTaggedFile { /// # Examples /// /// ```rust,no_run - /// use lofty::{ - /// AudioFile, BoundTaggedFile, ParseOptions, Tag, TagType, TaggedFileExt, WriteOptions, - /// }; + /// use lofty::config::{ParseOptions, WriteOptions}; + /// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; + /// use lofty::{Tag, TagType}; /// use std::fs::OpenOptions; - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// /// // We'll need to open our file for reading *and* writing diff --git a/src/id3/v2/util/synchsafe.rs b/src/id3/v2/util/synchsafe.rs index fedfe7489..a33ac434b 100644 --- a/src/id3/v2/util/synchsafe.rs +++ b/src/id3/v2/util/synchsafe.rs @@ -16,7 +16,7 @@ use std::io::Read; /// use std::io::{Cursor, Read}; /// use lofty::id3::v2::util::synchsafe::UnsynchronizedStream; /// -/// fn main() -> lofty::Result<()> { +/// fn main() -> lofty::error::Result<()> { /// // The content has two `0xFF 0x00` pairs, which will be removed /// let content = [0xFF, 0x00, 0x1A, 0xFF, 0x00, 0x15]; /// @@ -68,7 +68,7 @@ impl UnsynchronizedStream { /// use lofty::id3::v2::util::synchsafe::UnsynchronizedStream; /// use std::io::Cursor; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let reader = Cursor::new([0xFF, 0x00, 0x1A]); /// let unsynchronized_reader = UnsynchronizedStream::new(reader); /// diff --git a/src/lib.rs b/src/lib.rs index 70e1ddacd..f836398a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,8 +16,7 @@ //! ### Using a path //! //! ```rust,no_run -//! # use lofty::LoftyError; -//! # fn main() -> Result<(), LoftyError> { +//! # fn main() -> lofty::error::Result<()> { //! use lofty::{read_from_path, Probe}; //! //! // This will guess the format from the extension @@ -35,9 +34,9 @@ //! ### Using an existing reader //! //! ```rust,no_run -//! # use lofty::LoftyError; -//! # fn main() -> Result<(), LoftyError> { -//! use lofty::{read_from, ParseOptions}; +//! # fn main() -> lofty::error::Result<()> { +//! use lofty::config::ParseOptions; +//! use lofty::read_from; //! use std::fs::File; //! //! // Let's read from an open file @@ -53,9 +52,9 @@ //! ### Accessing tags //! //! ```rust,no_run -//! # use lofty::LoftyError; -//! # fn main() -> Result<(), LoftyError> { -//! use lofty::{read_from_path, ParseOptions, TaggedFileExt}; +//! # fn main() -> lofty::error::Result<()> { +//! use lofty::file::TaggedFileExt; +//! use lofty::read_from_path; //! //! let path = "test.mp3"; //! let tagged_file = read_from_path(path)?; @@ -73,10 +72,11 @@ //! ## Using concrete file types //! //! ```rust -//! # use lofty::LoftyError; -//! # fn main() -> Result<(), LoftyError> { +//! # fn main() -> lofty::error::Result<()> { +//! use lofty::config::ParseOptions; +//! use lofty::file::AudioFile; //! use lofty::mpeg::MpegFile; -//! use lofty::{AudioFile, ParseOptions, TagType}; +//! use lofty::TagType; //! use std::fs::File; //! //! # let path = "tests/files/assets/minimal/full_test.mp3"; diff --git a/src/mp4/ilst/atom.rs b/src/mp4/ilst/atom.rs index fe51e56e8..45aba0e71 100644 --- a/src/mp4/ilst/atom.rs +++ b/src/mp4/ilst/atom.rs @@ -179,7 +179,7 @@ impl<'a> Atom<'a> { /// ```rust /// use lofty::mp4::{Atom, AtomData, AtomIdent}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// // Create an artist atom /// let mut atom = Atom::new( /// AtomIdent::Fourcc(*b"\x49ART"), diff --git a/src/mp4/mod.rs b/src/mp4/mod.rs index 330c11735..582ce1ce9 100644 --- a/src/mp4/mod.rs +++ b/src/mp4/mod.rs @@ -47,10 +47,11 @@ impl Mp4File { /// # Examples /// /// ```rust,no_run + /// use lofty::config::ParseOptions; + /// use lofty::file::AudioFile; /// use lofty::mp4::Mp4File; - /// use lofty::{AudioFile, ParseOptions}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let mut m4a_reader = std::io::Cursor::new(&[]); /// let m4a_file = Mp4File::read_from(&mut m4a_reader, ParseOptions::new())?; /// diff --git a/src/ogg/picture_storage.rs b/src/ogg/picture_storage.rs index 0f25a8dca..4e02e5bd7 100644 --- a/src/ogg/picture_storage.rs +++ b/src/ogg/picture_storage.rs @@ -73,7 +73,7 @@ pub trait OggPictureStorage: private::Sealed { /// use lofty::ogg::{VorbisComments, OggPictureStorage}; /// # use lofty::{Picture, PictureInformation, PictureType, MimeType}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); /// # let front_cover_info = PictureInformation::default(); /// # let back_cover = Picture::new_unchecked(PictureType::CoverBack, Some(MimeType::Png), None, Vec::new()); @@ -121,7 +121,7 @@ pub trait OggPictureStorage: private::Sealed { /// use lofty::ogg::{VorbisComments, OggPictureStorage}; /// # use lofty::{Picture, PictureType, MimeType, PictureInformation}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); /// # let front_cover_info = PictureInformation::default(); /// let mut tag = VorbisComments::default(); @@ -148,7 +148,7 @@ pub trait OggPictureStorage: private::Sealed { /// use lofty::ogg::{VorbisComments, OggPictureStorage}; /// # use lofty::{Picture, PictureType, MimeType, PictureInformation}; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); /// # let front_cover_info = PictureInformation::default(); /// # let back_cover = Picture::new_unchecked(PictureType::CoverBack, Some(MimeType::Png), None, Vec::new()); diff --git a/src/probe.rs b/src/probe.rs index d59ffbabe..404f22c80 100644 --- a/src/probe.rs +++ b/src/probe.rs @@ -32,9 +32,9 @@ use std::path::Path; /// open file. /// /// ```rust,no_run -/// # use lofty::{LoftyError, Probe}; -/// # fn main() -> Result<(), LoftyError> { -/// use lofty::FileType; +/// # fn main() -> lofty::error::Result<()> { +/// use lofty::file::FileType; +/// use lofty::Probe; /// /// let probe = Probe::open("path/to/my.mp3")?; /// @@ -47,9 +47,9 @@ use std::path::Path; /// When a path isn't available, or is unreliable, content-based detection is also possible. /// /// ```rust,no_run -/// # use lofty::{LoftyError, Probe}; -/// # fn main() -> Result<(), LoftyError> { -/// use lofty::FileType; +/// # fn main() -> lofty::error::Result<()> { +/// use lofty::file::FileType; +/// use lofty::Probe; /// /// // Our same path probe with a guessed file type /// let probe = Probe::open("path/to/my.mp3")?.guess_file_type()?; @@ -63,9 +63,9 @@ use std::path::Path; /// Or with another reader /// /// ```rust -/// # use lofty::{LoftyError, Probe}; -/// # fn main() -> Result<(), LoftyError> { -/// use lofty::FileType; +/// # fn main() -> lofty::error::Result<()> { +/// use lofty::file::FileType; +/// use lofty::Probe; /// use std::io::Cursor; /// /// static MAC_HEADER: &[u8; 3] = b"MAC"; @@ -96,7 +96,7 @@ impl Probe { /// use std::fs::File; /// use std::io::BufReader; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// let file = File::open(path)?; /// let reader = BufReader::new(file); @@ -121,11 +121,12 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// use std::fs::File; /// use std::io::BufReader; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let my_mp3_path = "tests/files/assets/minimal/full_test.mp3"; /// // We know the file is going to be an MP3, /// // so we can skip the format detection @@ -148,9 +149,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); /// let probe = Probe::new(reader); /// @@ -166,9 +168,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); /// let mut probe = Probe::new(reader); /// assert_eq!(probe.file_type(), None); @@ -188,9 +191,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{ParseOptions, Probe}; + /// use lofty::config::ParseOptions; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); /// // By default, properties will be read. /// // In this example, we want to turn this off. @@ -210,9 +214,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); /// let probe = Probe::new(reader); /// @@ -237,9 +242,10 @@ impl Probe> { /// # Examples /// /// ```rust,no_run - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let probe = Probe::open("path/to/my.mp3")?; /// /// // Guessed from the "mp3" extension, see `FileType::from_ext` @@ -282,9 +288,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// # let file = std::fs::File::open(path)?; /// # let reader = std::io::BufReader::new(file); @@ -434,9 +441,10 @@ impl Probe { /// # Examples /// /// ```rust - /// use lofty::{FileType, Probe}; + /// use lofty::file::FileType; + /// use lofty::Probe; /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// # let file = std::fs::File::open(path)?; /// # let reader = std::io::BufReader::new(file); @@ -492,7 +500,7 @@ impl Probe { /// use lofty::read_from; /// use std::fs::File; /// -/// # fn main() -> lofty::Result<()> { +/// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// let mut file = File::open(path)?; /// @@ -519,7 +527,7 @@ pub fn read_from(file: &mut File) -> Result { /// ```rust /// use lofty::read_from_path; /// -/// # fn main() -> lofty::Result<()> { +/// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// let parsed_file = read_from_path(path)?; /// # Ok(()) } @@ -534,7 +542,8 @@ where #[cfg(test)] mod tests { use crate::config::{GlobalOptions, ParseOptions}; - use crate::{FileType, Probe}; + use crate::file::FileType; + use crate::Probe; use std::fs::File; From f49deb578bbad1652c7711f7301e154aaf5807dc Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 14:01:48 -0400 Subject: [PATCH 08/22] tag: Remove global re-exports of tag items --- CHANGELOG.md | 2 + examples/custom_resolver/src/main.rs | 2 +- examples/tag_reader.rs | 3 +- examples/tag_writer.rs | 3 +- lofty_attr/src/internal.rs | 15 +-- lofty_attr/src/lofty_file.rs | 8 +- src/ape/tag/item.rs | 4 +- src/ape/tag/mod.rs | 8 +- src/ape/tag/read.rs | 2 +- src/error.rs | 2 +- src/file/tagged_file.rs | 3 +- src/flac/mod.rs | 2 +- src/id3/v1/constants.rs | 2 +- src/id3/v1/tag.rs | 7 +- src/id3/v2/frame/id.rs | 3 +- src/id3/v2/frame/mod.rs | 3 +- src/id3/v2/tag.rs | 5 +- src/id3/v2/util/mappings.rs | 2 +- src/id3/v2/util/pairs.rs | 4 +- src/iff/aiff/tag.rs | 7 +- src/iff/wav/tag/mod.rs | 7 +- src/lib.rs | 10 +- src/mp4/atom_info.rs | 3 +- src/mp4/ilst/mod.rs | 7 +- src/ogg/tag.rs | 7 +- src/tag/mod.rs | 80 +++------------- src/tag/tag_type.rs | 69 ++++++++++++++ src/tag/tagext.rs | 135 +++++++++++++++++++++++++++ src/tag/utils.rs | 2 +- src/traits.rs | 133 -------------------------- tests/files/aac.rs | 3 +- tests/files/aiff.rs | 3 +- tests/files/ape.rs | 3 +- tests/files/mp4.rs | 3 +- tests/files/mpc.rs | 3 +- tests/files/mpeg.rs | 3 +- tests/files/ogg.rs | 3 +- tests/files/util/mod.rs | 14 +-- tests/files/wav.rs | 3 +- tests/files/wavpack.rs | 3 +- tests/tags/conversions.rs | 3 +- 41 files changed, 302 insertions(+), 282 deletions(-) create mode 100644 src/tag/tag_type.rs create mode 100644 src/tag/tagext.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 219ba7578..5ffc9c227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ⚠️ Important ⚠️: Moved to `lofty::options` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) - **AudioFile**/**TaggedFileExt**/**TaggedFile**/**BoundTaggedFile**: - ⚠️ Important ⚠️: Moved to `lofty::file` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) +- **Tag**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**: + - ⚠️ Important ⚠️: Moved to `lofty::tag` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) ### Fixed - **Vorbis**: Fix panic when reading properties of zero-length files ([issue](https://github.com/Serial-ATA/lofty-rs/issues/342)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/365)) diff --git a/examples/custom_resolver/src/main.rs b/examples/custom_resolver/src/main.rs index 51f5c9044..02d9508a4 100644 --- a/examples/custom_resolver/src/main.rs +++ b/examples/custom_resolver/src/main.rs @@ -5,7 +5,7 @@ use lofty::file::FileType; use lofty::id3::v2::Id3v2Tag; use lofty::properties::FileProperties; use lofty::resolve::FileResolver; -use lofty::TagType; +use lofty::tag::TagType; use lofty_attr::LoftyFile; use std::fs::File; diff --git a/examples/tag_reader.rs b/examples/tag_reader.rs index 4849529a0..1db62beac 100644 --- a/examples/tag_reader.rs +++ b/examples/tag_reader.rs @@ -33,8 +33,7 @@ fn main() { // import keys from https://docs.rs/lofty/latest/lofty/enum.ItemKey.html println!( "Album Artist: {}", - tag.get_string(&lofty::ItemKey::AlbumArtist) - .unwrap_or("None") + tag.get_string(&ItemKey::AlbumArtist).unwrap_or("None") ); let properties = tagged_file.properties(); diff --git a/examples/tag_writer.rs b/examples/tag_writer.rs index 745283e18..18dd65f9c 100644 --- a/examples/tag_writer.rs +++ b/examples/tag_writer.rs @@ -1,6 +1,7 @@ use lofty::config::WriteOptions; use lofty::prelude::*; -use lofty::{Probe, Tag}; +use lofty::tag::Tag; +use lofty::Probe; use structopt::StructOpt; diff --git a/lofty_attr/src/internal.rs b/lofty_attr/src/internal.rs index e46158f7a..6123dde7d 100644 --- a/lofty_attr/src/internal.rs +++ b/lofty_attr/src/internal.rs @@ -78,10 +78,10 @@ pub(crate) fn init_write_lookup( insert!(map, AiffText, { lofty::iff::aiff::tag::AiffTextChunksRef { - name: tag.get_string(&lofty::tag::item::ItemKey::TrackTitle), - author: tag.get_string(&lofty::tag::item::ItemKey::TrackArtist), - copyright: tag.get_string(&lofty::tag::item::ItemKey::CopyrightMessage), - annotations: Some(tag.get_strings(&lofty::tag::item::ItemKey::Comment)), + name: tag.get_string(&lofty::prelude::ItemKey::TrackTitle), + author: tag.get_string(&lofty::prelude::ItemKey::TrackArtist), + copyright: tag.get_string(&lofty::prelude::ItemKey::CopyrightMessage), + annotations: Some(tag.get_strings(&lofty::prelude::ItemKey::Comment)), comments: None, } .write_to(data, write_options) @@ -96,11 +96,12 @@ pub(crate) fn write_module( ) -> proc_macro2::TokenStream { let applicable_formats = fields.iter().map(|f| { let tag_ty = - syn::parse_str::(&format!("::lofty::TagType::{}", &f.tag_type)).unwrap(); + syn::parse_str::(&format!("::lofty::tag::TagType::{}", &f.tag_type)) + .unwrap(); let cfg_features = f.get_cfg_features(); - let block = lookup.get(&*tag_ty.segments[2].ident.to_string()).unwrap(); + let block = lookup.get(&*tag_ty.segments[3].ident.to_string()).unwrap(); quote! { #( #cfg_features )* @@ -111,7 +112,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::config::WriteOptions) -> ::lofty::error::Result<()> { + pub(crate) fn write_to(data: &mut ::std::fs::File, tag: &::lofty::tag::Tag, write_options: ::lofty::config::WriteOptions) -> ::lofty::error::Result<()> { match tag.tag_type() { #( #applicable_formats )* _ => crate::macros::err!(UnsupportedTag), diff --git a/lofty_attr/src/lofty_file.rs b/lofty_attr/src/lofty_file.rs index 85db78a4d..250151a1c 100644 --- a/lofty_attr/src/lofty_file.rs +++ b/lofty_attr/src/lofty_file.rs @@ -446,7 +446,7 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result ::lofty::error::Result<()> { - use ::lofty::prelude::TagExt as _; + use ::lofty::tag::TagExt as _; use ::std::io::Seek as _; #save_to_body } @@ -461,9 +461,9 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result bool { + fn contains_tag_type(&self, tag_type: ::lofty::tag::TagType) -> bool { match tag_type { - #( ::lofty::TagType::#tag_type => { #tag_exists_2 } ),* + #( ::lofty::tag::TagType::#tag_type => { #tag_exists_2 } ),* _ => false } } @@ -539,7 +539,7 @@ fn generate_from_taggedfile_impl(file: &LoftyFile) -> proc_macro2::TokenStream { #file_type_variant, ::lofty::properties::FileProperties::from(input.properties), { - let mut tags: Vec<::lofty::Tag> = Vec::new(); + let mut tags: Vec<::lofty::tag::Tag> = Vec::new(); #( #conditions )* tags diff --git a/src/ape/tag/item.rs b/src/ape/tag/item.rs index 90b5a5dd7..3cc8118dd 100644 --- a/src/ape/tag/item.rs +++ b/src/ape/tag/item.rs @@ -1,8 +1,8 @@ use crate::ape::constants::INVALID_KEYS; use crate::error::{LoftyError, Result}; use crate::macros::decode_err; -use crate::tag::item::{ItemValue, ItemValueRef, TagItem}; -use crate::tag::TagType; +use crate::tag::item::ItemValueRef; +use crate::tag::{ItemValue, TagItem, TagType}; /// Represents an `APE` tag item /// diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index b0056f812..36d9acaf2 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -6,9 +6,9 @@ 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::tag::item::ItemValueRef; +use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -547,7 +547,7 @@ mod tests { use crate::config::WriteOptions; use crate::id3::v2::util::pairs::DEFAULT_NUMBER_IN_PAIR; use crate::prelude::*; - use crate::{ItemValue, Tag, TagItem, TagType}; + use crate::tag::{ItemValue, Tag, TagItem, TagType}; use std::io::Cursor; diff --git a/src/ape/tag/read.rs b/src/ape/tag/read.rs index a4677adba..6096de00b 100644 --- a/src/ape/tag/read.rs +++ b/src/ape/tag/read.rs @@ -4,7 +4,7 @@ use crate::ape::constants::{APE_PREAMBLE, INVALID_KEYS}; use crate::ape::header::{self, ApeHeader}; use crate::error::Result; use crate::macros::{decode_err, err, try_vec}; -use crate::tag::item::ItemValue; +use crate::tag::ItemValue; use crate::util::text::utf8_decode; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/error.rs b/src/error.rs index 0c2a01f0d..a34e95654 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,7 +5,7 @@ use crate::file::FileType; use crate::id3::v2::FrameId; -use crate::tag::item::ItemKey; +use crate::tag::ItemKey; use std::collections::TryReserveError; use std::fmt::{Debug, Display, Formatter}; diff --git a/src/file/tagged_file.rs b/src/file/tagged_file.rs index c66262a5d..24be35c91 100644 --- a/src/file/tagged_file.rs +++ b/src/file/tagged_file.rs @@ -3,8 +3,7 @@ use super::file_type::FileType; use crate::config::{ParseOptions, WriteOptions}; use crate::error::Result; use crate::properties::FileProperties; -use crate::tag::{Tag, TagType}; -use crate::traits::TagExt; +use crate::tag::{Tag, TagExt, TagType}; use std::fs::File; use std::io::{Read, Seek}; diff --git a/src/flac/mod.rs b/src/flac/mod.rs index 4ff7642c8..01102dc00 100644 --- a/src/flac/mod.rs +++ b/src/flac/mod.rs @@ -16,7 +16,7 @@ use crate::id3::v2::tag::Id3v2Tag; use crate::ogg::tag::VorbisCommentsRef; use crate::ogg::{OggPictureStorage, VorbisComments}; use crate::picture::{Picture, PictureInformation}; -use crate::traits::TagExt; +use crate::tag::TagExt; use std::fs::File; use std::io::Seek; diff --git a/src/id3/v1/constants.rs b/src/id3/v1/constants.rs index e52fd111e..15352612a 100644 --- a/src/id3/v1/constants.rs +++ b/src/id3/v1/constants.rs @@ -194,7 +194,7 @@ pub const GENRES: [&str; 192] = [ "Psybient", ]; -use crate::tag::item::ItemKey; +use crate::tag::ItemKey; pub(crate) const VALID_ITEMKEYS: [ItemKey; 7] = [ ItemKey::TrackTitle, ItemKey::TrackArtist, diff --git a/src/id3/v1/tag.rs b/src/id3/v1/tag.rs index 84f88f08f..b09cfac76 100644 --- a/src/id3/v1/tag.rs +++ b/src/id3/v1/tag.rs @@ -1,9 +1,8 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::id3::v1::constants::GENRES; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -443,7 +442,7 @@ mod tests { use crate::config::WriteOptions; use crate::id3::v1::Id3v1Tag; use crate::prelude::*; - use crate::{Tag, TagType}; + use crate::tag::{Tag, TagType}; #[test] fn parse_id3v1() { diff --git a/src/id3/v2/frame/id.rs b/src/id3/v2/frame/id.rs index a43139085..419e32f68 100644 --- a/src/id3/v2/frame/id.rs +++ b/src/id3/v2/frame/id.rs @@ -2,8 +2,7 @@ use std::borrow::Cow; use std::fmt::{Display, Formatter}; use crate::error::{Id3v2Error, Id3v2ErrorKind, LoftyError, Result}; -use crate::tag::item::ItemKey; -use crate::tag::TagType; +use crate::tag::{ItemKey, TagType}; /// An `ID3v2` frame ID /// diff --git a/src/id3/v2/frame/mod.rs b/src/id3/v2/frame/mod.rs index d2b8ea9cd..5b4516751 100644 --- a/src/id3/v2/frame/mod.rs +++ b/src/id3/v2/frame/mod.rs @@ -11,8 +11,7 @@ use super::items::{ }; use super::util::upgrade::{upgrade_v2, upgrade_v3}; use crate::error::{ErrorKind, Id3v2Error, Id3v2ErrorKind, LoftyError, Result}; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::TagType; +use crate::tag::{ItemKey, ItemValue, TagItem, TagType}; use crate::util::text::TextEncoding; use id::FrameId; diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 81feae692..b76beea8d 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -18,9 +18,8 @@ use crate::id3::v2::util::pairs::{ }; use crate::id3::v2::KeyValueFrame; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{try_parse_year, Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding}; use std::borrow::Cow; diff --git a/src/id3/v2/util/mappings.rs b/src/id3/v2/util/mappings.rs index 269ec87df..7e62af06c 100644 --- a/src/id3/v2/util/mappings.rs +++ b/src/id3/v2/util/mappings.rs @@ -1,4 +1,4 @@ -use crate::tag::item::ItemKey; +use crate::tag::ItemKey; pub(crate) const TIPL_MAPPINGS: &[(ItemKey, &str)] = &[ (ItemKey::Producer, "producer"), diff --git a/src/id3/v2/util/pairs.rs b/src/id3/v2/util/pairs.rs index cfe1d2673..586c8b848 100644 --- a/src/id3/v2/util/pairs.rs +++ b/src/id3/v2/util/pairs.rs @@ -1,6 +1,6 @@ //! Contains utilities for ID3v2 style number pairs -use crate::tag::item::{ItemKey, TagItem}; +use crate::tag::{ItemKey, TagItem}; use std::fmt::Display; @@ -58,7 +58,7 @@ pub(crate) fn set_number(item: &TagItem, mut setter: F) { #[cfg(test)] mod tests { use crate::id3::v2::util::pairs::set_number; - use crate::{ItemKey, ItemValue, TagItem}; + use crate::tag::{ItemKey, ItemValue, TagItem}; #[test] fn whitespace_in_number() { diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 42bb48fb6..86cd23561 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -2,9 +2,8 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::iff::chunk::Chunks; use crate::macros::err; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -486,7 +485,7 @@ mod tests { use crate::config::{ParseOptions, WriteOptions}; use crate::iff::aiff::{AIFFTextChunks, Comment}; use crate::prelude::*; - use crate::{ItemValue, Tag, TagItem, TagType}; + use crate::tag::{ItemValue, Tag, TagItem, TagType}; use std::io::Cursor; diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index 10cd663e8..c3ac45891 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -3,9 +3,8 @@ mod write; use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{try_parse_year, Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -352,7 +351,7 @@ mod tests { use crate::iff::chunk::Chunks; use crate::iff::wav::RIFFInfoList; use crate::prelude::*; - use crate::{Tag, TagType}; + use crate::tag::{Tag, TagType}; use byteorder::LittleEndian; diff --git a/src/lib.rs b/src/lib.rs index f836398a6..48d8170a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,7 +159,7 @@ pub(crate) mod picture; mod probe; pub mod properties; pub mod resolve; -pub(crate) mod tag; +pub mod tag; mod traits; mod util; @@ -177,8 +177,6 @@ pub mod wavpack; pub use crate::probe::{read_from, read_from_path, Probe}; pub use crate::picture::{MimeType, Picture, PictureType}; -pub use crate::tag::{Tag, TagType}; -pub use tag::item::{ItemKey, ItemValue, TagItem}; pub use util::text::TextEncoding; pub use picture::PictureInformation; @@ -188,7 +186,7 @@ pub use lofty_attr::LoftyFile; pub mod prelude { //! A prelude for commonly used items in the library. //! - //! This module is intended to be glob imported. + //! This module is intended to be wildcard imported. //! //! ```rust //! use lofty::prelude::*; @@ -196,6 +194,6 @@ pub mod prelude { pub use crate::error::LoftyError; pub use crate::file::{AudioFile, TaggedFileExt}; - pub use crate::tag::item::ItemKey; - pub use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; + pub use crate::tag::{ItemKey, TagExt}; + pub use crate::traits::{Accessor, MergeTag, SplitTag}; } diff --git a/src/mp4/atom_info.rs b/src/mp4/atom_info.rs index 90085bb65..7a21de525 100644 --- a/src/mp4/atom_info.rs +++ b/src/mp4/atom_info.rs @@ -1,8 +1,7 @@ use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{err, try_vec}; -use crate::tag::item::ItemKey; -use crate::tag::TagType; +use crate::tag::{ItemKey, TagType}; use crate::util::text::utf8_decode; use std::borrow::Cow; diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 5520bd128..08266e01e 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -9,9 +9,8 @@ use crate::config::WriteOptions; use crate::error::LoftyError; use crate::mp4::ilst::atom::AtomDataStorage; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{try_parse_year, Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use atom::{AdvisoryRating, Atom, AtomData}; use std::borrow::Cow; @@ -767,7 +766,7 @@ mod tests { use crate::prelude::*; use crate::tag::utils::test_utils; use crate::tag::utils::test_utils::read_path; - use crate::{ItemValue, Tag, TagItem, TagType}; + use crate::tag::{ItemValue, Tag, TagItem, TagType}; use std::io::{Cursor, Read as _, Seek as _, Write as _}; diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index d9b2291c6..97db0a3e5 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -6,9 +6,8 @@ use crate::ogg::picture_storage::OggPictureStorage; use crate::ogg::write::OGGFormat; use crate::picture::{Picture, PictureInformation}; use crate::probe::Probe; -use crate::tag::item::{ItemKey, ItemValue, TagItem}; -use crate::tag::{try_parse_year, Tag, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; +use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -696,7 +695,7 @@ mod tests { use crate::config::{ParsingMode, WriteOptions}; use crate::ogg::{OggPictureStorage, VorbisComments}; use crate::prelude::*; - use crate::{ItemValue, Tag, TagItem, TagType}; + use crate::tag::{ItemValue, Tag, TagItem, TagType}; fn read_tag(tag: &[u8]) -> VorbisComments { let mut reader = std::io::Cursor::new(tag); diff --git a/src/tag/mod.rs b/src/tag/mod.rs index 87cd00afa..539dba28d 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -1,20 +1,27 @@ +//! Utilities for generic tag handling + pub(crate) mod item; +mod tag_type; +mod tagext; pub(crate) mod utils; use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; -use crate::file::FileType; use crate::macros::err; use crate::picture::{Picture, PictureType}; use crate::probe::Probe; -use crate::traits::{Accessor, MergeTag, SplitTag, TagExt}; -use item::{ItemKey, ItemValue, TagItem}; +use crate::traits::{Accessor, MergeTag, SplitTag}; use std::borrow::Cow; -use std::fs::{File, OpenOptions}; +use std::fs::File; use std::io::Write; use std::path::Path; +// Exports +pub use item::{ItemKey, ItemValue, TagItem}; +pub use tag_type::TagType; +pub use tagext::TagExt; + macro_rules! impl_accessor { ($($item_key:ident => $name:tt),+) => { paste::paste! { @@ -581,6 +588,7 @@ impl TagExt for Tag { } #[derive(Debug, Clone, Default)] +#[allow(missing_docs)] pub struct SplitTagRemainder; impl SplitTag for Tag { @@ -599,74 +607,14 @@ impl MergeTag for SplitTagRemainder { } } -/// The tag's format -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[non_exhaustive] -pub enum TagType { - /// This covers both APEv1 and APEv2 as it doesn't matter much - Ape, - /// Represents an ID3v1 tag - Id3v1, - /// This covers all ID3v2 versions since they all get upgraded to ID3v2.4 - Id3v2, - /// Represents an MP4 ilst atom - Mp4Ilst, - /// Represents vorbis comments - VorbisComments, - /// Represents a RIFF INFO LIST - RiffInfo, - /// Represents AIFF text chunks - AiffText, -} - -impl TagType { - /// Remove a tag from a [`Path`] - /// - /// # Errors - /// - /// See [`TagType::remove_from`] - pub fn remove_from_path(&self, path: impl AsRef) -> Result<()> { - let mut file = OpenOptions::new().read(true).write(true).open(path)?; - self.remove_from(&mut file) - } - - #[allow(clippy::shadow_unrelated)] - /// Remove a tag from a [`File`] - /// - /// # Errors - /// - /// * It is unable to guess the file format - /// * The format doesn't support the tag - /// * It is unable to write to the file - pub fn remove_from(&self, file: &mut File) -> Result<()> { - let probe = Probe::new(file).guess_file_type()?; - let Some(file_type) = probe.file_type() else { - err!(UnknownFormat); - }; - - // TODO: This should not have to be manually updated - let special_exceptions = ((file_type == FileType::Ape - || file_type == FileType::Mpc - || file_type == FileType::Flac) - && *self == TagType::Id3v2) - || file_type == FileType::Mpc && *self == TagType::Id3v1; - - if !special_exceptions && !file_type.supports_tag_type(*self) { - err!(UnsupportedTag); - } - - let file = probe.into_inner(); - utils::write_tag(&Tag::new(*self), file, file_type, WriteOptions::default()) // TODO - } -} - #[cfg(test)] mod tests { use super::try_parse_year; use crate::config::WriteOptions; use crate::prelude::*; use crate::tag::utils::test_utils::read_path; - use crate::{Picture, PictureType, Tag, TagType}; + use crate::tag::{Tag, TagType}; + use crate::{Picture, PictureType}; use std::io::{Seek, Write}; use std::process::Command; diff --git a/src/tag/tag_type.rs b/src/tag/tag_type.rs new file mode 100644 index 000000000..628779a82 --- /dev/null +++ b/src/tag/tag_type.rs @@ -0,0 +1,69 @@ +use super::{utils, Tag}; +use crate::config::WriteOptions; +use crate::file::FileType; +use crate::macros::err; +use crate::probe::Probe; + +use std::fs::{File, OpenOptions}; +use std::path::Path; + +/// The tag's format +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum TagType { + /// This covers both APEv1 and APEv2 as it doesn't matter much + Ape, + /// Represents an ID3v1 tag + Id3v1, + /// This covers all ID3v2 versions since they all get upgraded to ID3v2.4 + Id3v2, + /// Represents an MP4 ilst atom + Mp4Ilst, + /// Represents vorbis comments + VorbisComments, + /// Represents a RIFF INFO LIST + RiffInfo, + /// Represents AIFF text chunks + AiffText, +} + +impl TagType { + /// Remove a tag from a [`Path`] + /// + /// # Errors + /// + /// See [`TagType::remove_from`] + pub fn remove_from_path(&self, path: impl AsRef) -> crate::error::Result<()> { + let mut file = OpenOptions::new().read(true).write(true).open(path)?; + self.remove_from(&mut file) + } + + #[allow(clippy::shadow_unrelated)] + /// Remove a tag from a [`File`] + /// + /// # Errors + /// + /// * It is unable to guess the file format + /// * The format doesn't support the tag + /// * It is unable to write to the file + pub fn remove_from(&self, file: &mut File) -> crate::error::Result<()> { + let probe = Probe::new(file).guess_file_type()?; + let Some(file_type) = probe.file_type() else { + err!(UnknownFormat); + }; + + // TODO: This should not have to be manually updated + let special_exceptions = ((file_type == FileType::Ape + || file_type == FileType::Mpc + || file_type == FileType::Flac) + && *self == TagType::Id3v2) + || file_type == FileType::Mpc && *self == TagType::Id3v1; + + if !special_exceptions && !file_type.supports_tag_type(*self) { + err!(UnsupportedTag); + } + + let file = probe.into_inner(); + utils::write_tag(&Tag::new(*self), file, file_type, WriteOptions::default()) // TODO + } +} diff --git a/src/tag/tagext.rs b/src/tag/tagext.rs new file mode 100644 index 000000000..46fb95718 --- /dev/null +++ b/src/tag/tagext.rs @@ -0,0 +1,135 @@ +use crate::config::WriteOptions; +use crate::tag::Tag; +use crate::traits::Accessor; + +use std::fs::File; +use std::path::Path; + +/// A set of common methods between tags +/// +/// This provides a set of methods to make interaction with all tags a similar +/// experience. +/// +/// This can be implemented downstream to provide a familiar interface for custom tags. +pub trait TagExt: Accessor + Into + Sized { + /// The associated error which can be returned from IO operations + type Err: From; + /// The type of key used in the tag for non-mutating functions + type RefKey<'a> + where + Self: 'a; + + /// Returns the number of items in the tag + /// + /// This will also include any extras, such as pictures. + /// + /// # Example + /// + /// ```rust + /// use lofty::{Accessor, ItemKey, Tag, TagExt}; + /// # let tag_type = lofty::TagType::Id3v2; + /// + /// let mut tag = Tag::new(tag_type); + /// assert_eq!(tag.len(), 0); + /// + /// tag.set_artist(String::from("Foo artist")); + /// assert_eq!(tag.len(), 1); + /// ``` + fn len(&self) -> usize; + + /// Whether the tag contains an item with the key + /// + /// # Example + /// + /// ```rust + /// use lofty::{Accessor, ItemKey, Tag, TagExt}; + /// # let tag_type = lofty::TagType::Id3v2; + /// + /// let mut tag = Tag::new(tag_type); + /// assert!(tag.is_empty()); + /// + /// tag.set_artist(String::from("Foo artist")); + /// assert!(tag.contains(&ItemKey::TrackArtist)); + /// ``` + fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool; + + /// Whether the tag has any items + /// + /// # Example + /// + /// ```rust + /// use lofty::{Accessor, Tag, TagExt}; + /// # let tag_type = lofty::TagType::Id3v2; + /// + /// let mut tag = Tag::new(tag_type); + /// assert!(tag.is_empty()); + /// + /// tag.set_artist(String::from("Foo artist")); + /// assert!(!tag.is_empty()); + /// ``` + fn is_empty(&self) -> bool; + + /// Save the tag to a path + /// + /// # Errors + /// + /// * Path doesn't exist + /// * Path is not writable + /// * See [`TagExt::save_to`] + fn save_to_path>( + &self, + path: P, + write_options: WriteOptions, + ) -> std::result::Result<(), Self::Err> { + self.save_to( + &mut std::fs::OpenOptions::new() + .read(true) + .write(true) + .open(path)?, + write_options, + ) + } + + /// Save the tag to a [`File`] + /// + /// # Errors + /// + /// * The file format could not be determined + /// * Attempting to write a tag to a format that does not support it. + fn save_to( + &self, + file: &mut File, + write_options: WriteOptions, + ) -> std::result::Result<(), Self::Err>; + + #[allow(clippy::missing_errors_doc)] + /// Dump the tag to a writer + /// + /// This will only write the tag, it will not produce a usable file. + fn dump_to( + &self, + writer: &mut W, + write_options: WriteOptions, + ) -> std::result::Result<(), Self::Err>; + + /// Remove a tag from a [`Path`] + /// + /// # Errors + /// + /// See [`TagExt::remove_from`] + fn remove_from_path>(&self, path: P) -> std::result::Result<(), Self::Err>; + + /// Remove a tag from a [`File`] + /// + /// # Errors + /// + /// * It is unable to guess the file format + /// * The format doesn't support the tag + /// * It is unable to write to the file + fn remove_from(&self, file: &mut File) -> std::result::Result<(), Self::Err>; + + /// Clear the tag, removing all items + /// + /// NOTE: This will **not** remove any format-specific extras, such as flags + fn clear(&mut self); +} diff --git a/src/tag/utils.rs b/src/tag/utils.rs index 10673b523..2683764e0 100644 --- a/src/tag/utils.rs +++ b/src/tag/utils.rs @@ -99,7 +99,7 @@ pub(crate) fn dump_tag( #[cfg(test)] // Used for tag conversion tests pub(crate) mod test_utils { - use crate::{ItemKey, Tag, TagType}; + use crate::tag::{ItemKey, Tag, TagType}; use std::fs::File; use std::io::Read; diff --git a/src/traits.rs b/src/traits.rs index 973dfb81b..0e3c0ba81 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -118,141 +118,8 @@ accessor_trait! { [year ], [comment ], String>, } -use crate::config::WriteOptions; use crate::tag::Tag; -use std::fs::File; -use std::path::Path; - -/// A set of common methods between tags -/// -/// This provides a set of methods to make interaction with all tags a similar -/// experience. -/// -/// This can be implemented downstream to provide a familiar interface for custom tags. -pub trait TagExt: Accessor + Into + Sized { - /// The associated error which can be returned from IO operations - type Err: From; - /// The type of key used in the tag for non-mutating functions - type RefKey<'a> - where - Self: 'a; - - /// Returns the number of items in the tag - /// - /// This will also include any extras, such as pictures. - /// - /// # Example - /// - /// ```rust - /// use lofty::{Accessor, ItemKey, Tag, TagExt}; - /// # let tag_type = lofty::TagType::Id3v2; - /// - /// let mut tag = Tag::new(tag_type); - /// assert_eq!(tag.len(), 0); - /// - /// tag.set_artist(String::from("Foo artist")); - /// assert_eq!(tag.len(), 1); - /// ``` - fn len(&self) -> usize; - - /// Whether the tag contains an item with the key - /// - /// # Example - /// - /// ```rust - /// use lofty::{Accessor, ItemKey, Tag, TagExt}; - /// # let tag_type = lofty::TagType::Id3v2; - /// - /// let mut tag = Tag::new(tag_type); - /// assert!(tag.is_empty()); - /// - /// tag.set_artist(String::from("Foo artist")); - /// assert!(tag.contains(&ItemKey::TrackArtist)); - /// ``` - fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool; - - /// Whether the tag has any items - /// - /// # Example - /// - /// ```rust - /// use lofty::{Accessor, Tag, TagExt}; - /// # let tag_type = lofty::TagType::Id3v2; - /// - /// let mut tag = Tag::new(tag_type); - /// assert!(tag.is_empty()); - /// - /// tag.set_artist(String::from("Foo artist")); - /// assert!(!tag.is_empty()); - /// ``` - fn is_empty(&self) -> bool; - - /// Save the tag to a path - /// - /// # Errors - /// - /// * Path doesn't exist - /// * Path is not writable - /// * See [`TagExt::save_to`] - fn save_to_path>( - &self, - path: P, - write_options: WriteOptions, - ) -> std::result::Result<(), Self::Err> { - self.save_to( - &mut std::fs::OpenOptions::new() - .read(true) - .write(true) - .open(path)?, - write_options, - ) - } - - /// Save the tag to a [`File`] - /// - /// # Errors - /// - /// * The file format could not be determined - /// * Attempting to write a tag to a format that does not support it. - fn save_to( - &self, - file: &mut File, - write_options: WriteOptions, - ) -> std::result::Result<(), Self::Err>; - - #[allow(clippy::missing_errors_doc)] - /// Dump the tag to a writer - /// - /// This will only write the tag, it will not produce a usable file. - fn dump_to( - &self, - writer: &mut W, - write_options: WriteOptions, - ) -> std::result::Result<(), Self::Err>; - - /// Remove a tag from a [`Path`] - /// - /// # Errors - /// - /// See [`TagExt::remove_from`] - fn remove_from_path>(&self, path: P) -> std::result::Result<(), Self::Err>; - - /// Remove a tag from a [`File`] - /// - /// # Errors - /// - /// * It is unable to guess the file format - /// * The format doesn't support the tag - /// * It is unable to write to the file - fn remove_from(&self, file: &mut File) -> std::result::Result<(), Self::Err>; - - /// Clear the tag, removing all items - /// - /// NOTE: This will **not** remove any format-specific extras, such as flags - fn clear(&mut self); -} - /// Split (and merge) tags. /// /// Useful and required for implementing lossless read/modify/write round trips. diff --git a/tests/files/aac.rs b/tests/files/aac.rs index 0b9a448ef..6cf2142ad 100644 --- a/tests/files/aac.rs +++ b/tests/files/aac.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/aiff.rs b/tests/files/aiff.rs index 92563b1b1..85799da6c 100644 --- a/tests/files/aiff.rs +++ b/tests/files/aiff.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/ape.rs b/tests/files/ape.rs index 5cf9648fd..bddb597e0 100644 --- a/tests/files/ape.rs +++ b/tests/files/ape.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mp4.rs b/tests/files/mp4.rs index 11a77ce13..630375097 100644 --- a/tests/files/mp4.rs +++ b/tests/files/mp4.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mpc.rs b/tests/files/mpc.rs index 971f27be0..77e725f8c 100644 --- a/tests/files/mpc.rs +++ b/tests/files/mpc.rs @@ -3,7 +3,8 @@ use lofty::config::ParseOptions; use lofty::file::{FileType, TaggedFile}; use lofty::musepack::MpcFile; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mpeg.rs b/tests/files/mpeg.rs index 49acd59eb..80f7e2ce6 100644 --- a/tests/files/mpeg.rs +++ b/tests/files/mpeg.rs @@ -4,7 +4,8 @@ use lofty::file::FileType; use lofty::id3::v2::{Frame, FrameFlags, FrameId, FrameValue, Id3v2Tag, KeyValueFrame}; use lofty::mpeg::MpegFile; use lofty::prelude::*; -use lofty::{Probe, Tag, TagType}; +use lofty::tag::{Tag, TagType}; +use lofty::Probe; use std::borrow::Cow; use std::io::{Seek, Write}; diff --git a/tests/files/ogg.rs b/tests/files/ogg.rs index 5b5fb6b9b..50df20b3d 100644 --- a/tests/files/ogg.rs +++ b/tests/files/ogg.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::{ParseOptions, WriteOptions}; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/util/mod.rs b/tests/files/util/mod.rs index 5f3f05ade..23a15d812 100644 --- a/tests/files/util/mod.rs +++ b/tests/files/util/mod.rs @@ -30,10 +30,10 @@ macro_rules! verify_artist { assert_eq!(tag.item_count(), $item_count); assert_eq!( - tag.get(&lofty::ItemKey::TrackArtist), - Some(&lofty::TagItem::new( - lofty::ItemKey::TrackArtist, - lofty::ItemValue::Text(String::from($expected_value)) + tag.get(&lofty::prelude::ItemKey::TrackArtist), + Some(&lofty::tag::TagItem::new( + lofty::prelude::ItemKey::TrackArtist, + lofty::tag::ItemValue::Text(String::from($expected_value)) )) ); @@ -62,9 +62,9 @@ macro_rules! set_artist { set_artist!($file_write, $new_value, tag) }; ($file_write:ident, $new_value:literal, $tag:ident) => { - $tag.insert_unchecked(lofty::TagItem::new( - lofty::ItemKey::TrackArtist, - lofty::ItemValue::Text(String::from($new_value)), + $tag.insert_unchecked(lofty::tag::TagItem::new( + lofty::prelude::ItemKey::TrackArtist, + lofty::tag::ItemValue::Text(String::from($new_value)), )); $file_write.rewind().unwrap(); diff --git a/tests/files/wav.rs b/tests/files/wav.rs index 7bda63a0f..7e925c8a2 100644 --- a/tests/files/wav.rs +++ b/tests/files/wav.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index fcd6fea6b..72a77ffca 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -2,7 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; -use lofty::{Probe, TagType}; +use lofty::tag::TagType; +use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/tags/conversions.rs b/tests/tags/conversions.rs index b861b4548..c7e0f7b3f 100644 --- a/tests/tags/conversions.rs +++ b/tests/tags/conversions.rs @@ -1,7 +1,8 @@ // Tests for special case conversions use lofty::id3::v2::{CommentFrame, Frame, FrameFlags, FrameId, Id3v2Tag, UnsynchronizedTextFrame}; -use lofty::{ItemKey, Tag, TagType, TextEncoding}; +use lofty::tag::{ItemKey, Tag, TagType}; +use lofty::TextEncoding; use std::borrow::Cow; #[test] From 2b1c6f8de23bdc95ead3633d71807a39e9d37495 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 13 Apr 2024 14:09:51 -0400 Subject: [PATCH 09/22] doc: Fix a bunch more test imports --- src/ape/tag/mod.rs | 2 +- src/config/write_options.rs | 6 +++--- src/file/file_type.rs | 4 ++-- src/file/tagged_file.rs | 26 +++++++++++++------------- src/id3/v1/tag.rs | 2 +- src/id3/v2/tag.rs | 9 +++++---- src/iff/aiff/tag.rs | 2 +- src/iff/wav/tag/mod.rs | 2 +- src/lib.rs | 2 +- src/mp4/ilst/mod.rs | 8 +++++--- src/ogg/tag.rs | 4 ++-- src/tag/mod.rs | 13 ++++++++----- src/tag/tagext.rs | 11 +++++++---- src/traits.rs | 9 +++++---- 14 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index 36d9acaf2..a49c35323 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -89,7 +89,7 @@ impl ApeTag { /// /// ```rust /// use lofty::ape::ApeTag; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let ape_tag = ApeTag::new(); /// assert!(ape_tag.is_empty()); diff --git a/src/config/write_options.rs b/src/config/write_options.rs index de90df2c2..b7c70ebd6 100644 --- a/src/config/write_options.rs +++ b/src/config/write_options.rs @@ -73,7 +73,7 @@ impl WriteOptions { /// ```rust,no_run /// use lofty::config::WriteOptions; /// use lofty::prelude::*; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); @@ -103,7 +103,7 @@ impl WriteOptions { /// ```rust,no_run /// use lofty::config::WriteOptions; /// use lofty::prelude::*; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); @@ -133,7 +133,7 @@ impl WriteOptions { /// ```rust,no_run /// use lofty::config::WriteOptions; /// use lofty::prelude::*; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// /// # fn main() -> lofty::error::Result<()> { /// let mut id3v2_tag = Tag::new(TagType::Id3v2); diff --git a/src/file/file_type.rs b/src/file/file_type.rs index 38a02fae4..46535dd93 100644 --- a/src/file/file_type.rs +++ b/src/file/file_type.rs @@ -43,7 +43,7 @@ impl FileType { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// let file_type = FileType::Mpeg; /// assert_eq!(file_type.primary_tag_type(), TagType::Id3v2); @@ -77,7 +77,7 @@ impl FileType { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// let file_type = FileType::Mpeg; /// assert!(file_type.supports_tag_type(TagType::Id3v2)); diff --git a/src/file/tagged_file.rs b/src/file/tagged_file.rs index 24be35c91..c9185fefd 100644 --- a/src/file/tagged_file.rs +++ b/src/file/tagged_file.rs @@ -53,7 +53,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -72,7 +72,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -91,7 +91,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -113,7 +113,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -139,7 +139,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -165,7 +165,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::TaggedFileExt; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -244,7 +244,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::{AudioFile, TaggedFileExt}; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -269,7 +269,7 @@ pub trait TaggedFileExt { /// /// ```rust /// use lofty::file::{AudioFile, TaggedFileExt}; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -340,7 +340,7 @@ impl TaggedFile { /// /// ```rust /// use lofty::file::{AudioFile, FileType, TaggedFileExt}; - /// use lofty::TagType; + /// use lofty::tag::TagType; /// /// # fn main() -> lofty::error::Result<()> { /// # let path_to_mp3 = "tests/files/assets/minimal/full_test.mp3"; @@ -461,7 +461,7 @@ impl From for TaggedFile { /// ```rust,no_run /// use lofty::config::WriteOptions; /// use lofty::file::{AudioFile, TaggedFileExt}; -/// use lofty::{Tag, TagType}; +/// use lofty::tag::{Tag, TagType}; /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; /// @@ -486,7 +486,7 @@ impl From for TaggedFile { /// ```rust,no_run /// use lofty::config::{ParseOptions, WriteOptions}; /// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; -/// use lofty::{Tag, TagType}; +/// use lofty::tag::{Tag, TagType}; /// use std::fs::OpenOptions; /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; @@ -526,7 +526,7 @@ impl BoundTaggedFile { /// ```rust /// use lofty::config::ParseOptions; /// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// use std::fs::OpenOptions; /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; @@ -559,7 +559,7 @@ impl BoundTaggedFile { /// ```rust,no_run /// use lofty::config::{ParseOptions, WriteOptions}; /// use lofty::file::{AudioFile, BoundTaggedFile, TaggedFileExt}; - /// use lofty::{Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; /// use std::fs::OpenOptions; /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; diff --git a/src/id3/v1/tag.rs b/src/id3/v1/tag.rs index b09cfac76..1272ac21a 100644 --- a/src/id3/v1/tag.rs +++ b/src/id3/v1/tag.rs @@ -114,7 +114,7 @@ impl Id3v1Tag { /// /// ```rust /// use lofty::id3::v1::Id3v1Tag; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let id3v1_tag = Id3v1Tag::new(); /// assert!(id3v1_tag.is_empty()); diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index b76beea8d..780b7e9ae 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -154,7 +154,7 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::Id3v2Tag; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let id3v2_tag = Id3v2Tag::new(); /// assert!(id3v2_tag.is_empty()); @@ -313,7 +313,7 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::Id3v2Tag; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let mut tag = Id3v2Tag::new(); /// @@ -375,7 +375,7 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::Id3v2Tag; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let mut tag = Id3v2Tag::new(); /// assert!(tag.is_empty()); @@ -412,7 +412,8 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::{Frame, FrameFlags, FrameId, Id3v2Tag, TextInformationFrame}; - /// use lofty::{TagExt, TextEncoding}; + /// use lofty::tag::TagExt; + /// use lofty::TextEncoding; /// use std::borrow::Cow; /// /// const MOOD_FRAME_ID: FrameId<'static> = FrameId::Valid(Cow::Borrowed("TMOO")); diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 86cd23561..551696ba5 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -128,7 +128,7 @@ impl AIFFTextChunks { /// /// ```rust /// use lofty::iff::aiff::AIFFTextChunks; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let aiff_tag = AIFFTextChunks::new(); /// assert!(aiff_tag.is_empty()); diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index c3ac45891..76e53cbd7 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -59,7 +59,7 @@ impl RIFFInfoList { /// /// ```rust /// use lofty::iff::wav::RIFFInfoList; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let riff_info_tag = RIFFInfoList::new(); /// assert!(riff_info_tag.is_empty()); diff --git a/src/lib.rs b/src/lib.rs index 48d8170a9..2795b4f92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ //! use lofty::config::ParseOptions; //! use lofty::file::AudioFile; //! use lofty::mpeg::MpegFile; -//! use lofty::TagType; +//! use lofty::tag::TagType; //! use std::fs::File; //! //! # let path = "tests/files/assets/minimal/full_test.mp3"; diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 08266e01e..13d5029cb 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -91,7 +91,7 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::Ilst; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let ilst_tag = Ilst::new(); /// assert!(ilst_tag.is_empty()); @@ -249,7 +249,8 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::Ilst; - /// use lofty::{MimeType, Picture, PictureType, TagExt}; + /// use lofty::tag::TagExt; + /// use lofty::{MimeType, Picture, PictureType}; /// /// let mut ilst = Ilst::new(); /// @@ -292,7 +293,8 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::Ilst; - /// use lofty::{MimeType, Picture, PictureType, TagExt}; + /// use lofty::tag::TagExt; + /// use lofty::{MimeType, Picture, PictureType}; /// /// let mut ilst = Ilst::new(); /// diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index 97db0a3e5..c40c3ee3a 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -78,7 +78,7 @@ impl VorbisComments { /// /// ```rust /// use lofty::ogg::VorbisComments; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let vorbis_comments_tag = VorbisComments::new(); /// assert!(vorbis_comments_tag.is_empty()); @@ -143,7 +143,7 @@ impl VorbisComments { /// /// ```rust /// use lofty::ogg::VorbisComments; - /// use lofty::TagExt; + /// use lofty::tag::TagExt; /// /// let mut vorbis_comments = VorbisComments::default(); /// diff --git a/src/tag/mod.rs b/src/tag/mod.rs index 539dba28d..f1bad8b4a 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -64,7 +64,8 @@ macro_rules! impl_accessor { /// Accessing common items /// /// ```rust -/// use lofty::{Accessor, Tag, TagType}; +/// use lofty::tag::{Tag, TagType}; +/// use lofty::Accessor; /// /// let tag = Tag::new(TagType::Id3v2); /// @@ -79,7 +80,7 @@ macro_rules! impl_accessor { /// Getting an item of a known type /// /// ```rust -/// use lofty::{ItemKey, Tag, TagType}; +/// use lofty::tag::{ItemKey, Tag, TagType}; /// /// let tag = Tag::new(TagType::Id3v2); /// @@ -94,7 +95,7 @@ macro_rules! impl_accessor { /// /// ```rust /// use lofty::id3::v2::Id3v2Tag; -/// use lofty::{Tag, TagType}; +/// use lofty::tag::{Tag, TagType}; /// /// // Converting between formats is as simple as an `into` call. /// // However, such conversions can potentially be *very* lossy. @@ -458,7 +459,8 @@ impl Tag { /// # Examples /// /// ```rust - /// use lofty::{Picture, Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; + /// use lofty::Picture; /// # use lofty::{PictureType, MimeType}; /// /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); @@ -500,7 +502,8 @@ impl Tag { /// # Examples /// /// ```rust - /// use lofty::{Picture, Tag, TagType}; + /// use lofty::tag::{Tag, TagType}; + /// use lofty::Picture; /// # use lofty::{PictureType, MimeType}; /// /// # let picture = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); diff --git a/src/tag/tagext.rs b/src/tag/tagext.rs index 46fb95718..cf58d2c41 100644 --- a/src/tag/tagext.rs +++ b/src/tag/tagext.rs @@ -26,7 +26,8 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::{Accessor, ItemKey, Tag, TagExt}; + /// use lofty::tag::{ItemKey, Tag, TagExt}; + /// use lofty::Accessor; /// # let tag_type = lofty::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); @@ -42,7 +43,8 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::{Accessor, ItemKey, Tag, TagExt}; + /// use lofty::tag::{ItemKey, Tag, TagExt}; + /// use lofty::Accessor; /// # let tag_type = lofty::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); @@ -58,8 +60,9 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::{Accessor, Tag, TagExt}; - /// # let tag_type = lofty::TagType::Id3v2; + /// use lofty::tag::{Tag, TagExt}; + /// use lofty::Accessor; + /// # let tag_type = lofty::tag::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); /// assert!(tag.is_empty()); diff --git a/src/traits.rs b/src/traits.rs index 0e3c0ba81..9f53500bd 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -128,13 +128,14 @@ use crate::tag::Tag; /// # Example /// /// ```rust,no_run +/// use lofty::config::{ParseOptions, WriteOptions}; /// use lofty::mpeg::MpegFile; -/// use lofty::{AudioFile, ItemKey, MergeTag as _, SplitTag as _, WriteOptions}; +/// use lofty::prelude::*; /// /// // Read the tag from a file -/// # fn main() -> lofty::Result<()> { +/// # fn main() -> lofty::error::Result<()> { /// # let mut file = std::fs::OpenOptions::new().write(true).open("/path/to/file.mp3")?; -/// # let parse_options = lofty::ParseOptions::default(); +/// # let parse_options = ParseOptions::default(); /// let mut mpeg_file = ::read_from(&mut file, parse_options)?; /// let mut id3v2 = mpeg_file /// .id3v2_mut() @@ -156,7 +157,7 @@ use crate::tag::Tag; /// mpeg_file.set_id3v2(id3v2); /// mpeg_file.save_to(&mut file, WriteOptions::default())?; /// -/// # Ok::<(), lofty::LoftyError>(()) } +/// # Ok(()) } /// ``` pub trait SplitTag { /// The remainder of the split operation that is not represented From 4eb276090bd510fe56add1d847e8e926d4060069 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:35:02 -0400 Subject: [PATCH 10/22] Accessor: Move to `lofty::tag` --- CHANGELOG.md | 2 +- src/ape/tag/mod.rs | 10 +--- src/id3/v1/tag.rs | 4 +- src/id3/v2/tag.rs | 4 +- src/id3/v2/tag/tests.rs | 8 --- src/iff/aiff/tag.rs | 4 +- src/iff/wav/tag/mod.rs | 4 +- src/lib.rs | 4 +- src/mp4/ilst/mod.rs | 4 +- src/ogg/tag.rs | 4 +- src/resolve.rs | 3 +- src/tag/accessor.rs | 119 +++++++++++++++++++++++++++++++++++++++ src/tag/mod.rs | 4 +- src/tag/tagext.rs | 3 +- src/traits.rs | 120 ---------------------------------------- 15 files changed, 141 insertions(+), 156 deletions(-) create mode 100644 src/tag/accessor.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ffc9c227..ba117a17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ⚠️ Important ⚠️: Moved to `lofty::options` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) - **AudioFile**/**TaggedFileExt**/**TaggedFile**/**BoundTaggedFile**: - ⚠️ Important ⚠️: Moved to `lofty::file` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) -- **Tag**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**: +- **Tag**/**Accessor**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**: - ⚠️ Important ⚠️: Moved to `lofty::tag` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) ### Fixed diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index a49c35323..27bbadae5 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -7,8 +7,8 @@ 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::ItemValueRef; -use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -769,7 +769,6 @@ mod tests { #[test] fn track_number_tag_to_ape() { - use crate::traits::Accessor; let track_number = 1; let mut tag = Tag::new(TagType::Ape); @@ -787,7 +786,6 @@ mod tests { #[test] fn track_total_tag_to_ape() { - use crate::traits::Accessor; let track_total = 2; let mut tag = Tag::new(TagType::Ape); @@ -805,7 +803,6 @@ mod tests { #[test] fn track_number_and_track_total_tag_to_ape() { - use crate::traits::Accessor; let track_number = 1; let track_total = 2; @@ -829,7 +826,6 @@ mod tests { #[test] fn disk_number_tag_to_ape() { - use crate::traits::Accessor; let disk_number = 1; let mut tag = Tag::new(TagType::Ape); @@ -847,7 +843,6 @@ mod tests { #[test] fn disk_total_tag_to_ape() { - use crate::traits::Accessor; let disk_total = 2; let mut tag = Tag::new(TagType::Ape); @@ -865,7 +860,6 @@ mod tests { #[test] fn disk_number_and_disk_total_tag_to_ape() { - use crate::traits::Accessor; let disk_number = 1; let disk_total = 2; diff --git a/src/id3/v1/tag.rs b/src/id3/v1/tag.rs index 1272ac21a..dc795c15b 100644 --- a/src/id3/v1/tag.rs +++ b/src/id3/v1/tag.rs @@ -1,8 +1,8 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::id3::v1::constants::GENRES; -use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 780b7e9ae..67a6e8adf 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -18,8 +18,8 @@ use crate::id3::v2::util::pairs::{ }; use crate::id3::v2::KeyValueFrame; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding}; use std::borrow::Cow; diff --git a/src/id3/v2/tag/tests.rs b/src/id3/v2/tag/tests.rs index 940a7f5df..1cc12422a 100644 --- a/src/id3/v2/tag/tests.rs +++ b/src/id3/v2/tag/tests.rs @@ -438,7 +438,6 @@ fn popm_frame() { #[test] fn multi_value_frame_to_tag() { - use crate::traits::Accessor; let mut tag = Id3v2Tag::default(); tag.set_artist(String::from("foo\0bar\0baz")); @@ -450,7 +449,6 @@ fn multi_value_frame_to_tag() { #[test] fn multi_item_tag_to_id3v2() { - use crate::traits::Accessor; let mut tag = Tag::new(TagType::Id3v2); tag.push_unchecked(TagItem::new( @@ -823,7 +821,6 @@ fn set_disk_total_and_disk() { #[test] fn track_number_tag_to_id3v2() { - use crate::traits::Accessor; let track_number = 1; let mut tag = Tag::new(TagType::Id3v2); @@ -841,7 +838,6 @@ fn track_number_tag_to_id3v2() { #[test] fn track_total_tag_to_id3v2() { - use crate::traits::Accessor; let track_total = 2; let mut tag = Tag::new(TagType::Id3v2); @@ -859,7 +855,6 @@ fn track_total_tag_to_id3v2() { #[test] fn track_number_and_track_total_tag_to_id3v2() { - use crate::traits::Accessor; let track_number = 1; let track_total = 2; @@ -883,7 +878,6 @@ fn track_number_and_track_total_tag_to_id3v2() { #[test] fn disk_number_tag_to_id3v2() { - use crate::traits::Accessor; let disk_number = 1; let mut tag = Tag::new(TagType::Id3v2); @@ -901,7 +895,6 @@ fn disk_number_tag_to_id3v2() { #[test] fn disk_total_tag_to_id3v2() { - use crate::traits::Accessor; let disk_total = 2; let mut tag = Tag::new(TagType::Id3v2); @@ -919,7 +912,6 @@ fn disk_total_tag_to_id3v2() { #[test] fn disk_number_and_disk_total_tag_to_id3v2() { - use crate::traits::Accessor; let disk_number = 1; let disk_total = 2; diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 551696ba5..0cb9356d4 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -2,8 +2,8 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::iff::chunk::Chunks; use crate::macros::err; -use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index 76e53cbd7..e7c6bd65f 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -3,8 +3,8 @@ mod write; use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; -use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; diff --git a/src/lib.rs b/src/lib.rs index 2795b4f92..08d419e68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -194,6 +194,6 @@ pub mod prelude { pub use crate::error::LoftyError; pub use crate::file::{AudioFile, TaggedFileExt}; - pub use crate::tag::{ItemKey, TagExt}; - pub use crate::traits::{Accessor, MergeTag, SplitTag}; + pub use crate::tag::{Accessor, ItemKey, TagExt}; + pub use crate::traits::{MergeTag, SplitTag}; } diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 13d5029cb..d9ce61aa7 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -9,8 +9,8 @@ use crate::config::WriteOptions; use crate::error::LoftyError; use crate::mp4::ilst::atom::AtomDataStorage; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use atom::{AdvisoryRating, Atom, AtomData}; use std::borrow::Cow; diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index c40c3ee3a..3e7a08efc 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -6,8 +6,8 @@ use crate::ogg::picture_storage::OggPictureStorage; use crate::ogg::write::OGGFormat; use crate::picture::{Picture, PictureInformation}; use crate::probe::Probe; -use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; diff --git a/src/resolve.rs b/src/resolve.rs index 321fe62fb..e1231bd60 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -134,8 +134,7 @@ mod tests { use crate::id3::v2::Id3v2Tag; use crate::properties::FileProperties; use crate::resolve::{register_custom_resolver, FileResolver}; - use crate::tag::TagType; - use crate::traits::Accessor; + use crate::tag::{Accessor, TagType}; use std::fs::File; use std::io::{Read, Seek}; diff --git a/src/tag/accessor.rs b/src/tag/accessor.rs new file mode 100644 index 000000000..355c04b7d --- /dev/null +++ b/src/tag/accessor.rs @@ -0,0 +1,119 @@ +use std::borrow::Cow; + +// This defines the `Accessor` trait, used to define unified getters/setters for commonly +// accessed tag values. +// +// Usage: +// +// accessor_trait! { +// [field_name] +// } +// +// * `field_name` is the name of the method to access the field. If a name consists of multiple segments, +// such as `track_number`, they should be separated by spaces like so: [track number]. +// +// * `type` is the return type for `Accessor::field_name`. By default, this type will also be used +// in the setter. +// +// An owned type can also be specified for the setter: +// +// accessor_trait! { +// field_name +// } +macro_rules! accessor_trait { + ($([$($name:tt)+] < $($ty:ty),+ >),+ $(,)?) => { + /// Provides accessors for common items + /// + /// This attempts to only provide methods for items that all tags have in common, + /// but there may be exceptions. + pub trait Accessor { + $( + accessor_trait! { @GETTER [$($name)+] $($ty),+ } + + accessor_trait! { @SETTER [$($name)+] $($ty),+ } + + accessor_trait! { @REMOVE [$($name)+] $($ty),+ } + )+ + } + }; + (@GETTER [$($name:tt)+] $ty:ty $(, $_ty:tt)?) => { + accessor_trait! { @GET_METHOD [$($name)+] Option<$ty> } + }; + (@SETTER [$($name:tt)+] $_ty:ty, $owned_ty:tt) => { + accessor_trait! { @SETTER [$($name)+] $owned_ty } + }; + (@SETTER [$($name:tt)+] $ty:ty) => { + accessor_trait! { @SET_METHOD [$($name)+] $ty } + }; + (@REMOVE [$($name:tt)+] $_ty:ty, $owned_ty:tt) => { + accessor_trait! { @REMOVE [$($name)+] $owned_ty } + }; + (@REMOVE [$($name:tt)+] $ty:ty) => { + accessor_trait! { @REMOVE_METHOD [$($name)+], $ty } + }; + (@GET_METHOD [$name:tt $($other:tt)*] Option<$ret_ty:ty>) => { + paste::paste! { + #[doc = "Returns the " $name $(" " $other)*] + /// # Example + /// + /// ```rust + /// use lofty::{Tag, Accessor}; + /// + /// # let tag_type = lofty::TagType::Id3v2; + /// let mut tag = Tag::new(tag_type); + #[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"] + /// ``` + fn [< + $name $(_ $other)* + >] (&self) -> Option<$ret_ty> { None } + } + }; + (@SET_METHOD [$name:tt $($other:tt)*] $owned_ty:ty) => { + paste::paste! { + #[doc = "Sets the " $name $(" " $other)*] + /// # Example + /// + /// ```rust,ignore + /// use lofty::{Tag, Accessor}; + /// + /// let mut tag = Tag::new(tag_type); + #[doc = "tag.set_" $name $(_ $other)* "(value);"] + /// + #[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"] + /// ``` + fn [< + set_ $name $(_ $other)* + >] (&mut self , _value: $owned_ty) {} + } + }; + (@REMOVE_METHOD [$name:tt $($other:tt)*], $ty:ty) => { + paste::paste! { + #[doc = "Removes the " $name $(" " $other)*] + /// # Example + /// + /// ```rust,ignore + /// use lofty::{Tag, Accessor}; + /// + /// let mut tag = Tag::new(tag_type); + #[doc = "tag.set_" $name $(_ $other)* "(value);"] + /// + #[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"] + /// + #[doc = "tag.remove_" $name $(_ $other)* "();"] + /// + #[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"] + /// ``` + fn [< + remove_ $name $(_ $other)* + >] (&mut self) {} + } + }; +} + +accessor_trait! { + [artist], String>, [title ], String>, + [album ], String>, [genre ], String>, + [track ], [track total], + [disk ], [disk total ], + [year ], [comment ], String>, +} diff --git a/src/tag/mod.rs b/src/tag/mod.rs index f1bad8b4a..e26fe22a4 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -1,5 +1,6 @@ //! Utilities for generic tag handling +mod accessor; pub(crate) mod item; mod tag_type; mod tagext; @@ -10,7 +11,7 @@ use crate::error::{LoftyError, Result}; use crate::macros::err; use crate::picture::{Picture, PictureType}; use crate::probe::Probe; -use crate::traits::{Accessor, MergeTag, SplitTag}; +use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -18,6 +19,7 @@ use std::io::Write; use std::path::Path; // Exports +pub use accessor::Accessor; pub use item::{ItemKey, ItemValue, TagItem}; pub use tag_type::TagType; pub use tagext::TagExt; diff --git a/src/tag/tagext.rs b/src/tag/tagext.rs index cf58d2c41..614f6919e 100644 --- a/src/tag/tagext.rs +++ b/src/tag/tagext.rs @@ -1,6 +1,5 @@ use crate::config::WriteOptions; -use crate::tag::Tag; -use crate::traits::Accessor; +use crate::tag::{Accessor, Tag}; use std::fs::File; use std::path::Path; diff --git a/src/traits.rs b/src/traits.rs index 9f53500bd..7d3c95d43 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,123 +1,3 @@ -use std::borrow::Cow; - -// This defines the `Accessor` trait, used to define unified getters/setters for commonly -// accessed tag values. -// -// Usage: -// -// accessor_trait! { -// [field_name] -// } -// -// * `field_name` is the name of the method to access the field. If a name consists of multiple segments, -// such as `track_number`, they should be separated by spaces like so: [track number]. -// -// * `type` is the return type for `Accessor::field_name`. By default, this type will also be used -// in the setter. -// -// An owned type can also be specified for the setter: -// -// accessor_trait! { -// field_name -// } -macro_rules! accessor_trait { - ($([$($name:tt)+] < $($ty:ty),+ >),+ $(,)?) => { - /// Provides accessors for common items - /// - /// This attempts to only provide methods for items that all tags have in common, - /// but there may be exceptions. - pub trait Accessor { - $( - accessor_trait! { @GETTER [$($name)+] $($ty),+ } - - accessor_trait! { @SETTER [$($name)+] $($ty),+ } - - accessor_trait! { @REMOVE [$($name)+] $($ty),+ } - )+ - } - }; - (@GETTER [$($name:tt)+] $ty:ty $(, $_ty:tt)?) => { - accessor_trait! { @GET_METHOD [$($name)+] Option<$ty> } - }; - (@SETTER [$($name:tt)+] $_ty:ty, $owned_ty:tt) => { - accessor_trait! { @SETTER [$($name)+] $owned_ty } - }; - (@SETTER [$($name:tt)+] $ty:ty) => { - accessor_trait! { @SET_METHOD [$($name)+] $ty } - }; - (@REMOVE [$($name:tt)+] $_ty:ty, $owned_ty:tt) => { - accessor_trait! { @REMOVE [$($name)+] $owned_ty } - }; - (@REMOVE [$($name:tt)+] $ty:ty) => { - accessor_trait! { @REMOVE_METHOD [$($name)+], $ty } - }; - (@GET_METHOD [$name:tt $($other:tt)*] Option<$ret_ty:ty>) => { - paste::paste! { - #[doc = "Returns the " $name $(" " $other)*] - /// # Example - /// - /// ```rust - /// use lofty::{Tag, Accessor}; - /// - /// # let tag_type = lofty::TagType::Id3v2; - /// let mut tag = Tag::new(tag_type); - #[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"] - /// ``` - fn [< - $name $(_ $other)* - >] (&self) -> Option<$ret_ty> { None } - } - }; - (@SET_METHOD [$name:tt $($other:tt)*] $owned_ty:ty) => { - paste::paste! { - #[doc = "Sets the " $name $(" " $other)*] - /// # Example - /// - /// ```rust,ignore - /// use lofty::{Tag, Accessor}; - /// - /// let mut tag = Tag::new(tag_type); - #[doc = "tag.set_" $name $(_ $other)* "(value);"] - /// - #[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"] - /// ``` - fn [< - set_ $name $(_ $other)* - >] (&mut self , _value: $owned_ty) {} - } - }; - (@REMOVE_METHOD [$name:tt $($other:tt)*], $ty:ty) => { - paste::paste! { - #[doc = "Removes the " $name $(" " $other)*] - /// # Example - /// - /// ```rust,ignore - /// use lofty::{Tag, Accessor}; - /// - /// let mut tag = Tag::new(tag_type); - #[doc = "tag.set_" $name $(_ $other)* "(value);"] - /// - #[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"] - /// - #[doc = "tag.remove_" $name $(_ $other)* "();"] - /// - #[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"] - /// ``` - fn [< - remove_ $name $(_ $other)* - >] (&mut self) {} - } - }; -} - -accessor_trait! { - [artist], String>, [title ], String>, - [album ], String>, [genre ], String>, - [track ], [track total], - [disk ], [disk total ], - [year ], [comment ], String>, -} - use crate::tag::Tag; /// Split (and merge) tags. From b15475081e19f2187fdae7ed99855c14a573e83e Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:37:28 -0400 Subject: [PATCH 11/22] doc: Fix even more example imports --- src/ape/tag/mod.rs | 4 ++-- src/id3/v2/tag.rs | 6 +++--- src/mp4/ilst/mod.rs | 6 +++--- src/tag/accessor.rs | 8 ++++---- src/tag/mod.rs | 3 +-- src/tag/tagext.rs | 13 +++++-------- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index 27bbadae5..a525eeacb 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -107,7 +107,7 @@ impl ApeTag { /// /// ```rust /// use lofty::ape::ApeTag; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// /// let mut ape_tag = ApeTag::new(); /// ape_tag.set_title(String::from("Foo title")); @@ -138,7 +138,7 @@ impl ApeTag { /// /// ```rust /// use lofty::ape::ApeTag; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// /// let mut ape_tag = ApeTag::new(); /// ape_tag.set_title(String::from("Foo title")); diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 67a6e8adf..7ba90a52b 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -199,7 +199,7 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::{FrameId, Id3v2Tag}; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// use std::borrow::Cow; /// /// const TITLE_ID: FrameId<'_> = FrameId::Valid(Cow::Borrowed("TIT2")); @@ -240,7 +240,7 @@ impl Id3v2Tag { /// /// ```rust /// use lofty::id3::v2::{FrameId, Id3v2Tag}; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// use std::borrow::Cow; /// /// const TITLE_ID: FrameId<'_> = FrameId::Valid(Cow::Borrowed("TIT2")); @@ -418,7 +418,7 @@ impl Id3v2Tag { /// /// const MOOD_FRAME_ID: FrameId<'static> = FrameId::Valid(Cow::Borrowed("TMOO")); /// - /// # fn main() -> lofty::Result<()> { + /// # fn main() -> lofty::error::Result<()> { /// let mut tag = Id3v2Tag::new(); /// assert!(tag.is_empty()); /// diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index d9ce61aa7..9cd668e07 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -106,7 +106,7 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::{AtomIdent, Ilst}; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// /// let mut ilst = Ilst::new(); /// ilst.set_title(String::from("Foo title")); @@ -174,7 +174,7 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::{Atom, AtomData, AtomIdent, Ilst}; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// /// const TITLE_IDENTIFIER: AtomIdent = AtomIdent::Fourcc(*b"\xa9nam"); /// @@ -201,7 +201,7 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::{Atom, AtomData, AtomIdent, Ilst}; - /// use lofty::Accessor; + /// use lofty::tag::Accessor; /// /// const TITLE_IDENTIFIER: AtomIdent = AtomIdent::Fourcc(*b"\xa9nam"); /// diff --git a/src/tag/accessor.rs b/src/tag/accessor.rs index 355c04b7d..fc32657ba 100644 --- a/src/tag/accessor.rs +++ b/src/tag/accessor.rs @@ -57,9 +57,9 @@ macro_rules! accessor_trait { /// # Example /// /// ```rust - /// use lofty::{Tag, Accessor}; + /// use lofty::tag::{Tag, Accessor}; /// - /// # let tag_type = lofty::TagType::Id3v2; + /// # let tag_type = lofty::tag::TagType::Id3v2; /// let mut tag = Tag::new(tag_type); #[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"] /// ``` @@ -74,7 +74,7 @@ macro_rules! accessor_trait { /// # Example /// /// ```rust,ignore - /// use lofty::{Tag, Accessor}; + /// use lofty::tag::{Tag, Accessor}; /// /// let mut tag = Tag::new(tag_type); #[doc = "tag.set_" $name $(_ $other)* "(value);"] @@ -92,7 +92,7 @@ macro_rules! accessor_trait { /// # Example /// /// ```rust,ignore - /// use lofty::{Tag, Accessor}; + /// use lofty::tag::{Tag, Accessor}; /// /// let mut tag = Tag::new(tag_type); #[doc = "tag.set_" $name $(_ $other)* "(value);"] diff --git a/src/tag/mod.rs b/src/tag/mod.rs index e26fe22a4..af9fa4043 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -66,8 +66,7 @@ macro_rules! impl_accessor { /// Accessing common items /// /// ```rust -/// use lofty::tag::{Tag, TagType}; -/// use lofty::Accessor; +/// use lofty::tag::{Accessor, Tag, TagType}; /// /// let tag = Tag::new(TagType::Id3v2); /// diff --git a/src/tag/tagext.rs b/src/tag/tagext.rs index 614f6919e..0ebb55c04 100644 --- a/src/tag/tagext.rs +++ b/src/tag/tagext.rs @@ -25,9 +25,8 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::tag::{ItemKey, Tag, TagExt}; - /// use lofty::Accessor; - /// # let tag_type = lofty::TagType::Id3v2; + /// use lofty::tag::{Accessor, ItemKey, Tag, TagExt}; + /// # let tag_type = lofty::tag::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); /// assert_eq!(tag.len(), 0); @@ -42,9 +41,8 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::tag::{ItemKey, Tag, TagExt}; - /// use lofty::Accessor; - /// # let tag_type = lofty::TagType::Id3v2; + /// use lofty::tag::{Accessor, ItemKey, Tag, TagExt}; + /// # let tag_type = lofty::tag::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); /// assert!(tag.is_empty()); @@ -59,8 +57,7 @@ pub trait TagExt: Accessor + Into + Sized { /// # Example /// /// ```rust - /// use lofty::tag::{Tag, TagExt}; - /// use lofty::Accessor; + /// use lofty::tag::{Accessor, Tag, TagExt}; /// # let tag_type = lofty::tag::TagType::Id3v2; /// /// let mut tag = Tag::new(tag_type); From f145dc92e56c78b650f690b01460aeb788c5e48a Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:43:51 -0400 Subject: [PATCH 12/22] doc: Fix some item links --- src/config/parse_options.rs | 2 +- src/error.rs | 2 +- src/file/audio_file.rs | 6 +++--- src/id3/v2/frame/id.rs | 2 +- src/lib.rs | 2 +- src/properties/mod.rs | 2 +- src/tag/item.rs | 2 +- src/tag/mod.rs | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/config/parse_options.rs b/src/config/parse_options.rs index 12a1857ac..3c2ab4c9a 100644 --- a/src/config/parse_options.rs +++ b/src/config/parse_options.rs @@ -102,7 +102,7 @@ impl ParseOptions { /// The parsing strictness mode /// -/// This can be set with [`Probe::options`]. +/// This can be set with [`Probe::options`](crate::Probe). /// /// # Examples /// diff --git a/src/error.rs b/src/error.rs index a34e95654..9a6275bf0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -94,7 +94,7 @@ pub enum Id3v2ErrorKind { UnsupportedFrameId(ItemKey), /// Arises when a frame doesn't have enough data BadFrameLength, - /// Arises when a frame with no content is parsed with [ParsingMode::Strict](crate::probe::ParsingMode::Strict) + /// Arises when a frame with no content is parsed with [ParsingMode::Strict](crate::config::ParsingMode::Strict) EmptyFrame(FrameId<'static>), /// Arises when reading/writing a compressed or encrypted frame with no data length indicator MissingDataLengthIndicator, diff --git a/src/file/audio_file.rs b/src/file/audio_file.rs index ba403f37a..5b1b4bee7 100644 --- a/src/file/audio_file.rs +++ b/src/file/audio_file.rs @@ -11,14 +11,14 @@ use std::path::Path; pub trait AudioFile: Into { /// The struct the file uses for audio properties /// - /// Not all formats can use [`FileProperties`] since they may contain additional information + /// Not all formats can use [`FileProperties`](crate::properties::FileProperties) since they may contain additional information type Properties; /// Read a file from a reader /// /// # Errors /// - /// Errors depend on the file and tags being read. See [`LoftyError`](crate::LoftyError) + /// Errors depend on the file and tags being read. See [`LoftyError`](crate::error::LoftyError) fn read_from(reader: &mut R, parse_options: ParseOptions) -> Result where R: Read + Seek, @@ -58,7 +58,7 @@ pub trait AudioFile: Into { /// /// # Errors /// - /// See [`Tag::save_to`], however this is applicable to every tag in the file. + /// See [`TagExt::save_to`](crate::tag::TagExt::save_to), however this is applicable to every tag in the file. /// /// # Examples /// diff --git a/src/id3/v2/frame/id.rs b/src/id3/v2/frame/id.rs index 419e32f68..6fe90faf3 100644 --- a/src/id3/v2/frame/id.rs +++ b/src/id3/v2/frame/id.rs @@ -15,7 +15,7 @@ pub enum FrameId<'a> { /// /// This **will not** be written. It is up to the user to upgrade and store the key as [`Id3v2Frame::Valid`](Self::Valid). /// - /// The entire frame is stored as [`ItemValue::Binary`](crate::ItemValue::Binary). + /// The entire frame is stored as [`ItemValue::Binary`](crate::tag::ItemValue::Binary). Outdated(Cow<'a, str>), } diff --git a/src/lib.rs b/src/lib.rs index 08d419e68..f88afc1c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ //! //! ## Reading a generic file //! -//! It isn't always convenient to [use concrete file types](#using-concrete-file-types), which is where [`TaggedFile`] +//! It isn't always convenient to [use concrete file types](#using-concrete-file-types), which is where [`TaggedFile`](file::TaggedFile) //! comes in. //! //! ### Using a path diff --git a/src/properties/mod.rs b/src/properties/mod.rs index a6d5d12a7..84cb263a3 100644 --- a/src/properties/mod.rs +++ b/src/properties/mod.rs @@ -1,7 +1,7 @@ //! Generic audio properties //! //! Many audio formats have their own custom properties, but there are some properties that are -//! common to all audio formats. When using [`TaggedFile`](crate::TaggedFile), any custom properties +//! common to all audio formats. When using [`TaggedFile`](crate::file::TaggedFile), any custom properties //! will simply be converted to [`FileProperties`]. mod channel_mask; diff --git a/src/tag/item.rs b/src/tag/item.rs index 7653a692e..2f6beec02 100644 --- a/src/tag/item.rs +++ b/src/tag/item.rs @@ -799,7 +799,7 @@ impl TagItem { /// /// * This will check for validity based on the [`TagType`]. /// * If the [`ItemKey`] does not map to a key in the target format, `None` will be returned. - /// * This is unnecessary if you plan on using [`Tag::insert_item`](crate::Tag::insert), as it does validity checks itself. + /// * This is unnecessary if you plan on using [`Tag::insert`](crate::tag::Tag::insert), as it does validity checks itself. pub fn new_checked( tag_type: TagType, item_key: ItemKey, diff --git a/src/tag/mod.rs b/src/tag/mod.rs index af9fa4043..f01ca0bab 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -542,8 +542,8 @@ impl TagExt for Tag { /// /// # Errors /// - /// * A [`FileType`](crate::FileType) couldn't be determined from the File - /// * Attempting to write a tag to a format that does not support it. See [`FileType::supports_tag_type`](crate::FileType::supports_tag_type) + /// * A [`FileType`](crate::file::FileType) couldn't be determined from the File + /// * Attempting to write a tag to a format that does not support it. See [`FileType::supports_tag_type`](crate::file::FileType::supports_tag_type) fn save_to( &self, file: &mut File, From 766b5ce34a7587bfbecf4e09494c8a386ca913c3 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:46:16 -0400 Subject: [PATCH 13/22] traits: Move {Split,Merge}Tag to `lofty::tag` --- src/ape/tag/mod.rs | 5 ++- src/id3/v1/tag.rs | 3 +- src/id3/v2/tag.rs | 5 ++- src/iff/aiff/tag.rs | 3 +- src/iff/wav/tag/mod.rs | 5 ++- src/lib.rs | 3 +- src/mp4/ilst/mod.rs | 5 ++- src/ogg/tag.rs | 5 ++- src/tag/mod.rs | 7 ++-- src/tag/split_merge_tag.rs | 68 ++++++++++++++++++++++++++++++ src/tag/{tagext.rs => tag_ext.rs} | 0 src/traits.rs | 69 ------------------------------- 12 files changed, 90 insertions(+), 88 deletions(-) create mode 100644 src/tag/split_merge_tag.rs rename src/tag/{tagext.rs => tag_ext.rs} (100%) diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index a525eeacb..6be290c5e 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -7,8 +7,9 @@ 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::ItemValueRef; -use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{ + try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType, +}; use std::borrow::Cow; use std::fs::File; diff --git a/src/id3/v1/tag.rs b/src/id3/v1/tag.rs index dc795c15b..f49219da3 100644 --- a/src/id3/v1/tag.rs +++ b/src/id3/v1/tag.rs @@ -1,8 +1,7 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::id3::v1::constants::GENRES; -use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType}; use std::borrow::Cow; use std::fs::File; diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 7ba90a52b..a62962a27 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -18,8 +18,9 @@ use crate::id3::v2::util::pairs::{ }; use crate::id3::v2::KeyValueFrame; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{ + try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType, +}; use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding}; use std::borrow::Cow; diff --git a/src/iff/aiff/tag.rs b/src/iff/aiff/tag.rs index 0cb9356d4..186f03fa4 100644 --- a/src/iff/aiff/tag.rs +++ b/src/iff/aiff/tag.rs @@ -2,8 +2,7 @@ use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; use crate::iff::chunk::Chunks; use crate::macros::err; -use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType}; use std::borrow::Cow; use std::fs::File; diff --git a/src/iff/wav/tag/mod.rs b/src/iff/wav/tag/mod.rs index e7c6bd65f..fd5c0f9e3 100644 --- a/src/iff/wav/tag/mod.rs +++ b/src/iff/wav/tag/mod.rs @@ -3,8 +3,9 @@ mod write; use crate::config::WriteOptions; use crate::error::{LoftyError, Result}; -use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{ + try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType, +}; use std::borrow::Cow; use std::fs::File; diff --git a/src/lib.rs b/src/lib.rs index f88afc1c0..8c0554505 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -194,6 +194,5 @@ pub mod prelude { pub use crate::error::LoftyError; pub use crate::file::{AudioFile, TaggedFileExt}; - pub use crate::tag::{Accessor, ItemKey, TagExt}; - pub use crate::traits::{MergeTag, SplitTag}; + pub use crate::tag::{Accessor, ItemKey, MergeTag, SplitTag, TagExt}; } diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 9cd668e07..335728b59 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -9,8 +9,9 @@ use crate::config::WriteOptions; use crate::error::LoftyError; use crate::mp4::ilst::atom::AtomDataStorage; use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE}; -use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{ + try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType, +}; use atom::{AdvisoryRating, Atom, AtomData}; use std::borrow::Cow; diff --git a/src/ogg/tag.rs b/src/ogg/tag.rs index 3e7a08efc..f4e2ce069 100644 --- a/src/ogg/tag.rs +++ b/src/ogg/tag.rs @@ -6,8 +6,9 @@ use crate::ogg::picture_storage::OggPictureStorage; use crate::ogg::write::OGGFormat; use crate::picture::{Picture, PictureInformation}; use crate::probe::Probe; -use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType}; -use crate::traits::{MergeTag, SplitTag}; +use crate::tag::{ + try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType, +}; use std::borrow::Cow; use std::fs::File; diff --git a/src/tag/mod.rs b/src/tag/mod.rs index f01ca0bab..a34d68516 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -2,8 +2,9 @@ mod accessor; pub(crate) mod item; +mod split_merge_tag; +mod tag_ext; mod tag_type; -mod tagext; pub(crate) mod utils; use crate::config::WriteOptions; @@ -11,7 +12,6 @@ use crate::error::{LoftyError, Result}; use crate::macros::err; use crate::picture::{Picture, PictureType}; use crate::probe::Probe; -use crate::traits::{MergeTag, SplitTag}; use std::borrow::Cow; use std::fs::File; @@ -21,8 +21,9 @@ use std::path::Path; // Exports pub use accessor::Accessor; pub use item::{ItemKey, ItemValue, TagItem}; +pub use split_merge_tag::{MergeTag, SplitTag}; +pub use tag_ext::TagExt; pub use tag_type::TagType; -pub use tagext::TagExt; macro_rules! impl_accessor { ($($item_key:ident => $name:tt),+) => { diff --git a/src/tag/split_merge_tag.rs b/src/tag/split_merge_tag.rs new file mode 100644 index 000000000..80804a66d --- /dev/null +++ b/src/tag/split_merge_tag.rs @@ -0,0 +1,68 @@ +use super::Tag; + +/// Split (and merge) tags. +/// +/// Useful and required for implementing lossless read/modify/write round trips. +/// Its counterpart `MergeTag` is used for recombining the results later. +/// +/// # Example +/// +/// ```rust,no_run +/// use lofty::config::{ParseOptions, WriteOptions}; +/// use lofty::mpeg::MpegFile; +/// use lofty::prelude::*; +/// +/// // Read the tag from a file +/// # fn main() -> lofty::error::Result<()> { +/// # let mut file = std::fs::OpenOptions::new().write(true).open("/path/to/file.mp3")?; +/// # let parse_options = ParseOptions::default(); +/// let mut mpeg_file = ::read_from(&mut file, parse_options)?; +/// let mut id3v2 = mpeg_file +/// .id3v2_mut() +/// .map(std::mem::take) +/// .unwrap_or_default(); +/// +/// // Split: ID3v2 -> [`lofty::Tag`] +/// let (mut remainder, mut tag) = id3v2.split_tag(); +/// +/// // Modify the metadata in the generic [`lofty::Tag`], independent +/// // of the underlying tag and file format. +/// tag.insert_text(ItemKey::TrackTitle, "Track Title".to_owned()); +/// tag.remove_key(&ItemKey::Composer); +/// +/// // ID3v2 <- [`lofty::Tag`] +/// let id3v2 = remainder.merge_tag(tag); +/// +/// // Write the changes back into the file +/// mpeg_file.set_id3v2(id3v2); +/// mpeg_file.save_to(&mut file, WriteOptions::default())?; +/// +/// # Ok(()) } +/// ``` +pub trait SplitTag { + /// The remainder of the split operation that is not represented + /// in the resulting `Tag`. + type Remainder: MergeTag; + + /// Extract and split generic contents into a [`Tag`]. + /// + /// Returns the remaining content that cannot be represented in the + /// resulting `Tag` in `Self::Remainder`. This is useful if the + /// modified [`Tag`] is merged later using [`MergeTag::merge_tag`]. + fn split_tag(self) -> (Self::Remainder, Tag); +} + +/// The counterpart of [`SplitTag`]. +pub trait MergeTag { + /// The resulting tag. + type Merged: SplitTag; + + /// Merge a generic [`Tag`] back into the remainder of [`SplitTag::split_tag`]. + /// + /// Restores the original representation merged with the contents of + /// `tag` for further processing, e.g. writing back into a file. + /// + /// Multi-valued items in `tag` with identical keys might get lost + /// depending on the support for multi-valued fields in `self`. + fn merge_tag(self, tag: Tag) -> Self::Merged; +} diff --git a/src/tag/tagext.rs b/src/tag/tag_ext.rs similarity index 100% rename from src/tag/tagext.rs rename to src/tag/tag_ext.rs diff --git a/src/traits.rs b/src/traits.rs index 7d3c95d43..f344a64cc 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,72 +1,3 @@ -use crate::tag::Tag; - -/// Split (and merge) tags. -/// -/// Useful and required for implementing lossless read/modify/write round trips. -/// Its counterpart `MergeTag` is used for recombining the results later. -/// -/// # Example -/// -/// ```rust,no_run -/// use lofty::config::{ParseOptions, WriteOptions}; -/// use lofty::mpeg::MpegFile; -/// use lofty::prelude::*; -/// -/// // Read the tag from a file -/// # fn main() -> lofty::error::Result<()> { -/// # let mut file = std::fs::OpenOptions::new().write(true).open("/path/to/file.mp3")?; -/// # let parse_options = ParseOptions::default(); -/// let mut mpeg_file = ::read_from(&mut file, parse_options)?; -/// let mut id3v2 = mpeg_file -/// .id3v2_mut() -/// .map(std::mem::take) -/// .unwrap_or_default(); -/// -/// // Split: ID3v2 -> [`lofty::Tag`] -/// let (mut remainder, mut tag) = id3v2.split_tag(); -/// -/// // Modify the metadata in the generic [`lofty::Tag`], independent -/// // of the underlying tag and file format. -/// tag.insert_text(ItemKey::TrackTitle, "Track Title".to_owned()); -/// tag.remove_key(&ItemKey::Composer); -/// -/// // ID3v2 <- [`lofty::Tag`] -/// let id3v2 = remainder.merge_tag(tag); -/// -/// // Write the changes back into the file -/// mpeg_file.set_id3v2(id3v2); -/// mpeg_file.save_to(&mut file, WriteOptions::default())?; -/// -/// # Ok(()) } -/// ``` -pub trait SplitTag { - /// The remainder of the split operation that is not represented - /// in the resulting `Tag`. - type Remainder: MergeTag; - - /// Extract and split generic contents into a [`Tag`]. - /// - /// Returns the remaining content that cannot be represented in the - /// resulting `Tag` in `Self::Remainder`. This is useful if the - /// modified [`Tag`] is merged later using [`MergeTag::merge_tag`]. - fn split_tag(self) -> (Self::Remainder, Tag); -} - -/// The counterpart of [`SplitTag`]. -pub trait MergeTag { - /// The resulting tag. - type Merged: SplitTag; - - /// Merge a generic [`Tag`] back into the remainder of [`SplitTag::split_tag`]. - /// - /// Restores the original representation merged with the contents of - /// `tag` for further processing, e.g. writing back into a file. - /// - /// Multi-valued items in `tag` with identical keys might get lost - /// depending on the support for multi-valued fields in `self`. - fn merge_tag(self, tag: Tag) -> Self::Merged; -} - // TODO: https://github.com/rust-lang/rust/issues/59359 pub(crate) trait SeekStreamLen: std::io::Seek { fn stream_len(&mut self) -> crate::error::Result { From d7f91d9dfaf337e66081dba9ceca09a3347511af Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:48:01 -0400 Subject: [PATCH 14/22] changelog: Make list of items nicer --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba117a17c..95adf16d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ⚠️ Important ⚠️: Moved to `lofty::options` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) - **AudioFile**/**TaggedFileExt**/**TaggedFile**/**BoundTaggedFile**: - ⚠️ Important ⚠️: Moved to `lofty::file` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) -- **Tag**/**Accessor**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**: - - ⚠️ Important ⚠️: Moved to `lofty::tag` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)) +- **Tag**: + - ⚠️ Important ⚠️- The following items have been moved to `lofty::tag` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)): + - `Tag` + - `Accessor` + - `TagType` + - `TagItem` + - `ItemKey` + - `ItemValue` ### Fixed - **Vorbis**: Fix panic when reading properties of zero-length files ([issue](https://github.com/Serial-ATA/lofty-rs/issues/342)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/365)) From 63d7c8c2b907952a38dc3d7573bf1d8c284b386b Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:49:33 -0400 Subject: [PATCH 15/22] math: Move module to `lofty::util::math` --- src/iff/wav/properties.rs | 2 +- src/lib.rs | 1 - src/mp4/properties.rs | 2 +- src/mpeg/properties.rs | 2 +- src/ogg/opus/properties.rs | 2 +- src/ogg/speex/properties.rs | 2 +- src/ogg/vorbis/properties.rs | 2 +- src/{ => util}/math.rs | 0 src/util/mod.rs | 1 + 9 files changed, 7 insertions(+), 7 deletions(-) rename src/{ => util}/math.rs (100%) diff --git a/src/iff/wav/properties.rs b/src/iff/wav/properties.rs index 2fb9e347c..79a2ad234 100644 --- a/src/iff/wav/properties.rs +++ b/src/iff/wav/properties.rs @@ -1,7 +1,7 @@ use crate::error::Result; use crate::macros::decode_err; -use crate::math::RoundedDivision; use crate::properties::{ChannelMask, FileProperties}; +use crate::util::math::RoundedDivision; use std::time::Duration; diff --git a/src/lib.rs b/src/lib.rs index 8c0554505..831d7dfaf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,7 +154,6 @@ pub mod config; pub mod error; pub mod file; pub(crate) mod macros; -mod math; pub(crate) mod picture; mod probe; pub mod properties; diff --git a/src/mp4/properties.rs b/src/mp4/properties.rs index 7d458d151..6ebac0ea9 100644 --- a/src/mp4/properties.rs +++ b/src/mp4/properties.rs @@ -3,8 +3,8 @@ use super::read::{nested_atom, skip_unneeded, AtomReader}; use crate::config::ParsingMode; use crate::error::{LoftyError, Result}; use crate::macros::{decode_err, err, try_vec}; -use crate::math::RoundedDivision; use crate::properties::FileProperties; +use crate::util::math::RoundedDivision; use std::io::{Cursor, Read, Seek, SeekFrom}; use std::time::Duration; diff --git a/src/mpeg/properties.rs b/src/mpeg/properties.rs index d3b73e1d7..80a50cc08 100644 --- a/src/mpeg/properties.rs +++ b/src/mpeg/properties.rs @@ -1,8 +1,8 @@ use super::header::{ChannelMode, Emphasis, Header, Layer, MpegVersion, XingHeader}; use crate::error::Result; -use crate::math::RoundedDivision; use crate::mpeg::header::{cmp_header, rev_search_for_frame_sync, HeaderCmpResult, HEADER_MASK}; use crate::properties::{ChannelMask, FileProperties}; +use crate::util::math::RoundedDivision; use std::io::{Read, Seek, SeekFrom}; use std::time::Duration; diff --git a/src/ogg/opus/properties.rs b/src/ogg/opus/properties.rs index 472e9fdc8..63ad36dc1 100644 --- a/src/ogg/opus/properties.rs +++ b/src/ogg/opus/properties.rs @@ -1,8 +1,8 @@ use super::find_last_page; use crate::error::Result; use crate::macros::decode_err; -use crate::math::RoundedDivision; use crate::properties::{ChannelMask, FileProperties}; +use crate::util::math::RoundedDivision; use std::io::{Read, Seek, SeekFrom}; use std::time::Duration; diff --git a/src/ogg/speex/properties.rs b/src/ogg/speex/properties.rs index 660e20f11..9f7189691 100644 --- a/src/ogg/speex/properties.rs +++ b/src/ogg/speex/properties.rs @@ -1,8 +1,8 @@ use crate::error::Result; use crate::macros::decode_err; -use crate::math::RoundedDivision; use crate::ogg::find_last_page; use crate::properties::FileProperties; +use crate::util::math::RoundedDivision; use std::io::{Read, Seek, SeekFrom}; use std::time::Duration; diff --git a/src/ogg/vorbis/properties.rs b/src/ogg/vorbis/properties.rs index c76894cb2..af07bd545 100644 --- a/src/ogg/vorbis/properties.rs +++ b/src/ogg/vorbis/properties.rs @@ -1,7 +1,7 @@ use super::find_last_page; use crate::error::Result; -use crate::math::RoundedDivision; use crate::properties::FileProperties; +use crate::util::math::RoundedDivision; use std::io::{Read, Seek, SeekFrom}; use std::time::Duration; diff --git a/src/math.rs b/src/util/math.rs similarity index 100% rename from src/math.rs rename to src/util/math.rs diff --git a/src/util/mod.rs b/src/util/mod.rs index b29ec85ca..ffd58664f 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod alloc; +pub(crate) mod math; pub(crate) mod text; From 24d249a185223a64d24d9eabf8a0e94b3898b23d Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:51:01 -0400 Subject: [PATCH 16/22] traits: Move `SeekStreamLen` to `lofty::util::io` --- src/ape/header.rs | 2 +- src/lib.rs | 1 - src/mp4/read.rs | 2 +- src/musepack/read.rs | 2 +- src/{traits.rs => util/io.rs} | 0 src/util/mod.rs | 1 + 6 files changed, 4 insertions(+), 4 deletions(-) rename src/{traits.rs => util/io.rs} (100%) diff --git a/src/ape/header.rs b/src/ape/header.rs index a093a6924..115738ce2 100644 --- a/src/ape/header.rs +++ b/src/ape/header.rs @@ -1,6 +1,6 @@ use crate::error::Result; use crate::macros::decode_err; -use crate::traits::SeekStreamLen; +use crate::util::io::SeekStreamLen; use std::io::{Read, Seek, SeekFrom}; use std::ops::Neg; diff --git a/src/lib.rs b/src/lib.rs index 831d7dfaf..93c707e8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,7 +159,6 @@ mod probe; pub mod properties; pub mod resolve; pub mod tag; -mod traits; mod util; pub mod aac; diff --git a/src/mp4/read.rs b/src/mp4/read.rs index 457132b7a..b95de231c 100644 --- a/src/mp4/read.rs +++ b/src/mp4/read.rs @@ -5,7 +5,7 @@ use super::Mp4File; use crate::config::{ParseOptions, ParsingMode}; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::{decode_err, err}; -use crate::traits::SeekStreamLen; +use crate::util::io::SeekStreamLen; use crate::util::text::utf8_decode_str; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/musepack/read.rs b/src/musepack/read.rs index 09fd525d7..c311afbb5 100644 --- a/src/musepack/read.rs +++ b/src/musepack/read.rs @@ -6,7 +6,7 @@ use crate::config::ParseOptions; use crate::error::Result; use crate::id3::v2::read::parse_id3v2; use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, FindId3v2Config, ID3FindResults}; -use crate::traits::SeekStreamLen; +use crate::util::io::SeekStreamLen; use std::io::{Read, Seek, SeekFrom}; diff --git a/src/traits.rs b/src/util/io.rs similarity index 100% rename from src/traits.rs rename to src/util/io.rs diff --git a/src/util/mod.rs b/src/util/mod.rs index ffd58664f..009c84209 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ pub(crate) mod alloc; +pub(crate) mod io; pub(crate) mod math; pub(crate) mod text; From b2843e47eaaea6e40bc80e8f351aacddcfdeb7af Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:52:18 -0400 Subject: [PATCH 17/22] io: Prevent `unstable_name_collisions` --- src/ape/header.rs | 3 +-- src/mp4/read.rs | 5 ++--- src/musepack/read.rs | 3 +-- src/util/io.rs | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/ape/header.rs b/src/ape/header.rs index 115738ce2..23c0f45f7 100644 --- a/src/ape/header.rs +++ b/src/ape/header.rs @@ -44,8 +44,7 @@ where size = size.saturating_add(32); } - #[allow(unstable_name_collisions)] - if u64::from(size) > data.stream_len()? { + if u64::from(size) > data.stream_len_hack()? { decode_err!(@BAIL Ape, "APE tag has an invalid size (> file size)"); } diff --git a/src/mp4/read.rs b/src/mp4/read.rs index b95de231c..c5de5411a 100644 --- a/src/mp4/read.rs +++ b/src/mp4/read.rs @@ -28,8 +28,7 @@ where R: Read + Seek, { pub(super) fn new(mut reader: R, parse_mode: ParsingMode) -> Result { - #[allow(unstable_name_collisions)] - let len = reader.stream_len()?; + let len = reader.stream_len_hack()?; Ok(Self { reader, start: 0, @@ -185,7 +184,7 @@ where R: Read + Seek, { let mut reader = AtomReader::new(data, parse_options.parsing_mode)?; - let file_length = reader.stream_len()?; + let file_length = reader.stream_len_hack()?; let ftyp = verify_mp4(&mut reader)?; diff --git a/src/musepack/read.rs b/src/musepack/read.rs index c311afbb5..38fed80a0 100644 --- a/src/musepack/read.rs +++ b/src/musepack/read.rs @@ -20,8 +20,7 @@ where let mut version = MpcStreamVersion::Sv4to6; let mut file = MpcFile::default(); - #[allow(unstable_name_collisions)] - let mut stream_length = reader.stream_len()?; + let mut stream_length = reader.stream_len_hack()?; // ID3v2 tags are unsupported in MPC files, but still possible #[allow(unused_variables)] diff --git a/src/util/io.rs b/src/util/io.rs index f344a64cc..3a2946c6d 100644 --- a/src/util/io.rs +++ b/src/util/io.rs @@ -1,6 +1,6 @@ // TODO: https://github.com/rust-lang/rust/issues/59359 pub(crate) trait SeekStreamLen: std::io::Seek { - fn stream_len(&mut self) -> crate::error::Result { + fn stream_len_hack(&mut self) -> crate::error::Result { use std::io::SeekFrom; let current_pos = self.stream_position()?; From 42e4c65c5c82ba2099fbd553f70e5c216b22b5aa Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:55:47 -0400 Subject: [PATCH 18/22] picture: Make module public, remove re-exports --- src/lib.rs | 5 +---- src/ogg/picture_storage.rs | 2 +- src/picture.rs | 4 +++- src/tag/mod.rs | 2 +- tests/fuzz/pictureinformation_from_jpeg.rs | 2 +- tests/fuzz/pictureinformation_from_png.rs | 2 +- tests/picture/format_parsers.rs | 3 ++- tests/picture/from_reader.rs | 2 +- tests/picture/information.rs | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 93c707e8d..5abb57242 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,7 +154,7 @@ pub mod config; pub mod error; pub mod file; pub(crate) mod macros; -pub(crate) mod picture; +pub mod picture; mod probe; pub mod properties; pub mod resolve; @@ -174,11 +174,8 @@ pub mod wavpack; pub use crate::probe::{read_from, read_from_path, Probe}; -pub use crate::picture::{MimeType, Picture, PictureType}; pub use util::text::TextEncoding; -pub use picture::PictureInformation; - pub use lofty_attr::LoftyFile; pub mod prelude { diff --git a/src/ogg/picture_storage.rs b/src/ogg/picture_storage.rs index 4e02e5bd7..c94488c73 100644 --- a/src/ogg/picture_storage.rs +++ b/src/ogg/picture_storage.rs @@ -174,7 +174,7 @@ pub trait OggPictureStorage: private::Sealed { } mod private { - use crate::{Picture, PictureInformation}; + use crate::picture::{Picture, PictureInformation}; pub trait Sealed { fn pictures_mut(&mut self) -> &mut Vec<(Picture, PictureInformation)>; diff --git a/src/picture.rs b/src/picture.rs index 9686ea294..fb6a95161 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -1,3 +1,5 @@ +//! Format-agnostic picture handling + use crate::config::ParsingMode; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::err; @@ -138,7 +140,7 @@ pub enum PictureType { impl PictureType { // ID3/OGG specific methods - /// Get a u8 from a `PictureType` according to ID3v2 APIC + /// Get a `u8` from a `PictureType` according to ID3v2 APIC pub fn as_u8(&self) -> u8 { match self { Self::Other => 0, diff --git a/src/tag/mod.rs b/src/tag/mod.rs index a34d68516..51e6a8577 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -616,10 +616,10 @@ impl MergeTag for SplitTagRemainder { mod tests { use super::try_parse_year; use crate::config::WriteOptions; + use crate::picture::{Picture, PictureType}; use crate::prelude::*; use crate::tag::utils::test_utils::read_path; use crate::tag::{Tag, TagType}; - use crate::{Picture, PictureType}; use std::io::{Seek, Write}; use std::process::Command; diff --git a/tests/fuzz/pictureinformation_from_jpeg.rs b/tests/fuzz/pictureinformation_from_jpeg.rs index 33a984675..90c6e3a21 100644 --- a/tests/fuzz/pictureinformation_from_jpeg.rs +++ b/tests/fuzz/pictureinformation_from_jpeg.rs @@ -1,6 +1,6 @@ use crate::get_reader; use lofty::error::ErrorKind; -use lofty::PictureInformation; +use lofty::picture::PictureInformation; #[test] fn crash1() { diff --git a/tests/fuzz/pictureinformation_from_png.rs b/tests/fuzz/pictureinformation_from_png.rs index 5d36086c9..7006765cb 100644 --- a/tests/fuzz/pictureinformation_from_png.rs +++ b/tests/fuzz/pictureinformation_from_png.rs @@ -1,5 +1,5 @@ use crate::get_reader; -use lofty::PictureInformation; +use lofty::picture::PictureInformation; #[test] fn crash1() { diff --git a/tests/picture/format_parsers.rs b/tests/picture/format_parsers.rs index 6265f9663..b028fe31f 100644 --- a/tests/picture/format_parsers.rs +++ b/tests/picture/format_parsers.rs @@ -1,6 +1,7 @@ use lofty::config::ParsingMode; use lofty::id3::v2::{AttachedPictureFrame, Id3v2Version}; -use lofty::{Picture, PictureInformation, PictureType, TextEncoding}; +use lofty::picture::{Picture, PictureInformation, PictureType}; +use lofty::TextEncoding; use std::fs::File; use std::io::Read; diff --git a/tests/picture/from_reader.rs b/tests/picture/from_reader.rs index 56eaca2ae..9c7d5be70 100644 --- a/tests/picture/from_reader.rs +++ b/tests/picture/from_reader.rs @@ -1,4 +1,4 @@ -use lofty::{MimeType, Picture}; +use lofty::picture::{MimeType, Picture}; use std::fs::File; use std::io::Read; diff --git a/tests/picture/information.rs b/tests/picture/information.rs index 6750612da..f2619fcfe 100644 --- a/tests/picture/information.rs +++ b/tests/picture/information.rs @@ -1,4 +1,4 @@ -use lofty::PictureInformation; +use lofty::picture::PictureInformation; use std::fs::File; use std::io::Read; From 19ec2b4ef2b1c743ea49d092933caf0b3c661ca8 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:57:10 -0400 Subject: [PATCH 19/22] changelog: Update for `lofty::picture` change --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95adf16d1..2ff2e696b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `TagItem` - `ItemKey` - `ItemValue` +- **Picture**: + - ⚠️ Important ⚠️- The following items have been moved to `lofty::picture` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)): + - `Picture` + - `PictureType` + - `PictureInformation` + - `MimeType` ### Fixed - **Vorbis**: Fix panic when reading properties of zero-length files ([issue](https://github.com/Serial-ATA/lofty-rs/issues/342)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/365)) From 6b0f0d86f0e569d646a2713f4cac178152718d43 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 13:02:27 -0400 Subject: [PATCH 20/22] doc: Fix some example imports --- src/mp4/ilst/mod.rs | 4 +-- src/ogg/picture_storage.rs | 62 +++++++++++++++++++++++++++----------- src/picture.rs | 4 +-- src/tag/mod.rs | 32 +++++++++++++++----- 4 files changed, 73 insertions(+), 29 deletions(-) diff --git a/src/mp4/ilst/mod.rs b/src/mp4/ilst/mod.rs index 335728b59..1a901924d 100644 --- a/src/mp4/ilst/mod.rs +++ b/src/mp4/ilst/mod.rs @@ -250,8 +250,8 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::Ilst; + /// use lofty::picture::{MimeType, Picture, PictureType}; /// use lofty::tag::TagExt; - /// use lofty::{MimeType, Picture, PictureType}; /// /// let mut ilst = Ilst::new(); /// @@ -294,8 +294,8 @@ impl Ilst { /// /// ```rust /// use lofty::mp4::Ilst; + /// use lofty::picture::{MimeType, Picture, PictureType}; /// use lofty::tag::TagExt; - /// use lofty::{MimeType, Picture, PictureType}; /// /// let mut ilst = Ilst::new(); /// diff --git a/src/ogg/picture_storage.rs b/src/ogg/picture_storage.rs index c94488c73..fd3051794 100644 --- a/src/ogg/picture_storage.rs +++ b/src/ogg/picture_storage.rs @@ -70,30 +70,41 @@ pub trait OggPictureStorage: private::Sealed { /// # Examples /// /// ```rust - /// use lofty::ogg::{VorbisComments, OggPictureStorage}; - /// # use lofty::{Picture, PictureInformation, PictureType, MimeType}; + /// use lofty::ogg::{OggPictureStorage, VorbisComments}; + /// use lofty::picture::{MimeType, Picture, PictureInformation, PictureType}; /// /// # fn main() -> lofty::error::Result<()> { - /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); - /// # let front_cover_info = PictureInformation::default(); - /// # let back_cover = Picture::new_unchecked(PictureType::CoverBack, Some(MimeType::Png), None, Vec::new()); - /// # let back_cover_info = PictureInformation::default(); - /// # let another_picture = Picture::new_unchecked(PictureType::Band, Some(MimeType::Png), None, Vec::new()); /// let mut tag = VorbisComments::default(); /// /// // Add a front cover + /// let front_cover = Picture::new_unchecked( + /// PictureType::CoverFront, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// let front_cover_info = PictureInformation::default(); /// tag.insert_picture(front_cover, Some(front_cover_info))?; /// /// assert_eq!(tag.pictures().len(), 1); /// assert_eq!(tag.pictures()[0].0.pic_type(), PictureType::CoverFront); /// /// // Replace the front cover with a back cover + /// let back_cover = Picture::new_unchecked( + /// PictureType::CoverBack, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// let back_cover_info = PictureInformation::default(); /// tag.set_picture(0, back_cover, back_cover_info); /// /// assert_eq!(tag.pictures().len(), 1); /// assert_eq!(tag.pictures()[0].0.pic_type(), PictureType::CoverBack); /// /// // Use an out of bounds index + /// let another_picture = + /// Picture::new_unchecked(PictureType::Band, Some(MimeType::Png), None, Vec::new()); /// tag.set_picture(100, another_picture, PictureInformation::default()); /// /// assert_eq!(tag.pictures().len(), 2); @@ -118,12 +129,18 @@ pub trait OggPictureStorage: private::Sealed { /// # Examples /// /// ```rust - /// use lofty::ogg::{VorbisComments, OggPictureStorage}; - /// # use lofty::{Picture, PictureType, MimeType, PictureInformation}; + /// use lofty::ogg::{OggPictureStorage, VorbisComments}; + /// use lofty::picture::{MimeType, Picture, PictureInformation, PictureType}; /// /// # fn main() -> lofty::error::Result<()> { - /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); - /// # let front_cover_info = PictureInformation::default(); + /// let front_cover = Picture::new_unchecked( + /// PictureType::CoverFront, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// let front_cover_info = PictureInformation::default(); + /// /// let mut tag = VorbisComments::default(); /// /// // Add a front cover @@ -145,18 +162,29 @@ pub trait OggPictureStorage: private::Sealed { /// # Examples /// /// ```rust - /// use lofty::ogg::{VorbisComments, OggPictureStorage}; - /// # use lofty::{Picture, PictureType, MimeType, PictureInformation}; + /// use lofty::ogg::{OggPictureStorage, VorbisComments}; + /// use lofty::picture::{MimeType, Picture, PictureInformation, PictureType}; /// /// # fn main() -> lofty::error::Result<()> { - /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); - /// # let front_cover_info = PictureInformation::default(); - /// # let back_cover = Picture::new_unchecked(PictureType::CoverBack, Some(MimeType::Png), None, Vec::new()); - /// # let back_cover_info = PictureInformation::default(); /// let mut tag = VorbisComments::default(); /// /// // Add front and back covers + /// let front_cover = Picture::new_unchecked( + /// PictureType::CoverFront, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// let front_cover_info = PictureInformation::default(); /// tag.insert_picture(front_cover, Some(front_cover_info))?; + /// + /// let back_cover = Picture::new_unchecked( + /// PictureType::CoverBack, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// let back_cover_info = PictureInformation::default(); /// tag.insert_picture(back_cover, Some(front_cover_info))?; /// /// assert_eq!(tag.pictures().len(), 2); diff --git a/src/picture.rs b/src/picture.rs index fb6a95161..dda994e9e 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -61,7 +61,7 @@ impl MimeType { /// # Examples /// /// ```rust - /// use lofty::MimeType; + /// use lofty::picture::MimeType; /// /// let jpeg_mimetype_str = "image/jpeg"; /// assert_eq!(MimeType::from_str(jpeg_mimetype_str), MimeType::Jpeg); @@ -84,7 +84,7 @@ impl MimeType { /// # Examples /// /// ```rust - /// use lofty::MimeType; + /// use lofty::picture::MimeType; /// /// let jpeg_mimetype = MimeType::Jpeg; /// assert_eq!(jpeg_mimetype.as_str(), "image/jpeg") diff --git a/src/tag/mod.rs b/src/tag/mod.rs index 51e6a8577..9caaddb6f 100644 --- a/src/tag/mod.rs +++ b/src/tag/mod.rs @@ -461,28 +461,38 @@ impl Tag { /// # Examples /// /// ```rust + /// use lofty::picture::{MimeType, Picture, PictureType}; /// use lofty::tag::{Tag, TagType}; - /// use lofty::Picture; - /// # use lofty::{PictureType, MimeType}; /// - /// # let front_cover = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); - /// # let back_cover = Picture::new_unchecked(PictureType::CoverBack, Some(MimeType::Png), None, Vec::new()); - /// # let another_picture = Picture::new_unchecked(PictureType::Band, Some(MimeType::Png), None, Vec::new()); /// let mut tag = Tag::new(TagType::Id3v2); /// /// // Add a front cover + /// let front_cover = Picture::new_unchecked( + /// PictureType::CoverFront, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); /// tag.push_picture(front_cover); /// /// assert_eq!(tag.pictures().len(), 1); /// assert_eq!(tag.pictures()[0].pic_type(), PictureType::CoverFront); /// /// // Replace the front cover with a back cover + /// let back_cover = Picture::new_unchecked( + /// PictureType::CoverBack, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); /// tag.set_picture(0, back_cover); /// /// assert_eq!(tag.pictures().len(), 1); /// assert_eq!(tag.pictures()[0].pic_type(), PictureType::CoverBack); /// /// // Use an out of bounds index + /// let another_picture = + /// Picture::new_unchecked(PictureType::Band, Some(MimeType::Png), None, Vec::new()); /// tag.set_picture(100, another_picture); /// /// assert_eq!(tag.pictures().len(), 2); @@ -504,12 +514,18 @@ impl Tag { /// # Examples /// /// ```rust + /// use lofty::picture::{MimeType, Picture, PictureType}; /// use lofty::tag::{Tag, TagType}; - /// use lofty::Picture; - /// # use lofty::{PictureType, MimeType}; /// - /// # let picture = Picture::new_unchecked(PictureType::CoverFront, Some(MimeType::Png), None, Vec::new()); /// let mut tag = Tag::new(TagType::Id3v2); + /// + /// let picture = Picture::new_unchecked( + /// PictureType::CoverFront, + /// Some(MimeType::Png), + /// None, + /// Vec::new(), + /// ); + /// /// tag.push_picture(picture); /// /// assert_eq!(tag.pictures().len(), 1); From c15880cfe668646cffa891e81a1ec176028d672e Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 13:08:08 -0400 Subject: [PATCH 21/22] probe: Make module public, remove re-exports --- CHANGELOG.md | 2 ++ examples/tag_reader.rs | 2 +- examples/tag_stripper.rs | 2 +- examples/tag_writer.rs | 2 +- src/config/parse_options.rs | 4 ++-- src/file/file_type.rs | 2 +- src/lib.rs | 8 ++++---- src/probe.rs | 32 +++++++++++++++++--------------- src/resolve.rs | 2 +- tests/files/aac.rs | 2 +- tests/files/aiff.rs | 2 +- tests/files/ape.rs | 2 +- tests/files/mp4.rs | 2 +- tests/files/mpc.rs | 2 +- tests/files/mpeg.rs | 2 +- tests/files/ogg.rs | 2 +- tests/files/util/mod.rs | 4 ++-- tests/files/wav.rs | 2 +- tests/files/wavpack.rs | 2 +- 19 files changed, 41 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ff2e696b..6ecc5d578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `TagItem` - `ItemKey` - `ItemValue` +- **Probe**: + - ⚠️ Important ⚠️- Moved to `lofty::probe` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)): - **Picture**: - ⚠️ Important ⚠️- The following items have been moved to `lofty::picture` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374)): - `Picture` diff --git a/examples/tag_reader.rs b/examples/tag_reader.rs index 1db62beac..8392e3517 100644 --- a/examples/tag_reader.rs +++ b/examples/tag_reader.rs @@ -1,5 +1,5 @@ use lofty::prelude::*; -use lofty::Probe; +use lofty::probe::Probe; use std::path::Path; diff --git a/examples/tag_stripper.rs b/examples/tag_stripper.rs index b59a85192..039b04e9e 100644 --- a/examples/tag_stripper.rs +++ b/examples/tag_stripper.rs @@ -1,5 +1,5 @@ use lofty::file::TaggedFileExt; -use lofty::Probe; +use lofty::probe::Probe; use std::io::Write; diff --git a/examples/tag_writer.rs b/examples/tag_writer.rs index 18dd65f9c..2887ee8cb 100644 --- a/examples/tag_writer.rs +++ b/examples/tag_writer.rs @@ -1,7 +1,7 @@ use lofty::config::WriteOptions; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::Tag; -use lofty::Probe; use structopt::StructOpt; diff --git a/src/config/parse_options.rs b/src/config/parse_options.rs index 3c2ab4c9a..c11d6cdbd 100644 --- a/src/config/parse_options.rs +++ b/src/config/parse_options.rs @@ -102,13 +102,13 @@ impl ParseOptions { /// The parsing strictness mode /// -/// This can be set with [`Probe::options`](crate::Probe). +/// This can be set with [`Probe::options`](crate::probe::Probe). /// /// # Examples /// /// ```rust,no_run /// use lofty::config::{ParseOptions, ParsingMode}; -/// use lofty::Probe; +/// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// // We only want to read spec-compliant inputs diff --git a/src/file/file_type.rs b/src/file/file_type.rs index 46535dd93..59e0c4efb 100644 --- a/src/file/file_type.rs +++ b/src/file/file_type.rs @@ -172,7 +172,7 @@ impl FileType { /// * This **will not** search past tags at the start of the buffer. /// For this behavior, use [`Probe::guess_file_type`]. /// - /// [`Probe::guess_file_type`]: crate::Probe::guess_file_type + /// [`Probe::guess_file_type`]: crate::probe::Probe::guess_file_type /// /// # Examples /// diff --git a/src/lib.rs b/src/lib.rs index 5abb57242..c08c238d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,8 @@ //! //! ```rust,no_run //! # fn main() -> lofty::error::Result<()> { -//! use lofty::{read_from_path, Probe}; +//! use lofty::probe::Probe; +//! use lofty::read_from_path; //! //! // This will guess the format from the extension //! // ("mp3" in this case), but we can guess from the content if we want to. @@ -155,7 +156,7 @@ pub mod error; pub mod file; pub(crate) mod macros; pub mod picture; -mod probe; +pub mod probe; pub mod properties; pub mod resolve; pub mod tag; @@ -172,7 +173,7 @@ pub mod musepack; pub mod ogg; pub mod wavpack; -pub use crate::probe::{read_from, read_from_path, Probe}; +pub use crate::probe::{read_from, read_from_path}; pub use util::text::TextEncoding; @@ -187,7 +188,6 @@ pub mod prelude { //! use lofty::prelude::*; //! ``` - pub use crate::error::LoftyError; pub use crate::file::{AudioFile, TaggedFileExt}; pub use crate::tag::{Accessor, ItemKey, MergeTag, SplitTag, TagExt}; } diff --git a/src/probe.rs b/src/probe.rs index 404f22c80..0d66d5c83 100644 --- a/src/probe.rs +++ b/src/probe.rs @@ -1,3 +1,5 @@ +//! Format-agonostic file parsing tools + use crate::aac::AacFile; use crate::ape::ApeFile; use crate::config::{global_options, ParseOptions}; @@ -34,7 +36,7 @@ use std::path::Path; /// ```rust,no_run /// # fn main() -> lofty::error::Result<()> { /// use lofty::file::FileType; -/// use lofty::Probe; +/// use lofty::probe::Probe; /// /// let probe = Probe::open("path/to/my.mp3")?; /// @@ -49,7 +51,7 @@ use std::path::Path; /// ```rust,no_run /// # fn main() -> lofty::error::Result<()> { /// use lofty::file::FileType; -/// use lofty::Probe; +/// use lofty::probe::Probe; /// /// // Our same path probe with a guessed file type /// let probe = Probe::open("path/to/my.mp3")?.guess_file_type()?; @@ -65,7 +67,7 @@ use std::path::Path; /// ```rust /// # fn main() -> lofty::error::Result<()> { /// use lofty::file::FileType; -/// use lofty::Probe; +/// use lofty::probe::Probe; /// use std::io::Cursor; /// /// static MAC_HEADER: &[u8; 3] = b"MAC"; @@ -86,13 +88,13 @@ pub struct Probe { impl Probe { /// Create a new `Probe` /// - /// Before creating a `Probe`, consider wrapping it in a [`BufReader`](std::io::BufReader) for better + /// Before creating a `Probe`, consider wrapping it in a [`BufReader`] for better /// performance. /// /// # Examples /// /// ```rust - /// use lofty::Probe; + /// use lofty::probe::Probe; /// use std::fs::File; /// use std::io::BufReader; /// @@ -115,14 +117,14 @@ impl Probe { /// Create a new `Probe` with a specified [`FileType`] /// - /// Before creating a `Probe`, consider wrapping it in a [`BufReader`](std::io::BufReader) for better + /// Before creating a `Probe`, consider wrapping it in a [`BufReader`] for better /// performance. /// /// # Examples /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// use std::fs::File; /// use std::io::BufReader; /// @@ -150,7 +152,7 @@ impl Probe { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); @@ -169,7 +171,7 @@ impl Probe { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); @@ -192,7 +194,7 @@ impl Probe { /// /// ```rust /// use lofty::config::ParseOptions; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); @@ -215,7 +217,7 @@ impl Probe { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let reader = std::io::Cursor::new(&[]); @@ -243,7 +245,7 @@ impl Probe> { /// /// ```rust,no_run /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// let probe = Probe::open("path/to/my.mp3")?; @@ -289,7 +291,7 @@ impl Probe { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; @@ -442,7 +444,7 @@ impl Probe { /// /// ```rust /// use lofty::file::FileType; - /// use lofty::Probe; + /// use lofty::probe::Probe; /// /// # fn main() -> lofty::error::Result<()> { /// # let path = "tests/files/assets/minimal/full_test.mp3"; @@ -543,7 +545,7 @@ where mod tests { use crate::config::{GlobalOptions, ParseOptions}; use crate::file::FileType; - use crate::Probe; + use crate::probe::Probe; use std::fs::File; diff --git a/src/resolve.rs b/src/resolve.rs index e1231bd60..2262c0e8a 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -15,7 +15,7 @@ use std::sync::{Arc, Mutex, OnceLock}; /// /// This trait allows for the creation of custom [`FileType`]s, that can make use of /// lofty's API. Registering a `FileResolver` ([`register_custom_resolver`]) makes it possible -/// to detect and read files using [`Probe`](crate::Probe). +/// to detect and read files using [`Probe`](crate::probe::Probe). pub trait FileResolver: Send + Sync + AudioFile { /// The extension associated with the [`FileType`] without the '.' fn extension() -> Option<&'static str>; diff --git a/tests/files/aac.rs b/tests/files/aac.rs index 6cf2142ad..7d42b0bc3 100644 --- a/tests/files/aac.rs +++ b/tests/files/aac.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/aiff.rs b/tests/files/aiff.rs index 85799da6c..de7e9686b 100644 --- a/tests/files/aiff.rs +++ b/tests/files/aiff.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/ape.rs b/tests/files/ape.rs index bddb597e0..3af288013 100644 --- a/tests/files/ape.rs +++ b/tests/files/ape.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mp4.rs b/tests/files/mp4.rs index 630375097..0020f675c 100644 --- a/tests/files/mp4.rs +++ b/tests/files/mp4.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mpc.rs b/tests/files/mpc.rs index 77e725f8c..c9ab4466e 100644 --- a/tests/files/mpc.rs +++ b/tests/files/mpc.rs @@ -3,8 +3,8 @@ use lofty::config::ParseOptions; use lofty::file::{FileType, TaggedFile}; use lofty::musepack::MpcFile; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/mpeg.rs b/tests/files/mpeg.rs index 80f7e2ce6..a72fc3b72 100644 --- a/tests/files/mpeg.rs +++ b/tests/files/mpeg.rs @@ -4,8 +4,8 @@ use lofty::file::FileType; use lofty::id3::v2::{Frame, FrameFlags, FrameId, FrameValue, Id3v2Tag, KeyValueFrame}; use lofty::mpeg::MpegFile; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::{Tag, TagType}; -use lofty::Probe; use std::borrow::Cow; use std::io::{Seek, Write}; diff --git a/tests/files/ogg.rs b/tests/files/ogg.rs index 50df20b3d..1f002f09c 100644 --- a/tests/files/ogg.rs +++ b/tests/files/ogg.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::{ParseOptions, WriteOptions}; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/util/mod.rs b/tests/files/util/mod.rs index 23a15d812..72afe7694 100644 --- a/tests/files/util/mod.rs +++ b/tests/files/util/mod.rs @@ -79,7 +79,7 @@ macro_rules! remove_tag { ($path:tt, $tag_type:path) => { let mut file = temp_file!($path); - let tagged_file = lofty::Probe::new(&mut file) + let tagged_file = lofty::probe::Probe::new(&mut file) .options(lofty::config::ParseOptions::new().read_properties(false)) .guess_file_type() .unwrap() @@ -93,7 +93,7 @@ macro_rules! remove_tag { file.rewind().unwrap(); - let tagged_file = lofty::Probe::new(&mut file) + let tagged_file = lofty::probe::Probe::new(&mut file) .options(lofty::config::ParseOptions::new().read_properties(false)) .guess_file_type() .unwrap() diff --git a/tests/files/wav.rs b/tests/files/wav.rs index 7e925c8a2..2f7b1eebd 100644 --- a/tests/files/wav.rs +++ b/tests/files/wav.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index 72a77ffca..8c6d81e72 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -2,8 +2,8 @@ use crate::{set_artist, temp_file, verify_artist}; use lofty::config::ParseOptions; use lofty::file::FileType; use lofty::prelude::*; +use lofty::probe::Probe; use lofty::tag::TagType; -use lofty::Probe; use std::io::{Seek, Write}; From 7fd24ee8f6c6614ecd8b6128aebd19d5d101de27 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 14 Apr 2024 13:14:04 -0400 Subject: [PATCH 22/22] benches: Update for module refactor --- benches/create_tag.rs | 6 ++++-- benches/read_file.rs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/benches/create_tag.rs b/benches/create_tag.rs index 86b9aebfa..a6d7d7553 100644 --- a/benches/create_tag.rs +++ b/benches/create_tag.rs @@ -1,11 +1,13 @@ use lofty::ape::ApeTag; +use lofty::config::WriteOptions; use lofty::id3::v1::Id3v1Tag; use lofty::id3::v2::Id3v2Tag; use lofty::iff::aiff::AIFFTextChunks; use lofty::iff::wav::RIFFInfoList; use lofty::mp4::Ilst; use lofty::ogg::VorbisComments; -use lofty::{Accessor, MimeType, Picture, PictureType, TagExt, WriteOptions}; +use lofty::picture::{MimeType, Picture, PictureType}; +use lofty::tag::{Accessor, TagExt}; use iai_callgrind::{library_benchmark, library_benchmark_group, main}; @@ -36,7 +38,7 @@ bench_tag_write!([ (aiff_text_chunks, AIFFTextChunks, |tag| {}), (apev2, ApeTag, |tag| { use lofty::ape::ApeItem; - use lofty::ItemValue; + use lofty::tag::ItemValue; let picture = Picture::new_unchecked( PictureType::CoverFront, diff --git a/benches/read_file.rs b/benches/read_file.rs index d567cda1d..488438b2a 100644 --- a/benches/read_file.rs +++ b/benches/read_file.rs @@ -1,4 +1,5 @@ -use lofty::{ParseOptions, Probe}; +use lofty::config::ParseOptions; +use lofty::probe::Probe; use iai_callgrind::{library_benchmark, library_benchmark_group, main};