diff --git a/src/aac/read.rs b/src/aac/read.rs index 07955899..577e5d2f 100644 --- a/src/aac/read.rs +++ b/src/aac/read.rs @@ -1,8 +1,8 @@ use super::header::{ADTSHeader, HEADER_MASK}; use super::AacFile; use crate::error::Result; +use crate::id3::v2::header::Id3v2Header; use crate::id3::v2::read::parse_id3v2; -use crate::id3::v2::read_id3v2_header; 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}; @@ -43,7 +43,7 @@ where // Seek back to read the tag in full reader.seek(SeekFrom::Current(-4))?; - let header = read_id3v2_header(reader)?; + let header = Id3v2Header::parse(reader)?; let skip_footer = header.flags.footer; stream_len -= u64::from(header.size); diff --git a/src/id3/mod.rs b/src/id3/mod.rs index 1342bb67..9651220e 100644 --- a/src/id3/mod.rs +++ b/src/id3/mod.rs @@ -8,7 +8,7 @@ pub mod v2; use crate::error::{ErrorKind, LoftyError, Result}; use crate::macros::try_vec; -use v2::{read_id3v2_header, Id3v2Header}; +use v2::header::Id3v2Header; use std::io::{Read, Seek, SeekFrom}; use std::ops::Neg; @@ -92,7 +92,7 @@ where let mut header = None; let mut id3v2 = None; - if let Ok(id3v2_header) = read_id3v2_header(data) { + if let Ok(id3v2_header) = Id3v2Header::parse(data) { if read { let mut tag = try_vec![0; id3v2_header.size as usize]; data.read_exact(&mut tag)?; diff --git a/src/id3/v2/flags.rs b/src/id3/v2/flags.rs deleted file mode 100644 index e86f3832..00000000 --- a/src/id3/v2/flags.rs +++ /dev/null @@ -1,23 +0,0 @@ -use super::restrictions::TagRestrictions; - -/// Flags that apply to the entire tag -#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] -#[allow(clippy::struct_excessive_bools)] -pub struct Id3v2TagFlags { - /// Whether or not all frames are unsynchronised. See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) - pub unsynchronisation: bool, - /// Indicates if the tag is in an experimental stage - pub experimental: bool, - /// Indicates that the tag includes a footer - /// - /// A footer will be created if the tag is written - pub footer: bool, - /// Whether or not to include a CRC-32 in the extended header - /// - /// This is calculated if the tag is written - pub crc: bool, - /// Restrictions on the tag, written in the extended header - /// - /// In addition to being setting this flag, all restrictions must be provided. See [`TagRestrictions`] - pub restrictions: Option, -} diff --git a/src/id3/v2/frame/content.rs b/src/id3/v2/frame/content.rs index 9f8d5a63..e7607356 100644 --- a/src/id3/v2/frame/content.rs +++ b/src/id3/v2/frame/content.rs @@ -1,11 +1,11 @@ use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::frame::FrameValue; +use crate::id3::v2::header::Id3v2Version; use crate::id3::v2::items::{ AttachedPictureFrame, CommentFrame, EventTimingCodesFrame, ExtendedTextFrame, ExtendedUrlFrame, KeyValueFrame, OwnershipFrame, Popularimeter, PrivateFrame, RelativeVolumeAdjustmentFrame, TextInformationFrame, UniqueFileIdentifierFrame, UnsynchronizedTextFrame, UrlLinkFrame, }; -use crate::id3::v2::Id3v2Version; use crate::macros::err; use crate::probe::ParsingMode; use crate::util::text::TextEncoding; diff --git a/src/id3/v2/frame/mod.rs b/src/id3/v2/frame/mod.rs index b203157e..7c4ef30e 100644 --- a/src/id3/v2/frame/mod.rs +++ b/src/id3/v2/frame/mod.rs @@ -3,13 +3,13 @@ mod header; pub(super) mod id; pub(super) mod read; +use super::header::Id3v2Version; use super::items::{ AttachedPictureFrame, CommentFrame, EventTimingCodesFrame, ExtendedTextFrame, ExtendedUrlFrame, KeyValueFrame, OwnershipFrame, Popularimeter, PrivateFrame, RelativeVolumeAdjustmentFrame, TextInformationFrame, UniqueFileIdentifierFrame, UnsynchronizedTextFrame, UrlLinkFrame, }; use super::util::upgrade::{upgrade_v2, upgrade_v3}; -use super::Id3v2Version; use crate::error::{ErrorKind, Id3v2Error, Id3v2ErrorKind, LoftyError, Result}; use crate::tag::item::{ItemKey, ItemValue, TagItem}; use crate::tag::TagType; diff --git a/src/id3/v2/frame/read.rs b/src/id3/v2/frame/read.rs index 4ef3faab..0351d07c 100644 --- a/src/id3/v2/frame/read.rs +++ b/src/id3/v2/frame/read.rs @@ -2,8 +2,9 @@ use super::header::{parse_header, parse_v2_header}; use super::Frame; 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, Id3v2Version}; +use crate::id3::v2::{FrameFlags, FrameId, FrameValue}; use crate::macros::try_vec; use crate::probe::ParsingMode; diff --git a/src/id3/v2/header.rs b/src/id3/v2/header.rs new file mode 100644 index 00000000..287c1fac --- /dev/null +++ b/src/id3/v2/header.rs @@ -0,0 +1,141 @@ +use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; +use crate::id3::v2::restrictions::TagRestrictions; +use crate::id3::v2::util::synchsafe::SynchsafeInteger; +use crate::macros::err; + +use std::io::Read; + +use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; + +/// The ID3v2 version +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum Id3v2Version { + /// ID3v2.2 + V2, + /// ID3v2.3 + V3, + /// ID3v2.4 + V4, +} + +/// Flags that apply to the entire tag +#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] +#[allow(clippy::struct_excessive_bools)] +pub struct Id3v2TagFlags { + /// Whether or not all frames are unsynchronised. See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) + pub unsynchronisation: bool, + /// Indicates if the tag is in an experimental stage + pub experimental: bool, + /// Indicates that the tag includes a footer + /// + /// A footer will be created if the tag is written + pub footer: bool, + /// Whether or not to include a CRC-32 in the extended header + /// + /// This is calculated if the tag is written + pub crc: bool, + /// Restrictions on the tag, written in the extended header + /// + /// In addition to being setting this flag, all restrictions must be provided. See [`TagRestrictions`] + pub restrictions: Option, +} + +#[derive(Copy, Clone, Debug)] +pub(crate) struct Id3v2Header { + pub version: Id3v2Version, + pub flags: Id3v2TagFlags, + pub size: u32, + pub extended_size: u32, +} + +impl Id3v2Header { + pub(crate) fn parse(bytes: &mut R) -> Result + where + R: Read, + { + let mut header = [0; 10]; + bytes.read_exact(&mut header)?; + + if &header[..3] != b"ID3" { + err!(FakeTag); + } + + // Version is stored as [major, minor], but here we don't care about minor revisions unless there's an error. + let version = match header[3] { + 2 => Id3v2Version::V2, + 3 => Id3v2Version::V3, + 4 => Id3v2Version::V4, + major => { + return Err( + Id3v2Error::new(Id3v2ErrorKind::BadId3v2Version(major, header[4])).into(), + ) + }, + }; + + let flags = header[5]; + + // Compression was a flag only used in ID3v2.2 (bit 2). + // At the time the ID3v2.2 specification was written, a compression scheme wasn't decided. + // The spec recommends just ignoring the tag in this case. + if version == Id3v2Version::V2 && flags & 0x40 == 0x40 { + return Err(Id3v2Error::new(Id3v2ErrorKind::V2Compression).into()); + } + + let mut flags_parsed = Id3v2TagFlags { + unsynchronisation: flags & 0x80 == 0x80, + experimental: (version == Id3v2Version::V4 || version == Id3v2Version::V3) + && flags & 0x20 == 0x20, + footer: (version == Id3v2Version::V4 || version == Id3v2Version::V3) + && flags & 0x10 == 0x10, + crc: false, // Retrieved later if applicable + restrictions: None, // Retrieved later if applicable + }; + + let size = BigEndian::read_u32(&header[6..]).unsynch(); + let mut extended_size = 0; + + let extended_header = + (version == Id3v2Version::V4 || version == Id3v2Version::V3) && flags & 0x40 == 0x40; + + if extended_header { + extended_size = bytes.read_u32::()?.unsynch(); + + if extended_size < 6 { + return Err(Id3v2Error::new(Id3v2ErrorKind::BadExtendedHeaderSize).into()); + } + + // Useless byte since there's only 1 byte for flags + let _num_flag_bytes = bytes.read_u8()?; + + let extended_flags = bytes.read_u8()?; + + // The only flags we care about here are the CRC and restrictions + + if extended_flags & 0x20 == 0x20 { + flags_parsed.crc = true; + + // We don't care about the existing CRC (5) or its length byte (1) + let mut crc = [0; 6]; + bytes.read_exact(&mut crc)?; + } + + if extended_flags & 0x10 == 0x10 { + // We don't care about the length byte, it is always 1 + let _data_length = bytes.read_u8()?; + + flags_parsed.restrictions = Some(TagRestrictions::from_byte(bytes.read_u8()?)); + } + } + + if extended_size > 0 && extended_size >= size { + return Err(Id3v2Error::new(Id3v2ErrorKind::BadExtendedHeaderSize).into()); + } + + Ok(Id3v2Header { + version, + flags: flags_parsed, + size, + extended_size, + }) + } +} diff --git a/src/id3/v2/items/attached_picture_frame.rs b/src/id3/v2/items/attached_picture_frame.rs index 8f690f01..969515ec 100644 --- a/src/id3/v2/items/attached_picture_frame.rs +++ b/src/id3/v2/items/attached_picture_frame.rs @@ -1,5 +1,5 @@ use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::macros::err; use crate::picture::{MimeType, Picture, PictureType}; use crate::util::text::{encode_text, TextEncoding}; diff --git a/src/id3/v2/items/extended_text_frame.rs b/src/id3/v2/items/extended_text_frame.rs index 87188c40..eb684ed2 100644 --- a/src/id3/v2/items/extended_text_frame.rs +++ b/src/id3/v2/items/extended_text_frame.rs @@ -1,6 +1,6 @@ use crate::error::{Id3v2Error, Id3v2ErrorKind, LoftyError, Result}; use crate::id3::v2::frame::content::verify_encoding; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::util::text::{decode_text, encode_text, read_to_terminator, utf16_decode, TextEncoding}; use std::hash::{Hash, Hasher}; diff --git a/src/id3/v2/items/extended_url_frame.rs b/src/id3/v2/items/extended_url_frame.rs index 5dff8915..d37b5969 100644 --- a/src/id3/v2/items/extended_url_frame.rs +++ b/src/id3/v2/items/extended_url_frame.rs @@ -1,6 +1,6 @@ use crate::error::Result; use crate::id3::v2::frame::content::verify_encoding; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::util::text::{decode_text, encode_text, TextEncoding}; use std::hash::{Hash, Hasher}; diff --git a/src/id3/v2/items/key_value_frame.rs b/src/id3/v2/items/key_value_frame.rs index 6a771f90..53a15e29 100644 --- a/src/id3/v2/items/key_value_frame.rs +++ b/src/id3/v2/items/key_value_frame.rs @@ -1,6 +1,6 @@ use crate::error::Result; use crate::id3::v2::frame::content::verify_encoding; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::util::text::{decode_text, encode_text, TextEncoding}; use byteorder::ReadBytesExt; diff --git a/src/id3/v2/items/language_frame.rs b/src/id3/v2/items/language_frame.rs index 33e5f082..baf4f32e 100644 --- a/src/id3/v2/items/language_frame.rs +++ b/src/id3/v2/items/language_frame.rs @@ -1,6 +1,6 @@ use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::frame::content::verify_encoding; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::util::text::{decode_text, encode_text, TextEncoding}; use std::hash::{Hash, Hasher}; diff --git a/src/id3/v2/items/text_information_frame.rs b/src/id3/v2/items/text_information_frame.rs index 6209c31e..82ab65f0 100644 --- a/src/id3/v2/items/text_information_frame.rs +++ b/src/id3/v2/items/text_information_frame.rs @@ -1,6 +1,6 @@ use crate::error::Result; use crate::id3::v2::frame::content::verify_encoding; -use crate::id3::v2::Id3v2Version; +use crate::id3::v2::header::Id3v2Version; use crate::util::text::{decode_text, encode_text, TextEncoding}; use byteorder::ReadBytesExt; diff --git a/src/id3/v2/mod.rs b/src/id3/v2/mod.rs index f220d05a..68ddd965 100644 --- a/src/id3/v2/mod.rs +++ b/src/id3/v2/mod.rs @@ -7,8 +7,8 @@ //! * [`Id3v2Tag`] //! * [`Frame`] -mod flags; mod frame; +pub(crate) mod header; mod items; pub(crate) mod read; mod restrictions; @@ -16,17 +16,9 @@ pub(crate) mod tag; pub mod util; pub(crate) mod write; -use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; -use crate::macros::err; -use util::synchsafe::SynchsafeInteger; - -use std::io::Read; - -use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; - // Exports -pub use flags::Id3v2TagFlags; +pub use header::{Id3v2TagFlags, Id3v2Version}; pub use util::upgrade::{upgrade_v2, upgrade_v3}; pub use tag::Id3v2Tag; @@ -39,110 +31,3 @@ pub use frame::{Frame, FrameFlags, FrameValue}; pub use restrictions::{ ImageSizeRestrictions, TagRestrictions, TagSizeRestrictions, TextSizeRestrictions, }; - -/// The ID3v2 version -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum Id3v2Version { - /// ID3v2.2 - V2, - /// ID3v2.3 - V3, - /// ID3v2.4 - V4, -} - -#[derive(Copy, Clone, Debug)] -pub(crate) struct Id3v2Header { - pub version: Id3v2Version, - pub flags: Id3v2TagFlags, - pub size: u32, - pub extended_size: u32, -} - -pub(crate) fn read_id3v2_header(bytes: &mut R) -> Result -where - R: Read, -{ - let mut header = [0; 10]; - bytes.read_exact(&mut header)?; - - if &header[..3] != b"ID3" { - err!(FakeTag); - } - - // Version is stored as [major, minor], but here we don't care about minor revisions unless there's an error. - let version = match header[3] { - 2 => Id3v2Version::V2, - 3 => Id3v2Version::V3, - 4 => Id3v2Version::V4, - major => { - return Err(Id3v2Error::new(Id3v2ErrorKind::BadId3v2Version(major, header[4])).into()) - }, - }; - - let flags = header[5]; - - // Compression was a flag only used in ID3v2.2 (bit 2). - // At the time the ID3v2.2 specification was written, a compression scheme wasn't decided. - // The spec recommends just ignoring the tag in this case. - if version == Id3v2Version::V2 && flags & 0x40 == 0x40 { - return Err(Id3v2Error::new(Id3v2ErrorKind::V2Compression).into()); - } - - let mut flags_parsed = Id3v2TagFlags { - unsynchronisation: flags & 0x80 == 0x80, - experimental: (version == Id3v2Version::V4 || version == Id3v2Version::V3) - && flags & 0x20 == 0x20, - footer: (version == Id3v2Version::V4 || version == Id3v2Version::V3) - && flags & 0x10 == 0x10, - crc: false, // Retrieved later if applicable - restrictions: None, // Retrieved later if applicable - }; - - let size = BigEndian::read_u32(&header[6..]).unsynch(); - let mut extended_size = 0; - - let extended_header = - (version == Id3v2Version::V4 || version == Id3v2Version::V3) && flags & 0x40 == 0x40; - - if extended_header { - extended_size = bytes.read_u32::()?.unsynch(); - - if extended_size < 6 { - return Err(Id3v2Error::new(Id3v2ErrorKind::BadExtendedHeaderSize).into()); - } - - // Useless byte since there's only 1 byte for flags - let _num_flag_bytes = bytes.read_u8()?; - - let extended_flags = bytes.read_u8()?; - - // The only flags we care about here are the CRC and restrictions - - if extended_flags & 0x20 == 0x20 { - flags_parsed.crc = true; - - // We don't care about the existing CRC (5) or its length byte (1) - let mut crc = [0; 6]; - bytes.read_exact(&mut crc)?; - } - - if extended_flags & 0x10 == 0x10 { - // We don't care about the length byte, it is always 1 - let _data_length = bytes.read_u8()?; - - flags_parsed.restrictions = Some(TagRestrictions::from_byte(bytes.read_u8()?)); - } - } - - if extended_size > 0 && extended_size >= size { - return Err(Id3v2Error::new(Id3v2ErrorKind::BadExtendedHeaderSize).into()); - } - - Ok(Id3v2Header { - version, - flags: flags_parsed, - size, - extended_size, - }) -} diff --git a/src/id3/v2/read.rs b/src/id3/v2/read.rs index 7a2ce85c..96e2828a 100644 --- a/src/id3/v2/read.rs +++ b/src/id3/v2/read.rs @@ -1,6 +1,6 @@ use super::frame::read::ParsedFrame; +use super::header::Id3v2Header; use super::tag::Id3v2Tag; -use super::Id3v2Header; use crate::error::{Id3v2Error, Id3v2ErrorKind, Result}; use crate::id3::v2::util::synchsafe::UnsynchronizedStream; use crate::probe::ParsingMode; @@ -74,18 +74,18 @@ where #[test] fn zero_size_id3v2() { - use crate::id3::v2::read_id3v2_header; + 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()); - let header = read_id3v2_header(&mut f).unwrap(); + let header = Id3v2Header::parse(&mut f).unwrap(); assert!(parse_id3v2(&mut f, header, ParsingMode::Strict).is_ok()); } #[test] fn bad_frame_id_relaxed_id3v2() { - use crate::id3::v2::read_id3v2_header; + use crate::id3::v2::header::Id3v2Header; use crate::{Accessor, ParsingMode, TagExt}; use std::io::Cursor; @@ -94,7 +94,7 @@ fn bad_frame_id_relaxed_id3v2() { let mut f = Cursor::new( std::fs::read("tests/tags/assets/id3v2/bad_frame_otherwise_valid.id3v24").unwrap(), ); - let header = read_id3v2_header(&mut f).unwrap(); + let header = Id3v2Header::parse(&mut f).unwrap(); let id3v2 = parse_id3v2(&mut f, header, ParsingMode::Relaxed); assert!(id3v2.is_ok()); diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index 0a6133b1..5a080040 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -1,7 +1,6 @@ -use super::flags::Id3v2TagFlags; use super::frame::id::FrameId; use super::frame::{Frame, FrameFlags, FrameValue, EMPTY_CONTENT_DESCRIPTOR, UNKNOWN_LANGUAGE}; -use super::Id3v2Version; +use super::header::{Id3v2TagFlags, Id3v2Version}; use crate::error::{LoftyError, Result}; use crate::id3::v2::frame::{FrameRef, MUSICBRAINZ_UFID_OWNER}; use crate::id3::v2::items::{ @@ -1223,13 +1222,13 @@ mod tests { use std::borrow::Cow; use crate::id3::v2::frame::MUSICBRAINZ_UFID_OWNER; + use crate::id3::v2::header::{Id3v2Header, Id3v2Version}; use crate::id3::v2::items::{ExtendedUrlFrame, Popularimeter, UniqueFileIdentifierFrame}; use crate::id3::v2::tag::{filter_comment_frame_by_description, new_text_frame}; use crate::id3::v2::util::pairs::DEFAULT_NUMBER_IN_PAIR; use crate::id3::v2::{ - read_id3v2_header, AttachedPictureFrame, CommentFrame, ExtendedTextFrame, Frame, - FrameFlags, FrameId, FrameValue, Id3v2Tag, Id3v2Version, TextInformationFrame, - UrlLinkFrame, + AttachedPictureFrame, CommentFrame, ExtendedTextFrame, Frame, FrameFlags, FrameId, + FrameValue, Id3v2Tag, TextInformationFrame, UrlLinkFrame, }; use crate::tag::utils::test_utils::read_path; use crate::util::text::TextEncoding; @@ -1245,7 +1244,7 @@ mod tests { let mut reader = std::io::Cursor::new(&tag_bytes[..]); - let header = read_id3v2_header(&mut reader).unwrap(); + let header = Id3v2Header::parse(&mut reader).unwrap(); crate::id3::v2::read::parse_id3v2(&mut reader, header, ParsingMode::Strict).unwrap() } @@ -1356,7 +1355,7 @@ mod tests { let temp_reader = &mut &*writer; - let temp_header = read_id3v2_header(temp_reader).unwrap(); + let temp_header = Id3v2Header::parse(temp_reader).unwrap(); let temp_parsed_tag = crate::id3::v2::read::parse_id3v2(temp_reader, temp_header, ParsingMode::Strict) .unwrap(); @@ -1608,7 +1607,7 @@ mod tests { let mut reader = &mut &writer[..]; - let header = read_id3v2_header(&mut reader).unwrap(); + let header = Id3v2Header::parse(&mut reader).unwrap(); assert!(crate::id3::v2::read::parse_id3v2(reader, header, ParsingMode::Strict).is_ok()); assert_eq!(writer[3..10], writer[writer.len() - 7..]) @@ -1633,7 +1632,7 @@ mod tests { let mut reader = &mut &writer[..]; - let header = read_id3v2_header(&mut reader).unwrap(); + let header = Id3v2Header::parse(&mut reader).unwrap(); let tag = crate::id3::v2::read::parse_id3v2(reader, header, ParsingMode::Strict).unwrap(); assert_eq!(tag.len(), 1); @@ -1950,7 +1949,7 @@ mod tests { // And verify we can reread the tag let mut reader = std::io::Cursor::new(&content[..]); - let header = read_id3v2_header(&mut reader).unwrap(); + let header = Id3v2Header::parse(&mut reader).unwrap(); let reparsed = crate::id3::v2::read::parse_id3v2(&mut reader, header, ParsingMode::Strict).unwrap(); diff --git a/src/iff/chunk.rs b/src/iff/chunk.rs index 2045864d..a002721d 100644 --- a/src/iff/chunk.rs +++ b/src/iff/chunk.rs @@ -96,14 +96,14 @@ impl Chunks { where R: Read + Seek, { + use crate::id3::v2::header::Id3v2Header; use crate::id3::v2::read::parse_id3v2; - use crate::id3::v2::read_id3v2_header; let content = self.content(data)?; let reader = &mut &*content; - let header = read_id3v2_header(reader)?; + let header = Id3v2Header::parse(reader)?; let id3v2 = parse_id3v2(reader, header, parse_mode)?; // Skip over the footer diff --git a/src/mpeg/read.rs b/src/mpeg/read.rs index 608d287d..8c9ef167 100644 --- a/src/mpeg/read.rs +++ b/src/mpeg/read.rs @@ -2,8 +2,8 @@ use super::header::{cmp_header, search_for_frame_sync, Header, HeaderCmpResult, use super::{MpegFile, MpegProperties}; use crate::ape::header::read_ape_header; use crate::error::Result; +use crate::id3::v2::header::Id3v2Header; use crate::id3::v2::read::parse_id3v2; -use crate::id3::v2::read_id3v2_header; use crate::id3::{find_id3v1, find_lyrics3v2, ID3FindResults}; use crate::macros::{decode_err, err}; use crate::mpeg::header::HEADER_MASK; @@ -36,7 +36,7 @@ where // Seek back to read the tag in full reader.seek(SeekFrom::Current(-4))?; - let header = read_id3v2_header(reader)?; + let header = Id3v2Header::parse(reader)?; let skip_footer = header.flags.footer; let id3v2 = parse_id3v2(reader, header, parse_options.parsing_mode)?;