Cleanup; Make use of doc_cfg

This commit is contained in:
Serial 2022-02-04 00:59:20 -05:00
parent 4e3cf7a882
commit d13f01d215
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
22 changed files with 273 additions and 230 deletions

View file

@ -54,4 +54,5 @@ name = "create_tag"
harness = false harness = false
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true
rustdoc-args = ["--cfg", "docsrs"]

58
src/ape/header.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::error::{FileDecodingError, Result};
use crate::types::file::FileType;
use std::io::{Read, Seek, SeekFrom};
use std::ops::Neg;
use byteorder::{LittleEndian, ReadBytesExt};
#[derive(Copy, Clone)]
pub(crate) struct ApeHeader {
pub(crate) size: u32,
#[cfg(feature = "ape")]
pub(crate) item_count: u32,
}
pub(crate) fn read_ape_header<R>(data: &mut R, footer: bool) -> Result<ApeHeader>
where
R: Read + Seek,
{
let version = data.read_u32::<LittleEndian>()?;
let mut size = data.read_u32::<LittleEndian>()?;
if size < 32 {
// If the size is < 32, something went wrong during encoding
// The size includes the footer and all items
return Err(
FileDecodingError::new(FileType::APE, "APE tag has an invalid size (< 32)").into(),
);
}
#[cfg(feature = "ape")]
let item_count = data.read_u32::<LittleEndian>()?;
#[cfg(not(feature = "ape"))]
data.seek(SeekFrom::Current(4))?;
if footer {
// No point in reading the rest of the footer, just seek back to the end of the header
data.seek(SeekFrom::Current(i64::from(size - 12).neg()))?;
} else {
// There are 12 bytes remaining in the header
// Flags (4)
// Reserved (8)
data.seek(SeekFrom::Current(12))?;
}
// Version 1 doesn't include a header
if version == 2000 {
size += 32
}
Ok(ApeHeader {
size,
#[cfg(feature = "ape")]
item_count,
})
}

View file

@ -6,30 +6,36 @@
//! this tag will be read, but **cannot** be written. The only tags allowed by spec are `APEv1/2` and //! this tag will be read, but **cannot** be written. The only tags allowed by spec are `APEv1/2` and
//! `ID3v1`. //! `ID3v1`.
pub(crate) mod constants; pub(crate) mod constants;
pub(crate) mod header;
mod properties; mod properties;
mod read; mod read;
pub(crate) mod tag;
pub(crate) mod write; pub(crate) mod write;
pub use crate::ape::properties::ApeProperties;
#[cfg(feature = "ape")]
pub use {
crate::types::picture::APE_PICTURE_TYPES,
tag::{ape_tag::ApeTag, item::ApeItem},
};
use crate::error::Result; use crate::error::Result;
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
use std::io::{Read, Seek}; use std::io::{Read, Seek};
// Exports
crate::macros::feature_locked! {
#![cfg(feature = "ape")]
pub(crate) mod tag;
pub use tag::ape_tag::ApeTag;
pub use tag::item::ApeItem;
pub use crate::types::picture::APE_PICTURE_TYPES;
}
pub use properties::ApeProperties;
/// An APE file /// An APE file
pub struct ApeFile { pub struct ApeFile {
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
@ -106,12 +112,14 @@ impl AudioFile for ApeFile {
} }
impl ApeFile { impl ApeFile {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "id3v2")]; #[cfg(feature = "id3v2")]
id3v2_tag, Id3v2Tag; id3v2_tag, Id3v2Tag;
#[cfg(feature = "id3v1")];
#[cfg(feature = "id3v1")]
id3v1_tag, Id3v1Tag; id3v1_tag, Id3v1Tag;
#[cfg(feature = "ape")];
#[cfg(feature = "ape")]
ape_tag, ApeTag ape_tag, ApeTag
} }
} }

View file

@ -1,8 +1,8 @@
use super::constants::APE_PREAMBLE; use super::constants::APE_PREAMBLE;
use super::header::read_ape_header;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
use super::tag::{ape_tag::ApeTag, read::read_ape_tag}; use super::tag::{ape_tag::ApeTag, read::read_ape_tag};
use super::{ApeFile, ApeProperties}; use super::{ApeFile, ApeProperties};
use crate::ape::tag::read_ape_header;
use crate::error::{FileDecodingError, Result}; use crate::error::{FileDecodingError, Result};
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;

