mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-05 02:19:12 +00:00
tag: Remove global re-exports of tag items
This commit is contained in:
parent
826e55be23
commit
cf778c1f58
41 changed files with 302 additions and 282 deletions
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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::<syn::Path>(&format!("::lofty::TagType::{}", &f.tag_type)).unwrap();
|
||||
syn::parse_str::<syn::Path>(&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),
|
||||
|
|
|
@ -446,7 +446,7 @@ fn generate_audiofile_impl(file: &LoftyFile) -> syn::Result<proc_macro2::TokenSt
|
|||
}
|
||||
|
||||
fn save_to(&self, file: &mut ::std::fs::File, write_options: ::lofty::config::WriteOptions) -> ::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<proc_macro2::TokenSt
|
|||
}
|
||||
|
||||
#[allow(unreachable_code, unused_variables)]
|
||||
fn contains_tag_type(&self, tag_type: ::lofty::TagType) -> 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
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::tag::item::ItemKey;
|
||||
use crate::tag::ItemKey;
|
||||
|
||||
pub(crate) const TIPL_MAPPINGS: &[(ItemKey, &str)] = &[
|
||||
(ItemKey::Producer, "producer"),
|
||||
|
|
|
@ -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<F: FnMut(u32)>(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() {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
10
src/lib.rs
10
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};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 _};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Path>) -> 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;
|
||||
|
|
69
src/tag/tag_type.rs
Normal file
69
src/tag/tag_type.rs
Normal file
|
@ -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<Path>) -> 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
|
||||
}
|
||||
}
|
135
src/tag/tagext.rs
Normal file
135
src/tag/tagext.rs
Normal file
|
@ -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<Tag> + Sized {
|
||||
/// The associated error which can be returned from IO operations
|
||||
type Err: From<std::io::Error>;
|
||||
/// 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<P: AsRef<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<W: std::io::Write>(
|
||||
&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<P: AsRef<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);
|
||||
}
|
|
@ -99,7 +99,7 @@ pub(crate) fn dump_tag<W: Write>(
|
|||
#[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;
|
||||
|
||||
|
|
133
src/traits.rs
133
src/traits.rs
|
@ -118,141 +118,8 @@ accessor_trait! {
|
|||
[year ]<u32>, [comment ]<Cow<'_, str>, 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<Tag> + Sized {
|
||||
/// The associated error which can be returned from IO operations
|
||||
type Err: From<std::io::Error>;
|
||||
/// 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<P: AsRef<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<W: std::io::Write>(
|
||||
&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<P: AsRef<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.
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue