mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-12 21:52:33 +00:00
Misc: Remove id3v2{_restrictions}
features
This commit is contained in:
parent
39c338e15b
commit
823f931d31
24 changed files with 112 additions and 203 deletions
|
@ -30,9 +30,8 @@ once_cell = "1.16.0"
|
|||
paste = "1.0.11"
|
||||
|
||||
[features]
|
||||
default = ["id3v2"]
|
||||
id3v2 = ["flate2"]
|
||||
id3v2_restrictions = []
|
||||
default = ["id3v2_compression_support"]
|
||||
id3v2_compression_support = ["flate2"]
|
||||
|
||||
[dev-dependencies]
|
||||
# WAV properties validity tests
|
||||
|
|
|
@ -20,7 +20,6 @@ pub use properties::AACProperties;
|
|||
#[lofty(read_fn = "read::read_from")]
|
||||
#[lofty(internal_write_module_do_not_use_anywhere_else)]
|
||||
pub struct AACFile {
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
#[lofty(tag_type = "ID3v1")]
|
||||
|
|
|
@ -48,19 +48,16 @@ where
|
|||
|
||||
stream_len -= u64::from(header.size);
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
{
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
if let Some(existing_tag) = &mut file.id3v2_tag {
|
||||
// https://github.com/Serial-ATA/lofty-rs/issues/87
|
||||
// Duplicate tags should have their frames appended to the previous
|
||||
for frame in id3v2.frames {
|
||||
existing_tag.insert(frame);
|
||||
}
|
||||
continue;
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
if let Some(existing_tag) = &mut file.id3v2_tag {
|
||||
// https://github.com/Serial-ATA/lofty-rs/issues/87
|
||||
// Duplicate tags should have their frames appended to the previous
|
||||
for frame in id3v2.frames {
|
||||
existing_tag.insert(frame);
|
||||
}
|
||||
file.id3v2_tag = Some(id3v2);
|
||||
continue;
|
||||
}
|
||||
file.id3v2_tag = Some(id3v2);
|
||||
|
||||
// Skip over the footer
|
||||
if skip_footer {
|
||||
|
|
|
@ -12,7 +12,6 @@ mod read;
|
|||
pub(crate) mod tag;
|
||||
|
||||
use crate::id3::v1::tag::ID3v1Tag;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
|
||||
use lofty_attr::LoftyFile;
|
||||
|
@ -33,7 +32,6 @@ pub struct ApeFile {
|
|||
#[lofty(tag_type = "ID3v1")]
|
||||
pub(crate) id3v1_tag: Option<ID3v1Tag>,
|
||||
/// An ID3v2 tag (Not officially supported)
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
/// An APEv1/v2 tag
|
||||
|
|
|
@ -5,8 +5,8 @@ use super::tag::ApeTag;
|
|||
use super::{ApeFile, ApeProperties};
|
||||
use crate::error::Result;
|
||||
use crate::id3::v1::tag::ID3v1Tag;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::{read::parse_id3v2, tag::ID3v2Tag};
|
||||
use crate::id3::v2::read::parse_id3v2;
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, ID3FindResults};
|
||||
use crate::macros::decode_err;
|
||||
use crate::probe::ParseOptions;
|
||||
|
@ -24,7 +24,6 @@ where
|
|||
|
||||
let mut stream_len = end - start;
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
let mut id3v2_tag: Option<ID3v2Tag> = None;
|
||||
let mut id3v1_tag: Option<ID3v1Tag> = None;
|
||||
let mut ape_tag: Option<ApeTag> = None;
|
||||
|
@ -39,13 +38,10 @@ where
|
|||
stream_len -= 10;
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
{
|
||||
let reader = &mut &*content;
|
||||
let reader = &mut &*content;
|
||||
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
id3v2_tag = Some(id3v2)
|
||||
}
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
id3v2_tag = Some(id3v2);
|
||||
}
|
||||
|
||||
let mut found_mac = false;
|
||||
|
@ -133,7 +129,6 @@ where
|
|||
|
||||
Ok(ApeFile {
|
||||
id3v1_tag,
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag,
|
||||
ape_tag,
|
||||
properties: if parse_options.read_properties {
|
||||
|
|
10
src/error.rs
10
src/error.rs
|
@ -70,21 +70,16 @@ pub enum ErrorKind {
|
|||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum ID3v2ErrorKind {
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Arises when an invalid picture format is parsed. Only applicable to [`ID3v2Version::V2`](crate::id3::v2::ID3v2Version::V2)
|
||||
BadPictureFormat(String),
|
||||
/// Arises when an invalid ID3v2 version is found
|
||||
BadId3v2Version(u8, u8),
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Arises when a frame ID contains invalid characters (must be within `'A'..'Z'` or `'0'..'9'`)
|
||||
BadFrameID,
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Arises when a frame doesn't have enough data
|
||||
BadFrameLength,
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Arises when invalid data is encountered while reading an ID3v2 synchronized text frame
|
||||
BadSyncText,
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Arises when attempting to write an invalid Frame (Bad `FrameID`/`FrameValue` pairing)
|
||||
BadFrame(String, &'static str),
|
||||
/// A catch-all for all remaining errors
|
||||
|
@ -101,22 +96,17 @@ impl Display for ID3v2ErrorKind {
|
|||
"Found an invalid version (v{major}.{minor}), expected any major revision in: (2, \
|
||||
3, 4)"
|
||||
),
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3v2ErrorKind::BadFrameID => write!(f, "Failed to parse a frame ID"),
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3v2ErrorKind::BadFrameLength => write!(
|
||||
f,
|
||||
"Frame isn't long enough to extract the necessary information"
|
||||
),
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3v2ErrorKind::BadSyncText => write!(f, "Encountered invalid data in SYLT frame"),
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3v2ErrorKind::BadFrame(ref frame_id, frame_value) => write!(
|
||||
f,
|
||||
"Attempted to write an invalid frame. ID: \"{}\", Value: \"{}\"",
|
||||
frame_id, frame_value
|
||||
),
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3v2ErrorKind::BadPictureFormat(format) => {
|
||||
write!(f, "Picture: Found unexpected format \"{format}\"")
|
||||
},
|
||||
|
|
|
@ -817,7 +817,6 @@ impl FileType {
|
|||
/// ```
|
||||
pub fn supports_tag_type(&self, tag_type: TagType) -> bool {
|
||||
match self {
|
||||
#[cfg(feature = "id3v2")]
|
||||
FileType::AIFF | FileType::APE | FileType::MPEG | FileType::WAV | FileType::AAC
|
||||
if tag_type == TagType::ID3v2 =>
|
||||
{
|
||||
|
|
|
@ -9,7 +9,6 @@ pub(crate) mod properties;
|
|||
mod read;
|
||||
pub(crate) mod write;
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::ogg::VorbisComments;
|
||||
use crate::properties::FileProperties;
|
||||
|
@ -29,7 +28,6 @@ use lofty_attr::LoftyFile;
|
|||
#[lofty(read_fn = "read::read_from")]
|
||||
pub struct FlacFile {
|
||||
/// An ID3v2 tag
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
/// The vorbis comments contained in the file
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::block::Block;
|
||||
use super::FlacFile;
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::read::parse_id3v2;
|
||||
use crate::id3::{find_id3v2, ID3FindResults};
|
||||
use crate::macros::decode_err;
|
||||
|
@ -38,7 +37,6 @@ where
|
|||
R: Read + Seek,
|
||||
{
|
||||
let mut flac_file = FlacFile {
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag: None,
|
||||
vorbis_comments_tag: None,
|
||||
properties: FileProperties::default(),
|
||||
|
@ -46,13 +44,10 @@ where
|
|||
|
||||
// It is possible for a FLAC file to contain an ID3v2 tag
|
||||
if let ID3FindResults(Some(header), Some(content)) = find_id3v2(data, true)? {
|
||||
#[cfg(feature = "id3v2")]
|
||||
{
|
||||
let reader = &mut &*content;
|
||||
let reader = &mut &*content;
|
||||
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
flac_file.id3v2_tag = Some(id3v2)
|
||||
}
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
flac_file.id3v2_tag = Some(id3v2);
|
||||
}
|
||||
|
||||
let stream_info = verify_flac(data)?;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#[cfg(feature = "id3v2_restrictions")]
|
||||
use super::restrictions::TagRestrictions;
|
||||
|
||||
/// Flags that apply to the entire tag
|
||||
|
@ -17,7 +16,6 @@ pub struct ID3v2TagFlags {
|
|||
///
|
||||
/// This is calculated if the tag is written
|
||||
pub crc: bool,
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
/// Restrictions on the tag, written in the extended header
|
||||
///
|
||||
/// In addition to being setting this flag, all restrictions must be provided. See [`TagRestrictions`]
|
||||
|
|
|
@ -31,6 +31,7 @@ impl Frame {
|
|||
content = crate::id3::v2::util::unsynch_content(content.as_slice())?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2_compression_support")]
|
||||
if flags.compression {
|
||||
let mut decompressed = Vec::new();
|
||||
flate2::Decompress::new(true)
|
||||
|
@ -44,6 +45,11 @@ impl Frame {
|
|||
content = decompressed
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "id3v2_compression_support"))]
|
||||
if flags.compression {
|
||||
crate::macros::decode_err!(@BAIL ID3v2, "Encountered a compressed ID3v2 frame, support is disabled")
|
||||
}
|
||||
|
||||
let mut content_reader = &*content;
|
||||
|
||||
// Get the encryption method symbol
|
||||
|
|
|
@ -8,7 +8,13 @@
|
|||
//! * [Frame]
|
||||
|
||||
mod flags;
|
||||
mod frame;
|
||||
mod items;
|
||||
pub(crate) mod read;
|
||||
mod restrictions;
|
||||
pub(crate) mod tag;
|
||||
pub mod util;
|
||||
pub(crate) mod write;
|
||||
|
||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||
use crate::macros::err;
|
||||
|
@ -18,42 +24,26 @@ use std::io::Read;
|
|||
|
||||
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "id3v2")] {
|
||||
pub use flags::ID3v2TagFlags;
|
||||
pub use util::upgrade::{upgrade_v2, upgrade_v3};
|
||||
// Exports
|
||||
|
||||
pub(crate) mod tag;
|
||||
pub use tag::ID3v2Tag;
|
||||
pub use flags::ID3v2TagFlags;
|
||||
pub use util::upgrade::{upgrade_v2, upgrade_v3};
|
||||
|
||||
mod items;
|
||||
pub use items::encoded_text_frame::EncodedTextFrame;
|
||||
pub use items::language_frame::LanguageFrame;
|
||||
pub use items::encapsulated_object::{GEOBInformation, GeneralEncapsulatedObject};
|
||||
pub use items::sync_text::{SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat};
|
||||
pub use tag::ID3v2Tag;
|
||||
|
||||
mod frame;
|
||||
pub use frame::id::FrameID;
|
||||
pub use frame::Frame;
|
||||
pub use frame::FrameFlags;
|
||||
pub use frame::FrameValue;
|
||||
pub use items::encapsulated_object::{GEOBInformation, GeneralEncapsulatedObject};
|
||||
pub use items::encoded_text_frame::EncodedTextFrame;
|
||||
pub use items::language_frame::LanguageFrame;
|
||||
pub use items::sync_text::{
|
||||
SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat,
|
||||
};
|
||||
|
||||
pub(crate) mod read;
|
||||
pub(crate) mod write;
|
||||
}
|
||||
}
|
||||
pub use frame::id::FrameID;
|
||||
pub use frame::{Frame, FrameFlags, FrameValue};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "id3v2_restrictions")] {
|
||||
mod restrictions;
|
||||
pub use restrictions::{
|
||||
ImageSizeRestrictions, TagRestrictions, TagSizeRestrictions, TextSizeRestrictions,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "id3v2"))]
|
||||
use flags::ID3v2TagFlags;
|
||||
pub use restrictions::{
|
||||
ImageSizeRestrictions, TagRestrictions, TagSizeRestrictions, TextSizeRestrictions,
|
||||
};
|
||||
|
||||
/// The ID3v2 version
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
||||
|
@ -68,7 +58,6 @@ pub enum ID3v2Version {
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct ID3v2Header {
|
||||
#[cfg(feature = "id3v2")]
|
||||
pub version: ID3v2Version,
|
||||
pub flags: ID3v2TagFlags,
|
||||
pub size: u32,
|
||||
|
@ -114,8 +103,7 @@ where
|
|||
&& flags & 0x20 == 0x20,
|
||||
footer: (version == ID3v2Version::V4 || version == ID3v2Version::V3)
|
||||
&& flags & 0x10 == 0x10,
|
||||
crc: false, // Retrieved later if applicable
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
crc: false, // Retrieved later if applicable
|
||||
restrictions: None, // Retrieved later if applicable
|
||||
};
|
||||
|
||||
|
@ -150,7 +138,6 @@ where
|
|||
bytes.read_exact(&mut crc)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
if extended_flags & 0x10 == 0x10 {
|
||||
// We don't care about the length byte, it is always 1
|
||||
let _data_length = bytes.read_u8()?;
|
||||
|
@ -164,7 +151,6 @@ where
|
|||
}
|
||||
|
||||
Ok(ID3v2Header {
|
||||
#[cfg(feature = "id3v2")]
|
||||
version,
|
||||
flags: flags_parsed,
|
||||
size,
|
||||
|
|
|
@ -1,74 +1,70 @@
|
|||
//! Utilities for working with ID3v2 tags
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "id3v2")] {
|
||||
pub(crate) mod upgrade;
|
||||
pub(crate) mod upgrade;
|
||||
|
||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||
|
||||
pub(in crate::id3::v2) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut unsynch_content = Vec::new();
|
||||
pub(in crate::id3::v2) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut unsynch_content = Vec::new();
|
||||
|
||||
let mut discard = false;
|
||||
let mut discard = false;
|
||||
|
||||
let mut i = 0;
|
||||
let mut next = 0;
|
||||
let content_len = content.len();
|
||||
let mut i = 0;
|
||||
let mut next = 0;
|
||||
let content_len = content.len();
|
||||
|
||||
// Check for (0xFF, 0x00, 0x00), replace with (0xFF, 0x00)
|
||||
while i < content_len && next < content_len {
|
||||
// Verify the next byte is less than 0xE0 (0b111xxxxx)
|
||||
// Then remove the next byte if it is a zero
|
||||
if discard {
|
||||
if content[next] >= 0xE0 {
|
||||
return Err(ID3v2Error::new(ID3v2ErrorKind::Other(
|
||||
"Encountered an invalid unsynchronisation",
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
if content[next] == 0 {
|
||||
discard = false;
|
||||
next += 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check for (0xFF, 0x00, 0x00), replace with (0xFF, 0x00)
|
||||
while i < content_len && next < content_len {
|
||||
// Verify the next byte is less than 0xE0 (0b111xxxxx)
|
||||
// Then remove the next byte if it is a zero
|
||||
if discard {
|
||||
if content[next] >= 0xE0 {
|
||||
return Err(ID3v2Error::new(ID3v2ErrorKind::Other(
|
||||
"Encountered an invalid unsynchronisation",
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
if content[next] == 0 {
|
||||
discard = false;
|
||||
|
||||
unsynch_content.push(content[next]);
|
||||
|
||||
if content[next] == 0xFF {
|
||||
discard = true
|
||||
}
|
||||
|
||||
i += 1;
|
||||
next += 1;
|
||||
}
|
||||
|
||||
Ok(unsynch_content)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a synchsafe integer
|
||||
///
|
||||
/// See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) for an explanation.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// `n` doesn't fit in 28 bits
|
||||
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L9-L15
|
||||
pub fn synch_u32(n: u32) -> Result<u32> {
|
||||
if n > 0x1000_0000 {
|
||||
crate::macros::err!(TooMuchData);
|
||||
}
|
||||
discard = false;
|
||||
|
||||
let mut x: u32 = n & 0x7F | (n & 0xFFFF_FF80) << 1;
|
||||
x = x & 0x7FFF | (x & 0xFFFF_8000) << 1;
|
||||
x = x & 0x7F_FFFF | (x & 0xFF80_0000) << 1;
|
||||
Ok(x)
|
||||
unsynch_content.push(content[next]);
|
||||
|
||||
if content[next] == 0xFF {
|
||||
discard = true
|
||||
}
|
||||
|
||||
i += 1;
|
||||
next += 1;
|
||||
}
|
||||
|
||||
Ok(unsynch_content)
|
||||
}
|
||||
|
||||
/// Create a synchsafe integer
|
||||
///
|
||||
/// See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) for an explanation.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// `n` doesn't fit in 28 bits
|
||||
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L9-L15
|
||||
pub fn synch_u32(n: u32) -> Result<u32> {
|
||||
if n > 0x1000_0000 {
|
||||
crate::macros::err!(TooMuchData);
|
||||
}
|
||||
|
||||
let mut x: u32 = n & 0x7F | (n & 0xFFFF_FF80) << 1;
|
||||
x = x & 0x7FFF | (x & 0xFFFF_8000) << 1;
|
||||
x = x & 0x7F_FFFF | (x & 0xFF80_0000) << 1;
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
/// Unsynchronise a synchsafe integer
|
||||
|
|
|
@ -105,7 +105,6 @@ pub(super) fn create_tag<'a, I: Iterator<Item = FrameRef<'a>> + 'a>(
|
|||
|
||||
let has_footer = tag.flags.footer;
|
||||
let needs_crc = tag.flags.crc;
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
let has_restrictions = tag.flags.restrictions.is_some();
|
||||
|
||||
let (mut id3v2, extended_header_len) = create_tag_header(tag.flags)?;
|
||||
|
@ -126,7 +125,6 @@ pub(super) fn create_tag<'a, I: Iterator<Item = FrameRef<'a>> + 'a>(
|
|||
// Past the CRC
|
||||
let mut content_start_idx = 22;
|
||||
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
if has_restrictions {
|
||||
content_start_idx += 3;
|
||||
}
|
||||
|
@ -169,10 +167,6 @@ fn create_tag_header(flags: ID3v2TagFlags) -> Result<(Cursor<Vec<u8>>, u32)> {
|
|||
// Version 4, rev 0
|
||||
header.write_all(&[4, 0])?;
|
||||
|
||||
#[cfg(not(feature = "id3v2_restrictions"))]
|
||||
let extended_header = flags.crc;
|
||||
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
let extended_header = flags.crc || flags.restrictions.is_some();
|
||||
|
||||
if flags.footer {
|
||||
|
@ -212,7 +206,6 @@ fn create_tag_header(flags: ID3v2TagFlags) -> Result<(Cursor<Vec<u8>>, u32)> {
|
|||
header.write_all(&[0; 6])?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2_restrictions")]
|
||||
if let Some(restrictions) = flags.restrictions {
|
||||
ext_flags |= 0x10;
|
||||
extended_header_size += 2;
|
||||
|
|
|
@ -4,7 +4,6 @@ mod properties;
|
|||
mod read;
|
||||
pub(crate) mod tag;
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::properties::FileProperties;
|
||||
|
||||
|
@ -23,7 +22,6 @@ pub struct AiffFile {
|
|||
#[lofty(tag_type = "AIFFText")]
|
||||
pub(crate) text_chunks_tag: Option<AIFFTextChunks>,
|
||||
/// An ID3v2 tag
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
/// The file's audio properties
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::tag::{AIFFTextChunks, Comment};
|
||||
use super::AiffFile;
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::iff::chunk::Chunks;
|
||||
use crate::macros::{decode_err, err};
|
||||
|
@ -46,14 +45,12 @@ where
|
|||
let mut annotations = Vec::new();
|
||||
let mut comments = Vec::new();
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
let mut id3v2_tag: Option<ID3v2Tag> = None;
|
||||
|
||||
let mut chunks = Chunks::<BigEndian>::new(file_len);
|
||||
|
||||
while chunks.next(data).is_ok() {
|
||||
match &chunks.fourcc {
|
||||
#[cfg(feature = "id3v2")]
|
||||
b"ID3 " | b"id3 " => {
|
||||
let tag = chunks.id3_chunk(data)?;
|
||||
if let Some(existing_tag) = id3v2_tag.as_mut() {
|
||||
|
@ -159,7 +156,6 @@ where
|
|||
} => None,
|
||||
_ => Some(text_chunks),
|
||||
},
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::macros::{err, try_vec};
|
||||
|
||||
|
@ -91,7 +90,6 @@ impl<B: ByteOrder> Chunks<B> {
|
|||
Ok(content)
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
pub fn id3_chunk<R>(&mut self, data: &mut R) -> Result<ID3v2Tag>
|
||||
where
|
||||
R: Read + Seek,
|
||||
|
|
|
@ -4,7 +4,6 @@ mod properties;
|
|||
mod read;
|
||||
pub(crate) mod tag;
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
|
||||
use lofty_attr::LoftyFile;
|
||||
|
@ -22,7 +21,6 @@ pub struct WavFile {
|
|||
#[lofty(tag_type = "RIFFInfo")]
|
||||
pub(crate) riff_info_tag: Option<RIFFInfoList>,
|
||||
/// An ID3v2 tag
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
/// The file's audio properties
|
||||
|
|
|
@ -2,7 +2,6 @@ use super::properties::WavProperties;
|
|||
use super::tag::RIFFInfoList;
|
||||
use super::WavFile;
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
use crate::iff::chunk::Chunks;
|
||||
use crate::macros::decode_err;
|
||||
|
@ -46,7 +45,6 @@ where
|
|||
let mut fmt = Vec::new();
|
||||
|
||||
let mut riff_info = RIFFInfoList::default();
|
||||
#[cfg(feature = "id3v2")]
|
||||
let mut id3v2_tag: Option<ID3v2Tag> = None;
|
||||
|
||||
let mut chunks = Chunks::<LittleEndian>::new(file_len);
|
||||
|
@ -89,7 +87,6 @@ where
|
|||
},
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "id3v2")]
|
||||
b"ID3 " | b"id3 " => {
|
||||
let tag = chunks.id3_chunk(data)?;
|
||||
if let Some(existing_tag) = id3v2_tag.as_mut() {
|
||||
|
@ -125,7 +122,6 @@ where
|
|||
Ok(WavFile {
|
||||
properties,
|
||||
riff_info_tag: (!riff_info.items.is_empty()).then_some(riff_info),
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ pub use properties::MPEGProperties;
|
|||
|
||||
use crate::ape::tag::ApeTag;
|
||||
use crate::id3::v1::tag::ID3v1Tag;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::ID3v2Tag;
|
||||
|
||||
use lofty_attr::LoftyFile;
|
||||
|
@ -20,7 +19,6 @@ use lofty_attr::LoftyFile;
|
|||
#[lofty(internal_write_module_do_not_use_anywhere_else)]
|
||||
pub struct MPEGFile {
|
||||
/// An ID3v2 tag
|
||||
#[cfg(feature = "id3v2")]
|
||||
#[lofty(tag_type = "ID3v2")]
|
||||
pub(crate) id3v2_tag: Option<ID3v2Tag>,
|
||||
/// An ID3v1 tag
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::ape::constants::APE_PREAMBLE;
|
|||
use crate::ape::header::read_ape_header;
|
||||
use crate::ape::tag::read::read_ape_tag;
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::read::parse_id3v2;
|
||||
use crate::id3::v2::read_id3v2_header;
|
||||
use crate::id3::{find_id3v1, find_lyrics3v2, ID3FindResults};
|
||||
|
@ -42,19 +41,16 @@ where
|
|||
let header = read_id3v2_header(reader)?;
|
||||
let skip_footer = header.flags.footer;
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
{
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
if let Some(existing_tag) = &mut file.id3v2_tag {
|
||||
// https://github.com/Serial-ATA/lofty-rs/issues/87
|
||||
// Duplicate tags should have their frames appended to the previous
|
||||
for frame in id3v2.frames {
|
||||
existing_tag.insert(frame);
|
||||
}
|
||||
continue;
|
||||
let id3v2 = parse_id3v2(reader, header)?;
|
||||
if let Some(existing_tag) = &mut file.id3v2_tag {
|
||||
// https://github.com/Serial-ATA/lofty-rs/issues/87
|
||||
// Duplicate tags should have their frames appended to the previous
|
||||
for frame in id3v2.frames {
|
||||
existing_tag.insert(frame);
|
||||
}
|
||||
file.id3v2_tag = Some(id3v2);
|
||||
continue;
|
||||
}
|
||||
file.id3v2_tag = Some(id3v2);
|
||||
|
||||
// Skip over the footer
|
||||
if skip_footer {
|
||||
|
|
|
@ -1,26 +1,13 @@
|
|||
use crate::error::{ErrorKind, LoftyError, Result};
|
||||
use crate::error::{ErrorKind, ID3v2Error, ID3v2ErrorKind, LoftyError, Result};
|
||||
use crate::id3::v2::ID3v2Version;
|
||||
use crate::macros::err;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::{
|
||||
error::{ID3v2Error, ID3v2ErrorKind},
|
||||
id3::v2::ID3v2Version,
|
||||
};
|
||||
use crate::util::text::TextEncoding;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
#[cfg(any(feature = "id3v2"))]
|
||||
use std::io::Cursor;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use std::io::Write;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::util::text::TextEncoding;
|
||||
use byteorder::BigEndian;
|
||||
#[cfg(any(feature = "id3v2"))]
|
||||
use byteorder::ReadBytesExt;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use byteorder::WriteBytesExt;
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
/// Common picture item keys for APE
|
||||
pub const APE_PICTURE_TYPES: [&str; 21] = [
|
||||
|
@ -142,7 +129,6 @@ pub enum PictureType {
|
|||
impl PictureType {
|
||||
// ID3/OGG specific methods
|
||||
|
||||
#[cfg(any(feature = "id3v2"))]
|
||||
/// Get a u8 from a `PictureType` according to ID3v2 APIC
|
||||
pub fn as_u8(&self) -> u8 {
|
||||
match self {
|
||||
|
@ -171,7 +157,6 @@ impl PictureType {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "id3v2"))]
|
||||
/// Get a `PictureType` from a u8 according to ID3v2 APIC
|
||||
pub fn from_u8(byte: u8) -> Self {
|
||||
match byte {
|
||||
|
@ -554,7 +539,6 @@ impl Picture {
|
|||
&self.data
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Convert a [`Picture`] to a ID3v2 A/PIC byte Vec
|
||||
///
|
||||
/// NOTE: This does not include the frame header
|
||||
|
@ -618,7 +602,6 @@ impl Picture {
|
|||
Ok(data)
|
||||
}
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
/// Get a [`Picture`] and [`TextEncoding`] from ID3v2 A/PIC bytes:
|
||||
///
|
||||
/// NOTE: This expects *only* the frame content
|
||||
|
|
|
@ -121,7 +121,6 @@ gen_map!(
|
|||
);
|
||||
|
||||
gen_map!(
|
||||
#[cfg(feature = "id3v2")]
|
||||
ID3V2_MAP;
|
||||
|
||||
"TALB" => AlbumTitle,
|
||||
|
@ -417,7 +416,6 @@ gen_item_keys!(
|
|||
|
||||
[TagType::APE, APE_MAP],
|
||||
|
||||
#[cfg(feature = "id3v2")]
|
||||
[TagType::ID3v2, ID3V2_MAP],
|
||||
|
||||
[TagType::MP4ilst, ILST_MAP],
|
||||
|
|
|
@ -5,8 +5,8 @@ use crate::tag::{Tag, TagType};
|
|||
use crate::{aac, ape, flac, iff, mpeg, wavpack};
|
||||
|
||||
use crate::id3::v1::tag::Id3v1TagRef;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::{self, tag::Id3v2TagRef, ID3v2TagFlags};
|
||||
use crate::id3::v2::tag::Id3v2TagRef;
|
||||
use crate::id3::v2::{self, ID3v2TagFlags};
|
||||
use crate::mp4::Ilst;
|
||||
use crate::ogg::tag::{create_vorbis_comments_ref, VorbisCommentsRef};
|
||||
use ape::tag::ApeTagRef;
|
||||
|
@ -45,7 +45,6 @@ pub(crate) fn dump_tag<W: Write>(tag: &Tag, writer: &mut W) -> Result<()> {
|
|||
}
|
||||
.dump_to(writer),
|
||||
TagType::ID3v1 => Into::<Id3v1TagRef<'_>>::into(tag).dump_to(writer),
|
||||
#[cfg(feature = "id3v2")]
|
||||
TagType::ID3v2 => Id3v2TagRef {
|
||||
flags: ID3v2TagFlags::default(),
|
||||
frames: v2::tag::tag_frames(tag),
|
||||
|
|
Loading…
Reference in a new issue