View file

@ -278,8 +278,8 @@ impl<'a> Into<ApeTagRef<'a>> for &'a ApeTag {
mod tests { mod tests {
use crate::ape::{ApeItem, ApeTag}; use crate::ape::{ApeItem, ApeTag};
use crate::{ItemValue, Tag, TagIO, TagType}; use crate::{ItemValue, Tag, TagIO, TagType};
use crate::ape::header::read_ape_header;
use crate::ape::tag::read_ape_header;
use std::io::Cursor; use std::io::Cursor;
#[test] #[test]

View file

@ -1,67 +1,4 @@
#[cfg(feature = "ape")]
pub(crate) mod ape_tag; pub(crate) mod ape_tag;
#[cfg(feature = "ape")]
pub(crate) mod item; pub(crate) mod item;
#[cfg(feature = "ape")]
pub(crate) mod read; pub(crate) mod read;
#[cfg(feature = "ape")] mod write;
mod write;
use crate::error::{FileDecodingError, Result};
use crate::types::file::FileType;
use std::io::{Read, Seek, SeekFrom};
use std::ops::Neg;
use byteorder::{LittleEndian, ReadBytesExt};
#[derive(Copy, Clone)]
pub(crate) struct ApeHeader {
pub(crate) size: u32,
#[cfg(feature = "ape")]
pub(crate) item_count: u32,
}
pub(crate) fn read_ape_header<R>(data: &mut R, footer: bool) -> Result<ApeHeader>
where
R: Read + Seek,
{
let version = data.read_u32::<LittleEndian>()?;
let mut size = data.read_u32::<LittleEndian>()?;
if size < 32 {
// If the size is < 32, something went wrong during encoding
// The size includes the footer and all items
return Err(
FileDecodingError::new(FileType::APE, "APE tag has an invalid size (< 32)").into(),
);
}
#[cfg(feature = "ape")]
let item_count = data.read_u32::<LittleEndian>()?;
#[cfg(not(feature = "ape"))]
data.seek(SeekFrom::Current(4))?;
if footer {
// No point in reading the rest of the footer, just seek back to the end of the header
data.seek(SeekFrom::Current(i64::from(size - 12).neg()))?;
} else {
// There are 12 bytes remaining in the header
// Flags (4)
// Reserved (8)
data.seek(SeekFrom::Current(12))?;
}
// Version 1 doesn't include a header
if version == 2000 {
size += 32
}
Ok(ApeHeader {
size,
#[cfg(feature = "ape")]
item_count,
})
}

View file

@ -1,6 +1,6 @@
use super::ape_tag::ApeTag; use super::ape_tag::ApeTag;
use super::item::ApeItem; use super::item::ApeItem;
use super::ApeHeader; use crate::ape::header::ApeHeader;
use crate::ape::constants::INVALID_KEYS; use crate::ape::constants::INVALID_KEYS;
use crate::error::{FileDecodingError, Result}; use crate::error::{FileDecodingError, Result};
use crate::types::file::FileType; use crate::types::file::FileType;

View file

@ -6,11 +6,11 @@ use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use crate::probe::Probe; use crate::probe::Probe;
use crate::types::file::FileType; use crate::types::file::FileType;
use crate::types::item::ItemValueRef; use crate::types::item::ItemValueRef;
use crate::ape::header::read_ape_header;
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write}; use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use crate::ape::tag::read_ape_header;
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
#[allow(clippy::shadow_unrelated)] #[allow(clippy::shadow_unrelated)]

View file

@ -15,12 +15,15 @@
//! A track number of 0 will be treated as an empty field. //! A track number of 0 will be treated as an empty field.
//! Additionally, there is no track total field. //! Additionally, there is no track total field.
pub(crate) mod constants; pub(crate) mod constants;
#[cfg(feature = "id3v1")]
pub(crate) mod read;
#[cfg(feature = "id3v1")]
pub(crate) mod tag;
#[cfg(feature = "id3v1")]
pub(crate) mod write;
#[cfg(feature = "id3v1")] crate::macros::feature_locked! {
pub use crate::id3::v1::{constants::GENRES, tag::Id3v1Tag}; #![cfg(feature = "id3v1")]
pub use constants::GENRES;
pub(crate) mod tag;
pub use tag::Id3v1Tag;
pub(crate) mod read;
pub(crate) mod write;
}

