mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-12 23:47:06 +00:00
Cleanup; Make use of doc_cfg
This commit is contained in:
parent
4e3cf7a882
commit
d13f01d215
22 changed files with 273 additions and 230 deletions
|
@ -54,4 +54,5 @@ name = "create_tag"
|
|||
harness = false
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
58
src/ape/header.rs
Normal file
58
src/ape/header.rs
Normal 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,
|
||||
})
|
||||
}
|
|
@ -6,30 +6,36 @@
|
|||
//! this tag will be read, but **cannot** be written. The only tags allowed by spec are `APEv1/2` and
|
||||
//! `ID3v1`.
|
||||
pub(crate) mod constants;
|
||||
pub(crate) mod header;
|
||||
mod properties;
|
||||
mod read;
|
||||
pub(crate) mod tag;
|
||||
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;
|
||||
#[cfg(feature = "id3v1")]
|
||||
use crate::id3::v1::tag::Id3v1Tag;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::Id3v2Tag;
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::types::file::{AudioFile, FileType, TaggedFile};
|
||||
use crate::types::properties::FileProperties;
|
||||
use crate::types::tag::{Tag, TagType};
|
||||
|
||||
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
|
||||
pub struct ApeFile {
|
||||
#[cfg(feature = "id3v1")]
|
||||
|
@ -106,12 +112,14 @@ impl AudioFile for ApeFile {
|
|||
}
|
||||
|
||||
impl ApeFile {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "id3v2")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag, Id3v2Tag;
|
||||
#[cfg(feature = "id3v1")];
|
||||
|
||||
#[cfg(feature = "id3v1")]
|
||||
id3v1_tag, Id3v1Tag;
|
||||
#[cfg(feature = "ape")];
|
||||
|
||||
#[cfg(feature = "ape")]
|
||||
ape_tag, ApeTag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use super::constants::APE_PREAMBLE;
|
||||
use super::header::read_ape_header;
|
||||
#[cfg(feature = "ape")]
|
||||
use super::tag::{ape_tag::ApeTag, read::read_ape_tag};
|
||||
use super::{ApeFile, ApeProperties};
|
||||
use crate::ape::tag::read_ape_header;
|
||||
use crate::error::{FileDecodingError, Result};
|
||||
#[cfg(feature = "id3v1")]
|
||||
use crate::id3::v1::tag::Id3v1Tag;
|
||||
|
|
|
@ -278,8 +278,8 @@ impl<'a> Into<ApeTagRef<'a>> for &'a ApeTag {
|
|||
mod tests {
|
||||
use crate::ape::{ApeItem, ApeTag};
|
||||
use crate::{ItemValue, Tag, TagIO, TagType};
|
||||
use crate::ape::header::read_ape_header;
|
||||
|
||||
use crate::ape::tag::read_ape_header;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,67 +1,4 @@
|
|||
#[cfg(feature = "ape")]
|
||||
pub(crate) mod ape_tag;
|
||||
#[cfg(feature = "ape")]
|
||||
pub(crate) mod item;
|
||||
#[cfg(feature = "ape")]
|
||||
pub(crate) mod read;
|
||||
#[cfg(feature = "ape")]
|
||||
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,
|
||||
})
|
||||
}
|
||||
mod write;
|
|
@ -1,6 +1,6 @@
|
|||
use super::ape_tag::ApeTag;
|
||||
use super::item::ApeItem;
|
||||
use super::ApeHeader;
|
||||
use crate::ape::header::ApeHeader;
|
||||
use crate::ape::constants::INVALID_KEYS;
|
||||
use crate::error::{FileDecodingError, Result};
|
||||
use crate::types::file::FileType;
|
||||
|
|
|
@ -6,11 +6,11 @@ use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
|
|||
use crate::probe::Probe;
|
||||
use crate::types::file::FileType;
|
||||
use crate::types::item::ItemValueRef;
|
||||
use crate::ape::header::read_ape_header;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||
|
||||
use crate::ape::tag::read_ape_header;
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
#[allow(clippy::shadow_unrelated)]
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
//! A track number of 0 will be treated as an empty field.
|
||||
//! Additionally, there is no track total field.
|
||||
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")]
|
||||
pub use crate::id3::v1::{constants::GENRES, tag::Id3v1Tag};
|
||||
crate::macros::feature_locked! {
|
||||
#![cfg(feature = "id3v1")]
|
||||
|
||||
pub use constants::GENRES;
|
||||
|
||||
pub(crate) mod tag;
|
||||
pub use tag::Id3v1Tag;
|
||||
|
||||
pub(crate) mod read;
|
||||
pub(crate) mod write;
|
||||
}
|
||||
|
|
|
@ -8,51 +8,52 @@
|
|||
//! * [Frame]
|
||||
|
||||
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;
|
||||
#[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::macros::feature_locked;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
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)]
|
||||
/// The ID3v2 version
|
||||
pub enum Id3v2Version {
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
mod properties;
|
||||
mod read;
|
||||
#[cfg(feature = "aiff_text_chunks")]
|
||||
pub(crate) mod tag;
|
||||
pub(crate) mod write;
|
||||
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::Id3v2Tag;
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::types::file::{AudioFile, FileType, TaggedFile};
|
||||
use crate::types::properties::FileProperties;
|
||||
use crate::types::tag::{Tag, TagType};
|
||||
#[cfg(feature = "aiff_text_chunks")]
|
||||
use tag::AiffTextChunks;
|
||||
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
crate::macros::feature_locked! {
|
||||
#![cfg(feature = "aiff_text_chunks")]
|
||||
|
||||
pub(crate) mod tag;
|
||||
use tag::AiffTextChunks;
|
||||
}
|
||||
|
||||
/// An AIFF file
|
||||
pub struct AiffFile {
|
||||
#[cfg(feature = "aiff_text_chunks")]
|
||||
|
@ -83,10 +85,11 @@ impl AudioFile for AiffFile {
|
|||
}
|
||||
|
||||
impl AiffFile {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "id3v2")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag, Id3v2Tag;
|
||||
#[cfg(feature = "aiff_text_chunks")];
|
||||
|
||||
#[cfg(feature = "aiff_text_chunks")]
|
||||
text_chunks, AiffTextChunks
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,22 @@ pub(crate) mod aiff;
|
|||
pub(crate) mod chunk;
|
||||
pub(crate) mod wav;
|
||||
|
||||
use crate::macros::feature_locked;
|
||||
|
||||
// Exports
|
||||
|
||||
pub use aiff::AiffFile;
|
||||
pub use wav::{WavFile, WavFormat, WavProperties};
|
||||
|
||||
#[cfg(feature = "aiff_text_chunks")]
|
||||
pub use aiff::tag::{AiffTextChunks, Comment};
|
||||
#[cfg(feature = "riff_info_list")]
|
||||
pub use wav::tag::RiffInfoList;
|
||||
feature_locked! {
|
||||
#![cfg(feature = "aiff_text_chunks")]
|
||||
|
||||
pub use aiff::tag::AiffTextChunks;
|
||||
pub use aiff::tag::Comment;
|
||||
}
|
||||
|
||||
feature_locked! {
|
||||
#![cfg(feature = "riff_info_list")]
|
||||
|
||||
pub use wav::tag::RiffInfoList;
|
||||
}
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
mod properties;
|
||||
mod read;
|
||||
#[cfg(feature = "riff_info_list")]
|
||||
pub(crate) mod tag;
|
||||
pub(crate) mod write;
|
||||
|
||||
pub use crate::iff::wav::properties::{WavFormat, WavProperties};
|
||||
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::Id3v2Tag;
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::types::file::{AudioFile, FileType, TaggedFile};
|
||||
use crate::types::properties::FileProperties;
|
||||
use crate::types::tag::{Tag, TagType};
|
||||
#[cfg(feature = "riff_info_list")]
|
||||
use tag::RiffInfoList;
|
||||
|
||||
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
|
||||
pub struct WavFile {
|
||||
#[cfg(feature = "riff_info_list")]
|
||||
|
@ -86,10 +89,11 @@ impl AudioFile for WavFile {
|
|||
}
|
||||
|
||||
impl WavFile {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "id3v2")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag, Id3v2Tag;
|
||||
#[cfg(feature = "riff_info_list")];
|
||||
|
||||
#[cfg(feature = "riff_info_list")]
|
||||
riff_info, RiffInfoList
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,11 +151,13 @@
|
|||
clippy::tabs_in_doc_comments,
|
||||
clippy::len_without_is_empty
|
||||
)]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
pub mod ape;
|
||||
pub mod error;
|
||||
pub mod id3;
|
||||
pub mod iff;
|
||||
pub(crate) mod macros;
|
||||
pub mod mp3;
|
||||
pub mod mp4;
|
||||
pub mod ogg;
|
||||
|
|
45
src/macros.rs
Normal file
45
src/macros.rs
Normal 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};
|
|
@ -15,7 +15,6 @@ use crate::error::Result;
|
|||
use crate::id3::v1::tag::Id3v1Tag;
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::tag::Id3v2Tag;
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::types::file::{AudioFile, FileType, TaggedFile};
|
||||
use crate::types::properties::FileProperties;
|
||||
use crate::types::tag::{Tag, TagType};
|
||||
|
@ -100,12 +99,14 @@ impl AudioFile for Mp3File {
|
|||
}
|
||||
|
||||
impl Mp3File {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "id3v2")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "id3v2")]
|
||||
id3v2_tag, Id3v2Tag;
|
||||
#[cfg(feature = "id3v1")];
|
||||
|
||||
#[cfg(feature = "id3v1")]
|
||||
id3v1_tag, Id3v1Tag;
|
||||
#[cfg(feature = "ape")];
|
||||
|
||||
#[cfg(feature = "ape")]
|
||||
ape_tag, ApeTag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use super::header::{search_for_frame_sync, Header, XingHeader};
|
||||
use super::{Mp3File, Mp3Properties};
|
||||
use crate::ape::constants::APE_PREAMBLE;
|
||||
use crate::ape::header::read_ape_header;
|
||||
#[cfg(feature = "ape")]
|
||||
use crate::ape::tag::read::read_ape_tag;
|
||||
use crate::ape::tag::read_ape_header;
|
||||
use crate::error::{FileDecodingError, Result};
|
||||
#[cfg(feature = "id3v2")]
|
||||
use crate::id3::v2::read::parse_id3v2;
|
||||
|
|
|
@ -4,29 +4,31 @@
|
|||
//!
|
||||
//! The only supported tag format is [`Ilst`].
|
||||
mod atom_info;
|
||||
#[cfg(feature = "mp4_ilst")]
|
||||
pub(crate) mod ilst;
|
||||
mod moov;
|
||||
mod properties;
|
||||
mod read;
|
||||
mod trak;
|
||||
|
||||
pub use crate::mp4::properties::{Mp4Codec, Mp4Properties};
|
||||
#[cfg(feature = "mp4_ilst")]
|
||||
pub use crate::mp4::{
|
||||
atom_info::AtomIdent,
|
||||
ilst::{
|
||||
atom::{Atom, AtomData},
|
||||
Ilst,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::error::Result;
|
||||
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};
|
||||
|
||||
// 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
|
||||
pub struct Mp4File {
|
||||
/// The file format from ftyp's "major brand" (Ex. "M4A ")
|
||||
|
@ -97,8 +99,8 @@ impl Mp4File {
|
|||
}
|
||||
|
||||
impl Mp4File {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "mp4_ilst")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "mp4_ilst")]
|
||||
ilst, Ilst
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ pub(crate) mod write;
|
|||
#[cfg(feature = "vorbis_comments")]
|
||||
use super::tag::VorbisComments;
|
||||
use crate::error::Result;
|
||||
use crate::tag_utils::tag_methods;
|
||||
use crate::types::file::{AudioFile, FileType, TaggedFile};
|
||||
use crate::types::properties::FileProperties;
|
||||
use crate::types::tag::TagType;
|
||||
|
@ -73,8 +72,8 @@ impl AudioFile for FlacFile {
|
|||
}
|
||||
|
||||
impl FlacFile {
|
||||
tag_methods! {
|
||||
#[cfg(feature = "vorbis_comments")];
|
||||
crate::macros::tag_methods! {
|
||||
#[cfg(feature = "vorbis_comments")]
|
||||
vorbis_comments, VorbisComments
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,32 +8,33 @@ pub(crate) mod flac;
|
|||
pub(crate) mod opus;
|
||||
pub(crate) mod read;
|
||||
pub(crate) mod speex;
|
||||
#[cfg(feature = "vorbis_comments")]
|
||||
pub(crate) mod tag;
|
||||
pub(crate) mod vorbis;
|
||||
#[cfg(feature = "vorbis_comments")]
|
||||
pub(crate) mod write;
|
||||
|
||||
use crate::error::{FileDecodingError, Result};
|
||||
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 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<()> {
|
||||
let sig_len = sig.len();
|
||||
|
||||
|
|
|
@ -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)]
|
||||
// Used for tag conversion tests
|
||||
pub(crate) mod test_utils {
|
||||
|
|
|
@ -110,7 +110,7 @@ impl MimeType {
|
|||
}
|
||||
}
|
||||
|
||||
/// The picture type
|
||||
/// The picture type, according to ID3v2 APIC
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum PictureType {
|
||||
|
@ -141,8 +141,8 @@ pub enum PictureType {
|
|||
impl PictureType {
|
||||
// ID3/OGG specific methods
|
||||
|
||||
/// Get a u8 from a `PictureType` according to ID3v2 APIC
|
||||
#[cfg(any(feature = "id3v2", feature = "vorbis_comments"))]
|
||||
/// Get a u8 from a `PictureType` according to ID3v2 APIC
|
||||
pub fn as_u8(&self) -> u8 {
|
||||
match self {
|
||||
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"))]
|
||||
/// Get a `PictureType` from a u8 according to ID3v2 APIC
|
||||
pub fn from_u8(bytes: u8) -> Self {
|
||||
match bytes {
|
||||
0 => Self::Other,
|
||||
|
@ -201,8 +201,8 @@ impl PictureType {
|
|||
|
||||
// APE specific methods
|
||||
|
||||
/// Get an APE item key from a `PictureType`
|
||||
#[cfg(feature = "ape")]
|
||||
/// Get an APE item key from a `PictureType`
|
||||
pub fn as_ape_key(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Other => Some("Cover Art (Other)"),
|
||||
|
@ -230,8 +230,8 @@ impl PictureType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a `PictureType` from an APE item key
|
||||
#[cfg(feature = "ape")]
|
||||
/// Get a `PictureType` from an APE item key
|
||||
pub fn from_ape_key(key: &str) -> Self {
|
||||
match key {
|
||||
"Cover Art (Other)" => Self::Other,
|
||||
|
|
Loading…
Reference in a new issue