View file

@ -8,51 +8,52 @@
//! * [Frame] //! * [Frame]
mod flags; mod flags;
#[cfg(feature = "id3v2")]
mod frame;
#[cfg(feature = "id3v2")]
mod items;
#[cfg(feature = "id3v2")]
pub(crate) mod read;
#[cfg(feature = "id3v2_restrictions")]
mod restrictions;
#[cfg(feature = "id3v2")]
pub(crate) mod tag;
pub(crate) mod util; pub(crate) mod util;
#[cfg(feature = "id3v2")]
pub(crate) mod write;
#[cfg(feature = "id3v2_restrictions")]
pub use restrictions::{
ImageSizeRestrictions, TagRestrictions, TagSizeRestrictions, TextSizeRestrictions,
};
#[cfg(feature = "id3v2")]
pub use {
flags::Id3v2TagFlags,
frame::{
content::EncodedTextFrame, content::LanguageFrame, id::FrameID, Frame, FrameFlags,
FrameValue,
},
items::{
encapsulated_object::{GEOBInformation, GeneralEncapsulatedObject},
sync_text::{SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat},
},
tag::Id3v2Tag,
util::{
text_utils::TextEncoding,
upgrade::{upgrade_v2, upgrade_v3},
},
};
#[cfg(not(feature = "id3v2"))]
use flags::Id3v2TagFlags;
use crate::error::{ErrorKind, Id3v2Error, Id3v2ErrorKind, LoftyError, Result}; use crate::error::{ErrorKind, Id3v2Error, Id3v2ErrorKind, LoftyError, Result};
use crate::macros::feature_locked;
use std::io::Read; use std::io::Read;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
feature_locked! {
#![cfg(feature = "id3v2")]
pub use flags::Id3v2TagFlags;
pub use util::text_utils::TextEncoding;
pub use util::upgrade::{upgrade_v2, upgrade_v3};
pub(crate) mod tag;
pub use tag::Id3v2Tag;
mod items;
pub use items::encapsulated_object::{GEOBInformation, GeneralEncapsulatedObject};
pub use items::sync_text::{SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat};
mod frame;
pub use frame::content::{EncodedTextFrame, LanguageFrame};
pub use frame::id::FrameID;
pub use frame::Frame;
pub use frame::FrameFlags;
pub use frame::FrameValue;
pub(crate) mod read;
pub(crate) mod write;
}
feature_locked! {
#![cfg(feature = "id3v2_restrictions")]
mod restrictions;
pub use restrictions::{
ImageSizeRestrictions, TagRestrictions, TagSizeRestrictions, TextSizeRestrictions,
};
}
#[cfg(not(feature = "id3v2"))]
use flags::Id3v2TagFlags;
#[derive(PartialEq, Debug, Clone, Copy)] #[derive(PartialEq, Debug, Clone, Copy)]
/// The ID3v2 version /// The ID3v2 version
pub enum Id3v2Version { pub enum Id3v2Version {

View file

@ -1,21 +1,23 @@
mod properties; mod properties;
mod read; mod read;
#[cfg(feature = "aiff_text_chunks")]
pub(crate) mod tag;
pub(crate) mod write; pub(crate) mod write;
use crate::error::Result; use crate::error::Result;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
#[cfg(feature = "aiff_text_chunks")]
use tag::AiffTextChunks;
use std::io::{Read, Seek}; use std::io::{Read, Seek};
crate::macros::feature_locked! {
#![cfg(feature = "aiff_text_chunks")]
pub(crate) mod tag;
use tag::AiffTextChunks;
}
/// An AIFF file /// An AIFF file
pub struct AiffFile { pub struct AiffFile {
#[cfg(feature = "aiff_text_chunks")] #[cfg(feature = "aiff_text_chunks")]
@ -83,10 +85,11 @@ impl AudioFile for AiffFile {
} }
impl AiffFile { impl AiffFile {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "id3v2")]; #[cfg(feature = "id3v2")]
id3v2_tag, Id3v2Tag; id3v2_tag, Id3v2Tag;
#[cfg(feature = "aiff_text_chunks")];
#[cfg(feature = "aiff_text_chunks")]
text_chunks, AiffTextChunks text_chunks, AiffTextChunks
} }
} }

View file

@ -3,10 +3,22 @@ pub(crate) mod aiff;
pub(crate) mod chunk; pub(crate) mod chunk;
pub(crate) mod wav; pub(crate) mod wav;
use crate::macros::feature_locked;
// Exports
pub use aiff::AiffFile; pub use aiff::AiffFile;
pub use wav::{WavFile, WavFormat, WavProperties}; pub use wav::{WavFile, WavFormat, WavProperties};
#[cfg(feature = "aiff_text_chunks")] feature_locked! {
pub use aiff::tag::{AiffTextChunks, Comment}; #![cfg(feature = "aiff_text_chunks")]
#[cfg(feature = "riff_info_list")]
pub use wav::tag::RiffInfoList; pub use aiff::tag::AiffTextChunks;
pub use aiff::tag::Comment;
}
feature_locked! {
#![cfg(feature = "riff_info_list")]
pub use wav::tag::RiffInfoList;
}

View file

@ -1,23 +1,26 @@
mod properties; mod properties;
mod read; mod read;
#[cfg(feature = "riff_info_list")]
pub(crate) mod tag;
pub(crate) mod write; pub(crate) mod write;
pub use crate::iff::wav::properties::{WavFormat, WavProperties};
use crate::error::Result; use crate::error::Result;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
#[cfg(feature = "riff_info_list")]
use tag::RiffInfoList;
use std::io::{Read, Seek}; use std::io::{Read, Seek};
crate::macros::feature_locked! {
#![cfg(feature = "riff_info_list")]
pub(crate) mod tag;
use tag::RiffInfoList;
}
// Exports
pub use crate::iff::wav::properties::{WavFormat, WavProperties};
/// A WAV file /// A WAV file
pub struct WavFile { pub struct WavFile {
#[cfg(feature = "riff_info_list")] #[cfg(feature = "riff_info_list")]
@ -86,10 +89,11 @@ impl AudioFile for WavFile {
} }
impl WavFile { impl WavFile {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "id3v2")]; #[cfg(feature = "id3v2")]
id3v2_tag, Id3v2Tag; id3v2_tag, Id3v2Tag;
#[cfg(feature = "riff_info_list")];
#[cfg(feature = "riff_info_list")]
riff_info, RiffInfoList riff_info, RiffInfoList
} }
} }

View file

@ -151,11 +151,13 @@
clippy::tabs_in_doc_comments, clippy::tabs_in_doc_comments,
clippy::len_without_is_empty clippy::len_without_is_empty
)] )]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod ape; pub mod ape;
pub mod error; pub mod error;
pub mod id3; pub mod id3;
pub mod iff; pub mod iff;
pub(crate) mod macros;
pub mod mp3; pub mod mp3;
pub mod mp4; pub mod mp4;
pub mod ogg; pub mod ogg;

45
src/macros.rs Normal file
View file

@ -0,0 +1,45 @@
macro_rules! tag_methods {
(
$(
$(#[cfg($meta:meta)])?
$name:ident,
$ty:ty
);*
) => {
paste::paste! {
$(
$(#[cfg($meta)])?
#[doc = "Gets the [`" $ty "`] if it exists"]
pub fn $name(&self) -> Option<&$ty> {
self.$name.as_ref()
}
$(#[cfg($meta)])?
#[doc = "Gets a mutable reference to the [`" $ty "`] if it exists"]
pub fn [<$name _mut>](&mut self) -> Option<&mut $ty> {
self.$name.as_mut()
}
$(#[cfg($meta)])?
#[doc = "Removes the [`" $ty "`]"]
pub fn [<remove_ $name>](&mut self) {
self.$name = None
}
)*
}
}
}
macro_rules! feature_locked {
(
#![cfg($meta:meta)]
$($item:item)+
) => {
$(
#[cfg($meta)]
$item
)+
}
}
pub(crate) use {feature_locked, tag_methods};

View file

@ -15,7 +15,6 @@ use crate::error::Result;
use crate::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
@ -100,12 +99,14 @@ impl AudioFile for Mp3File {
} }
impl Mp3File { impl Mp3File {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "id3v2")]; #[cfg(feature = "id3v2")]
id3v2_tag, Id3v2Tag; id3v2_tag, Id3v2Tag;
#[cfg(feature = "id3v1")];
#[cfg(feature = "id3v1")]
id3v1_tag, Id3v1Tag; id3v1_tag, Id3v1Tag;
#[cfg(feature = "ape")];
#[cfg(feature = "ape")]
ape_tag, ApeTag ape_tag, ApeTag
} }
} }

View file

@ -1,9 +1,9 @@
use super::header::{search_for_frame_sync, Header, XingHeader}; use super::header::{search_for_frame_sync, Header, XingHeader};
use super::{Mp3File, Mp3Properties}; use super::{Mp3File, Mp3Properties};
use crate::ape::constants::APE_PREAMBLE; use crate::ape::constants::APE_PREAMBLE;
use crate::ape::header::read_ape_header;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
use crate::ape::tag::read::read_ape_tag; use crate::ape::tag::read::read_ape_tag;
use crate::ape::tag::read_ape_header;
use crate::error::{FileDecodingError, Result}; use crate::error::{FileDecodingError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::read::parse_id3v2; use crate::id3::v2::read::parse_id3v2;

View file

@ -4,29 +4,31 @@
//! //!
//! The only supported tag format is [`Ilst`]. //! The only supported tag format is [`Ilst`].
mod atom_info; mod atom_info;
#[cfg(feature = "mp4_ilst")]
pub(crate) mod ilst;
mod moov; mod moov;
mod properties; mod properties;
mod read; mod read;
mod trak; mod trak;
pub use crate::mp4::properties::{Mp4Codec, Mp4Properties}; use crate::error::Result;
#[cfg(feature = "mp4_ilst")]
pub use crate::mp4::{
atom_info::AtomIdent,
ilst::{
atom::{Atom, AtomData},
Ilst,
},
};
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::{FileProperties, Result, TagType}; use crate::types::properties::FileProperties;
use crate::types::tag::TagType;
use std::io::{Read, Seek}; use std::io::{Read, Seek};
// Exports
crate::macros::feature_locked! {
#![cfg(feature = "mp4_ilst")]
pub(crate) mod ilst;
pub use atom_info::AtomIdent;
pub use ilst::atom::{Atom, AtomData};
pub use ilst::Ilst;
}
pub use crate::mp4::properties::{Mp4Codec, Mp4Properties};
/// An MP4 file /// An MP4 file
pub struct Mp4File { pub struct Mp4File {
/// The file format from ftyp's "major brand" (Ex. "M4A ") /// The file format from ftyp's "major brand" (Ex. "M4A ")
@ -97,8 +99,8 @@ impl Mp4File {
} }
impl Mp4File { impl Mp4File {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "mp4_ilst")]; #[cfg(feature = "mp4_ilst")]
ilst, Ilst ilst, Ilst
} }
} }

View file

@ -7,7 +7,6 @@ pub(crate) mod write;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
use super::tag::VorbisComments; use super::tag::VorbisComments;
use crate::error::Result; use crate::error::Result;
use crate::tag_utils::tag_methods;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use crate::types::tag::TagType; use crate::types::tag::TagType;
@ -73,8 +72,8 @@ impl AudioFile for FlacFile {
} }
impl FlacFile { impl FlacFile {
tag_methods! { crate::macros::tag_methods! {
#[cfg(feature = "vorbis_comments")]; #[cfg(feature = "vorbis_comments")]
vorbis_comments, VorbisComments vorbis_comments, VorbisComments
} }
} }

View file

@ -8,32 +8,33 @@ pub(crate) mod flac;
pub(crate) mod opus; pub(crate) mod opus;
pub(crate) mod read; pub(crate) mod read;
pub(crate) mod speex; pub(crate) mod speex;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod tag;
pub(crate) mod vorbis; pub(crate) mod vorbis;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod write;
use crate::error::{FileDecodingError, Result}; use crate::error::{FileDecodingError, Result};
use crate::types::file::FileType; use crate::types::file::FileType;
// Exports
#[cfg(feature = "vorbis_comments")]
pub use crate::ogg::tag::VorbisComments;
pub use crate::ogg::flac::FlacFile;
pub use crate::ogg::opus::properties::OpusProperties;
pub use crate::ogg::opus::OpusFile;
pub use crate::ogg::speex::properties::SpeexProperties;
pub use crate::ogg::speex::SpeexFile;
pub use crate::ogg::vorbis::properties::VorbisProperties;
pub use crate::ogg::vorbis::VorbisFile;
use std::io::{Read, Seek}; use std::io::{Read, Seek};
use ogg_pager::Page; use ogg_pager::Page;
// Exports
crate::macros::feature_locked! {
#![cfg(feature = "vorbis_comments")]
pub(crate) mod write;
pub(crate) mod tag;
pub use tag::VorbisComments;
}
pub use flac::FlacFile;
pub use opus::properties::OpusProperties;
pub use opus::OpusFile;
pub use speex::properties::SpeexProperties;
pub use speex::SpeexFile;
pub use vorbis::properties::VorbisProperties;
pub use vorbis::VorbisFile;
pub(self) fn verify_signature(page: &Page, sig: &[u8]) -> Result<()> { pub(self) fn verify_signature(page: &Page, sig: &[u8]) -> Result<()> {
let sig_len = sig.len(); let sig_len = sig.len();

View file

@ -75,40 +75,6 @@ pub(crate) fn dump_tag<W: Write>(tag: &Tag, writer: &mut W) -> Result<()> {
} }
} }
macro_rules! tag_methods {
(
$(
$(#[$attr:meta])?;
$name:ident,
$ty:ty
);*
) => {
paste::paste! {
$(
$(#[$attr])?
#[doc = "Gets the [`" $ty "`] if it exists"]
pub fn $name(&self) -> Option<&$ty> {
self.$name.as_ref()
}
$(#[$attr])?
#[doc = "Gets a mutable reference to the [`" $ty "`] if it exists"]
pub fn [<$name _mut>](&mut self) -> Option<&mut $ty> {
self.$name.as_mut()
}
$(#[$attr])?
#[doc = "Removes the [`" $ty "`]"]
pub fn [<remove_ $name>](&mut self) {
self.$name = None
}
)*
}
}
}
pub(crate) use tag_methods;
#[cfg(test)] #[cfg(test)]
// Used for tag conversion tests // Used for tag conversion tests
pub(crate) mod test_utils { pub(crate) mod test_utils {

View file

@ -110,7 +110,7 @@ impl MimeType {
} }
} }
/// The picture type /// The picture type, according to ID3v2 APIC
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum PictureType { pub enum PictureType {
@ -141,8 +141,8 @@ pub enum PictureType {
impl PictureType { impl PictureType {
// ID3/OGG specific methods // ID3/OGG specific methods
/// Get a u8 from a `PictureType` according to ID3v2 APIC
#[cfg(any(feature = "id3v2", feature = "vorbis_comments"))] #[cfg(any(feature = "id3v2", feature = "vorbis_comments"))]
/// Get a u8 from a `PictureType` according to ID3v2 APIC
pub fn as_u8(&self) -> u8 { pub fn as_u8(&self) -> u8 {
match self { match self {
Self::Other => 0, Self::Other => 0,
@ -170,8 +170,8 @@ impl PictureType {
} }
} }
/// Get a `PictureType` from a u8 according to ID3v2 APIC
#[cfg(any(feature = "id3v2", feature = "vorbis_comments"))] #[cfg(any(feature = "id3v2", feature = "vorbis_comments"))]
/// Get a `PictureType` from a u8 according to ID3v2 APIC
pub fn from_u8(bytes: u8) -> Self { pub fn from_u8(bytes: u8) -> Self {
match bytes { match bytes {
0 => Self::Other, 0 => Self::Other,
@ -201,8 +201,8 @@ impl PictureType {
// APE specific methods // APE specific methods
/// Get an APE item key from a `PictureType`
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
/// Get an APE item key from a `PictureType`
pub fn as_ape_key(&self) -> Option<&str> { pub fn as_ape_key(&self) -> Option<&str> {
match self { match self {
Self::Other => Some("Cover Art (Other)"), Self::Other => Some("Cover Art (Other)"),
@ -230,8 +230,8 @@ impl PictureType {
} }
} }
/// Get a `PictureType` from an APE item key
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
/// Get a `PictureType` from an APE item key
pub fn from_ape_key(key: &str) -> Self { pub fn from_ape_key(key: &str) -> Self {
match key { match key {
"Cover Art (Other)" => Self::Other, "Cover Art (Other)" => Self::Other,