Restructure project

This commit is contained in:
Serial 2021-12-22 09:49:43 -05:00
parent e61f63e63b
commit 8f2f7ba484
91 changed files with 390 additions and 421 deletions

View file

@ -1,21 +1,32 @@
//! APE specific items
//!
//! ## File notes
//!
//! It is possible for an `APE` file to contain an `ID3v2` tag. For the sake of data preservation,
//! this tag will be read, but **cannot** be written. The only tags allowed by spec are `APEv1/2` and
//! `ID3v1`.
mod constants; mod constants;
pub(crate) mod properties; mod properties;
pub(crate) mod read; mod read;
pub(crate) mod tag; 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::logic::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods; 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 properties::ApeProperties;
#[cfg(feature = "ape")]
use tag::ape_tag::ApeTag;
use std::io::{Read, Seek}; use std::io::{Read, Seek};

View file

@ -2,13 +2,13 @@ use super::constants::APE_PREAMBLE;
#[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::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ape::tag::read_ape_header;
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::{read::parse_id3v2, tag::Id3v2Tag}; use crate::id3::v2::{read::parse_id3v2, tag::Id3v2Tag};
use crate::logic::id3::{find_id3v1, find_id3v2, find_lyrics3v2}; use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};

View file

@ -1,5 +1,5 @@
use crate::ape::tag::item::{ApeItem, ApeItemRef};
use crate::error::Result; use crate::error::Result;
use crate::logic::ape::tag::item::{ApeItem, ApeItemRef};
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Accessor, Tag, TagType}; use crate::types::tag::{Accessor, Tag, TagType};
@ -199,7 +199,7 @@ impl From<Tag> for ApeTag {
} }
} }
pub(in crate::logic) struct ApeTagRef<'a> { pub(crate) struct ApeTagRef<'a> {
pub(crate) read_only: bool, pub(crate) read_only: bool,
pub(super) items: Box<dyn Iterator<Item = ApeItemRef<'a>> + 'a>, pub(super) items: Box<dyn Iterator<Item = ApeItemRef<'a>> + 'a>,
} }
@ -239,7 +239,7 @@ mod tests {
use crate::ape::{ApeItem, ApeTag}; use crate::ape::{ApeItem, ApeTag};
use crate::{ItemValue, Tag, TagType}; use crate::{ItemValue, Tag, TagType};
use crate::logic::ape::tag::read_ape_header; use crate::ape::tag::read_ape_header;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
#[test] #[test]
@ -300,7 +300,7 @@ mod tests {
let mut reader = Cursor::new(tag); let mut reader = Cursor::new(tag);
let header = read_ape_header(&mut reader, false).unwrap(); let header = read_ape_header(&mut reader, false).unwrap();
let parsed_tag = crate::logic::ape::tag::read::read_ape_tag(&mut reader, header).unwrap(); let parsed_tag = crate::ape::tag::read::read_ape_tag(&mut reader, header).unwrap();
assert_eq!(expected_tag.items().len(), parsed_tag.items().len()); assert_eq!(expected_tag.items().len(), parsed_tag.items().len());
@ -321,11 +321,11 @@ mod tests {
let mut reader = Cursor::new(tag_bytes); let mut reader = Cursor::new(tag_bytes);
let header = read_ape_header(&mut reader, false).unwrap(); let header = read_ape_header(&mut reader, false).unwrap();
let ape = crate::logic::ape::tag::read::read_ape_tag(&mut reader, header).unwrap(); let ape = crate::ape::tag::read::read_ape_tag(&mut reader, header).unwrap();
let tag: Tag = ape.into(); let tag: Tag = ape.into();
crate::logic::test_utils::verify_tag(&tag, true, true); crate::tag_utils::test_utils::verify_tag(&tag, true, true);
} }
#[test] #[test]
@ -337,7 +337,7 @@ mod tests {
); );
} }
let tag = crate::logic::test_utils::create_tag(TagType::Ape); let tag = crate::tag_utils::test_utils::create_tag(TagType::Ape);
let ape_tag: ApeTag = tag.into(); let ape_tag: ApeTag = tag.into();

View file

@ -1,5 +1,5 @@
use crate::ape::constants::INVALID_KEYS;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ape::constants::INVALID_KEYS;
use crate::types::item::{ItemValue, ItemValueRef, TagItem}; use crate::types::item::{ItemValue, ItemValueRef, TagItem};
use crate::types::tag::TagType; use crate::types::tag::TagType;
@ -80,7 +80,7 @@ impl TryFrom<TagItem> for ApeItem {
} }
} }
pub(in crate::logic) struct ApeItemRef<'a> { pub(crate) struct ApeItemRef<'a> {
pub read_only: bool, pub read_only: bool,
pub key: &'a str, pub key: &'a str,
pub value: ItemValueRef<'a>, pub value: ItemValueRef<'a>,

View file

@ -3,9 +3,9 @@ pub(crate) mod ape_tag;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
pub(crate) mod item; pub(crate) mod item;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
pub(in crate::logic) mod read; pub(crate) mod read;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
pub(in crate::logic) mod write; mod write;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};

View file

@ -1,6 +1,6 @@
use super::{ape_tag::ApeTag, item::ApeItem, ApeHeader}; use super::{ape_tag::ApeTag, item::ApeItem, ApeHeader};
use crate::ape::constants::INVALID_KEYS;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ape::constants::INVALID_KEYS;
use crate::types::item::ItemValue; use crate::types::item::ItemValue;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};

View file

@ -1,8 +1,8 @@
use super::read::read_ape_tag; use super::read::read_ape_tag;
use crate::ape::constants::APE_PREAMBLE;
use crate::ape::tag::ape_tag::ApeTagRef;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ape::constants::APE_PREAMBLE; use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use crate::logic::ape::tag::ape_tag::ApeTagRef;
use crate::logic::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;
@ -10,11 +10,11 @@ use crate::types::item::ItemValueRef;
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::logic::ape::tag::read_ape_header; use crate::ape::tag::read_ape_header;
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
#[allow(clippy::shadow_unrelated)] #[allow(clippy::shadow_unrelated)]
pub(in crate::logic) fn write_to(data: &mut File, tag: &mut ApeTagRef) -> Result<()> { pub(crate) fn write_to(data: &mut File, tag: &mut ApeTagRef) -> Result<()> {
let probe = Probe::new(data).guess_file_type()?; let probe = Probe::new(data).guess_file_type()?;
match probe.file_type() { match probe.file_type() {

View file

@ -1,15 +1,15 @@
use crate::error::{LoftyError, Result};
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
use crate::logic::ape::tag::ape_tag::ApeTagRef; use crate::ape::tag::ape_tag::ApeTagRef;
use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1TagRef; use crate::id3::v1::tag::Id3v1TagRef;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
use std::fs::File; use std::fs::File;
#[allow(unused_variables)] #[allow(unused_variables)]
pub(in crate::logic) fn write_to(data: &mut File, tag: &Tag) -> Result<()> { pub(crate) fn write_to(data: &mut File, tag: &Tag) -> Result<()> {
match tag.tag_type() { match tag.tag_type() {
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
TagType::Ape => Into::<ApeTagRef>::into(tag).write_to(data), TagType::Ape => Into::<ApeTagRef>::into(tag).write_to(data),

View file

@ -1,7 +1,8 @@
use ogg_pager::PageError;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
/// Result of tag operations use ogg_pager::PageError;
/// Alias for `Result<T, LoftyError>`
pub type Result<T> = std::result::Result<T, LoftyError>; pub type Result<T> = std::result::Result<T, LoftyError>;
/// Errors that could occur within Lofty /// Errors that could occur within Lofty
@ -21,7 +22,7 @@ pub enum LoftyError {
// Picture related errors // Picture related errors
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
/// Arises when an invalid picture format is parsed. Only applicable to [`Id3v2Version::V2`](crate::logic::id3::v2::Id3v2Version) /// Arises when an invalid picture format is parsed. Only applicable to [`Id3v2Version::V2`](crate::id3::v2::Id3v2Version)
BadPictureFormat(String), BadPictureFormat(String),
/// Provided an invalid picture /// Provided an invalid picture
NotAPicture, NotAPicture,

View file

@ -1,6 +1,11 @@
//! ID3 specific items
//!
//! ID3 does things differently than other tags, making working with them a little more effort than other formats.
//! Check the other modules for important notes and/or warnings.
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
pub(crate) mod v1; pub mod v1;
pub(crate) mod v2; pub mod v2;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use v2::{read_id3v2_header, Id3v2Header}; use v2::{read_id3v2_header, Id3v2Header};
@ -37,10 +42,7 @@ where
} }
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
pub(in crate::logic) fn find_id3v1<R>( pub(crate) fn find_id3v1<R>(data: &mut R, read: bool) -> Result<(bool, Option<v1::tag::Id3v1Tag>)>
data: &mut R,
read: bool,
) -> Result<(bool, Option<v1::tag::Id3v1Tag>)>
where where
R: Read + Seek, R: Read + Seek,
{ {
@ -74,7 +76,7 @@ where
} }
#[cfg(not(feature = "id3v1"))] #[cfg(not(feature = "id3v1"))]
pub(in crate::logic) fn find_id3v1<R>(data: &mut R, _read: bool) -> Result<(bool, Option<()>)> pub(in crate::tag_utils) fn find_id3v1<R>(data: &mut R, _read: bool) -> Result<(bool, Option<()>)>
where where
R: Read + Seek, R: Read + Seek,
{ {

23
src/id3/v1/mod.rs Normal file
View file

@ -0,0 +1,23 @@
//! ID3v1 items
//!
//! # ID3v1 notes
//!
//! See also: [Id3v1Tag]
//!
//! ## Genres
//!
//! ID3v1 stores the genre in a single byte ranging from 0 to 192 (inclusive).
//! All possible genres have been stored in the [`GENRES`] constant.
//!
//! ## Track Numbers
//!
//! ID3v1 stores the track number in a non-zero byte.
//! A track number of 0 will be treated as an empty field.
//! Additionally, there is no track total field.
pub(crate) mod constants;
pub(crate) mod read;
pub(crate) mod tag;
pub(crate) mod write;
pub use crate::id3::v1::constants::GENRES;
pub use crate::id3::v1::tag::Id3v1Tag;

View file

@ -1,5 +1,5 @@
use crate::error::Result; use crate::error::Result;
use crate::logic::id3::v1::constants::GENRES; use crate::id3::v1::constants::GENRES;
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Accessor, Tag, TagType}; use crate::types::tag::{Accessor, Tag, TagType};
@ -173,7 +173,7 @@ impl From<Tag> for Id3v1Tag {
} }
} }
pub(in crate::logic) struct Id3v1TagRef<'a> { pub(crate) struct Id3v1TagRef<'a> {
pub title: Option<&'a str>, pub title: Option<&'a str>,
pub artist: Option<&'a str>, pub artist: Option<&'a str>,
pub album: Option<&'a str>, pub album: Option<&'a str>,
@ -263,7 +263,7 @@ mod tests {
.read_exact(&mut tag) .read_exact(&mut tag)
.unwrap(); .unwrap();
let parsed_tag = crate::logic::id3::v1::read::parse_id3v1(tag); let parsed_tag = crate::id3::v1::read::parse_id3v1(tag);
assert_eq!(expected_tag, parsed_tag); assert_eq!(expected_tag, parsed_tag);
} }
@ -276,16 +276,16 @@ mod tests {
.read_exact(&mut tag_bytes) .read_exact(&mut tag_bytes)
.unwrap(); .unwrap();
let id3v1 = crate::logic::id3::v1::read::parse_id3v1(tag_bytes); let id3v1 = crate::id3::v1::read::parse_id3v1(tag_bytes);
let tag: Tag = id3v1.into(); let tag: Tag = id3v1.into();
crate::logic::test_utils::verify_tag(&tag, true, true); crate::tag_utils::test_utils::verify_tag(&tag, true, true);
} }
#[test] #[test]
fn tag_to_id3v1() { fn tag_to_id3v1() {
let tag = crate::logic::test_utils::create_tag(TagType::Id3v1); let tag = crate::tag_utils::test_utils::create_tag(TagType::Id3v1);
let id3v1_tag: Id3v1Tag = tag.into(); let id3v1_tag: Id3v1Tag = tag.into();

View file

@ -1,6 +1,6 @@
use super::tag::Id3v1TagRef; use super::tag::Id3v1TagRef;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::find_id3v1; use crate::id3::find_id3v1;
use crate::probe::Probe; use crate::probe::Probe;
use crate::types::file::FileType; use crate::types::file::FileType;
@ -10,7 +10,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::WriteBytesExt; use byteorder::WriteBytesExt;
#[allow(clippy::shadow_unrelated)] #[allow(clippy::shadow_unrelated)]
pub(in crate::logic) fn write_id3v1(writer: &mut File, tag: &Id3v1TagRef) -> Result<()> { pub(crate) fn write_id3v1(writer: &mut File, tag: &Id3v1TagRef) -> Result<()> {
let probe = Probe::new(writer).guess_file_type()?; let probe = Probe::new(writer).guess_file_type()?;
match probe.file_type() { match probe.file_type() {

View file

@ -1,14 +1,14 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::frame::{EncodedTextFrame, FrameValue, LanguageFrame}; use crate::id3::v2::frame::{EncodedTextFrame, FrameValue, LanguageFrame};
use crate::logic::id3::v2::util::text_utils::{decode_text, TextEncoding}; use crate::id3::v2::util::text_utils::{decode_text, TextEncoding};
use crate::logic::id3::v2::Id3v2Version; use crate::id3::v2::Id3v2Version;
use crate::types::picture::Picture; use crate::types::picture::Picture;
use std::io::Read; use std::io::Read;
use byteorder::ReadBytesExt; use byteorder::ReadBytesExt;
pub(crate) fn parse_content( pub(super) fn parse_content(
content: &mut &[u8], content: &mut &[u8],
id: &str, id: &str,
version: Id3v2Version, version: Id3v2Version,

View file

@ -1,7 +1,7 @@
use super::FrameFlags; use super::FrameFlags;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
use crate::id3::v2::FrameID; use crate::id3::v2::FrameID;
use crate::logic::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
use std::io::Read; use std::io::Read;
@ -52,7 +52,7 @@ where
let id_str = std::str::from_utf8(&frame_header[..4]).map_err(|_| LoftyError::BadFrameID)?; let id_str = std::str::from_utf8(&frame_header[..4]).map_err(|_| LoftyError::BadFrameID)?;
let (id, size) = if synchsafe { let (id, size) = if synchsafe {
let size = crate::logic::id3::v2::unsynch_u32(u32::from_be_bytes([ let size = crate::id3::v2::unsynch_u32(u32::from_be_bytes([
frame_header[4], frame_header[4],
frame_header[5], frame_header[5],
frame_header[6], frame_header[6],

View file

@ -1,11 +1,11 @@
pub(in crate::logic::id3::v2) mod content; mod content;
mod header; mod header;
pub(in crate::logic::id3::v2) mod read; pub(super) mod read;
use super::util::text_utils::TextEncoding; use super::util::text_utils::TextEncoding;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::text_utils::encode_text; use crate::id3::v2::util::text_utils::encode_text;
use crate::logic::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3}; use crate::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::picture::Picture; use crate::types::picture::Picture;
use crate::types::tag::TagType; use crate::types::tag::TagType;

View file

@ -1,9 +1,9 @@
use super::header::{parse_header, parse_v2_header}; use super::header::{parse_header, parse_v2_header};
use super::Frame; use super::Frame;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::id3::v2::frame::content::parse_content;
use crate::id3::v2::FrameValue; use crate::id3::v2::FrameValue;
use crate::logic::id3::v2::frame::content::parse_content; use crate::id3::v2::Id3v2Version;
use crate::logic::id3::v2::Id3v2Version;
use std::io::Read; use std::io::Read;
@ -28,7 +28,7 @@ impl Frame {
reader.read_exact(&mut content)?; reader.read_exact(&mut content)?;
if flags.unsynchronisation { if flags.unsynchronisation {
content = crate::logic::id3::v2::util::unsynch_content(content.as_slice())?; content = crate::id3::v2::util::unsynch_content(content.as_slice())?;
} }
if flags.compression { if flags.compression {

View file

@ -1,5 +1,5 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::text_utils::{decode_text, encode_text, TextEncoding}; use crate::id3::v2::util::text_utils::{decode_text, encode_text, TextEncoding};
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};

4
src/id3/v2/items/mod.rs Normal file
View file

@ -0,0 +1,4 @@
pub(super) mod encapsulated_object;
#[cfg(feature = "id3v2_restrictions")]
pub(super) mod restrictions;
pub(super) mod sync_text;

View file

@ -3,8 +3,8 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::text_utils; use crate::id3::v2::util::text_utils;
use crate::logic::id3::v2::util::text_utils::{ use crate::id3::v2::util::text_utils::{
decode_text, encode_text, read_to_terminator, utf16_decode, TextEncoding, decode_text, encode_text, read_to_terminator, utf16_decode, TextEncoding,
}; };

View file

@ -1,20 +1,48 @@
pub(crate) mod flags; //! ID3v2 items and utilities
//!
//! ## Important notes
//!
//! See:
//!
//! * [Id3v2Tag]
//! * [Frame]
mod flags;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(crate) mod frame; mod frame;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(crate) mod items; mod items;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(crate) mod read; pub(crate) mod read;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(crate) mod tag; pub(crate) mod tag;
pub(crate) mod util; pub(crate) mod util;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(in crate::logic) mod write; pub(crate) mod write;
#[cfg(feature = "id3v2")]
pub use frame::{EncodedTextFrame, Frame, FrameFlags, FrameID, FrameValue, LanguageFrame};
#[cfg(feature = "id3v2")]
pub use items::{
encapsulated_object::{GEOBInformation, GeneralEncapsulatedObject},
sync_text::{SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat},
};
#[cfg(feature = "id3v2")]
pub use tag::Id3v2Tag;
pub use util::text_utils::TextEncoding;
#[cfg(feature = "id3v2")]
pub use util::upgrade::{upgrade_v2, upgrade_v3};
#[cfg(feature = "id3v2")]
pub use flags::Id3v2TagFlags;
#[cfg(not(feature = "id3v2"))]
use flags::Id3v2TagFlags;
#[cfg(feature = "id3v2_restrictions")]
pub use crate::id3::v2::items::restrictions::*;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2_restrictions")] #[cfg(feature = "id3v2_restrictions")]
use crate::logic::id3::v2::items::restrictions::TagRestrictions; use crate::id3::v2::items::restrictions::TagRestrictions;
use flags::Id3v2TagFlags;
use std::io::Read; use std::io::Read;

View file

@ -4,7 +4,7 @@ use super::frame::{Frame, FrameID, FrameValue};
use super::util::text_utils::TextEncoding; use super::util::text_utils::TextEncoding;
use super::Id3v2Version; use super::Id3v2Version;
use crate::error::Result; use crate::error::Result;
use crate::logic::id3::v2::frame::FrameRef; use crate::id3::v2::frame::FrameRef;
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Accessor, Tag, TagType}; use crate::types::tag::{Accessor, Tag, TagType};
@ -300,7 +300,7 @@ pub(crate) struct Id3v2TagRef<'a> {
} }
impl<'a> Id3v2TagRef<'a> { impl<'a> Id3v2TagRef<'a> {
pub(in crate::logic) fn write_to(&mut self, file: &mut File) -> Result<()> { pub(crate) fn write_to(&mut self, file: &mut File) -> Result<()> {
super::write::write_id3v2(file, self) super::write::write_id3v2(file, self)
} }
} }
@ -333,7 +333,7 @@ mod tests {
use crate::id3::v2::{Frame, FrameFlags, FrameValue, Id3v2Tag, LanguageFrame, TextEncoding}; use crate::id3::v2::{Frame, FrameFlags, FrameValue, Id3v2Tag, LanguageFrame, TextEncoding};
use crate::{Tag, TagType}; use crate::{Tag, TagType};
use crate::logic::id3::v2::read_id3v2_header; use crate::id3::v2::read_id3v2_header;
use std::io::Read; use std::io::Read;
#[test] #[test]
@ -439,7 +439,7 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag[..]); let mut reader = std::io::Cursor::new(&tag[..]);
let header = read_id3v2_header(&mut reader).unwrap(); let header = read_id3v2_header(&mut reader).unwrap();
let parsed_tag = crate::logic::id3::v2::read::parse_id3v2(&mut reader, header).unwrap(); let parsed_tag = crate::id3::v2::read::parse_id3v2(&mut reader, header).unwrap();
assert_eq!(expected_tag, parsed_tag); assert_eq!(expected_tag, parsed_tag);
} }
@ -456,11 +456,11 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag_bytes[..]); let mut reader = std::io::Cursor::new(&tag_bytes[..]);
let header = read_id3v2_header(&mut reader).unwrap(); let header = read_id3v2_header(&mut reader).unwrap();
let id3v2 = crate::logic::id3::v2::read::parse_id3v2(&mut reader, header).unwrap(); let id3v2 = crate::id3::v2::read::parse_id3v2(&mut reader, header).unwrap();
let tag: Tag = id3v2.into(); let tag: Tag = id3v2.into();
crate::logic::test_utils::verify_tag(&tag, true, true); crate::tag_utils::test_utils::verify_tag(&tag, true, true);
} }
#[test] #[test]
@ -481,7 +481,7 @@ mod tests {
); );
} }
let tag = crate::logic::test_utils::create_tag(TagType::Id3v2); let tag = crate::tag_utils::test_utils::create_tag(TagType::Id3v2);
let id3v2_tag: Id3v2Tag = tag.into(); let id3v2_tag: Id3v2Tag = tag.into();

View file

@ -6,7 +6,7 @@ pub(crate) mod upgrade;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
pub(crate) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> { pub(in crate::id3::v2) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> {
let mut unsynch_content = Vec::new(); let mut unsynch_content = Vec::new();
let mut discard = false; let mut discard = false;

View file

@ -1,23 +1,39 @@
use std::collections::HashMap;
macro_rules! gen_upgrades { macro_rules! gen_upgrades {
(V2 => [$($($v2_key:tt)|* => $id3v24_from_v2:tt),+]; V3 => [$($($v3_key:tt)|* => $id3v24_from_v3:tt),+]) => { (V2 => [$($($v2_key:literal)|* => $id3v24_from_v2:literal),+]; V3 => [$($($v3_key:literal)|* => $id3v24_from_v3:literal),+]) => {
lazy_static::lazy_static! {
static ref V2KEYS: HashMap<&'static str, &'static str> = {
let mut map = HashMap::new();
$(
$(
map.insert($v2_key, $id3v24_from_v2);
)+
)+
map
};
}
lazy_static::lazy_static! {
static ref V3KEYS: HashMap<&'static str, &'static str> = {
let mut map = HashMap::new();
$(
$(
map.insert($v3_key, $id3v24_from_v3);
)+
)+
map
};
}
/// Upgrade an ID3v2.2 key to an ID3v2.4 key /// Upgrade an ID3v2.2 key to an ID3v2.4 key
pub fn upgrade_v2(key: &str) -> Option<&'static str> { pub fn upgrade_v2(key: &str) -> Option<&'static str> {
match key { V2KEYS.get(key).map(|s| *s)
$(
$($v2_key)|* => Some($id3v24_from_v2),
)+
_ => None
}
} }
/// Upgrade an ID3v2.3 key to an ID3v2.4 key /// Upgrade an ID3v2.3 key to an ID3v2.4 key
pub fn upgrade_v3(key: &str) -> Option<&'static str> { pub fn upgrade_v3(key: &str) -> Option<&'static str> {
match key { V3KEYS.get(key).map(|s| *s)
$(
$($v3_key)|* => Some($id3v24_from_v3),
)+
_ => None
}
} }
} }
} }

View file

@ -1,12 +1,12 @@
use crate::error::Result; use crate::error::Result;
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use std::fs::File; use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, SeekFrom, Write};
use byteorder::{ByteOrder, WriteBytesExt}; use byteorder::{ByteOrder, WriteBytesExt};
pub(in crate::logic::id3::v2) fn write_to_chunk_file<B>(data: &mut File, tag: &[u8]) -> Result<()> pub(in crate::id3::v2) fn write_to_chunk_file<B>(data: &mut File, tag: &[u8]) -> Result<()>
where where
B: ByteOrder, B: ByteOrder,
{ {

View file

@ -1,13 +1,13 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::id3::v2::frame::{FrameFlags, FrameRef, FrameValueRef};
use crate::id3::v2::synch_u32;
use crate::id3::v2::Id3v2Version; use crate::id3::v2::Id3v2Version;
use crate::logic::id3::v2::frame::{FrameFlags, FrameRef, FrameValueRef};
use crate::logic::id3::v2::synch_u32;
use std::io::Write; use std::io::Write;
use byteorder::{BigEndian, WriteBytesExt}; use byteorder::{BigEndian, WriteBytesExt};
pub(in crate::logic::id3::v2) fn create_items<'a, W>( pub(in crate::id3::v2) fn create_items<'a, W>(
writer: &mut W, writer: &mut W,
frames: &mut dyn Iterator<Item = FrameRef<'a>>, frames: &mut dyn Iterator<Item = FrameRef<'a>>,
) -> Result<()> ) -> Result<()>

View file

@ -3,8 +3,8 @@ mod frame;
use super::Id3v2TagFlags; use super::Id3v2TagFlags;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::tag::Id3v2TagRef; use crate::id3::v2::tag::Id3v2TagRef;
use crate::logic::id3::{find_id3v2, v2::synch_u32}; use crate::id3::{find_id3v2, v2::synch_u32};
use crate::probe::Probe; use crate::probe::Probe;
use crate::types::file::FileType; use crate::types::file::FileType;
@ -14,7 +14,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt}; use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
#[allow(clippy::shadow_unrelated)] #[allow(clippy::shadow_unrelated)]
pub(in crate::logic) fn write_id3v2(data: &mut File, tag: &mut Id3v2TagRef) -> Result<()> { pub(crate) fn write_id3v2(data: &mut File, tag: &mut Id3v2TagRef) -> Result<()> {
let probe = Probe::new(data).guess_file_type()?; let probe = Probe::new(data).guess_file_type()?;
match probe.file_type() { match probe.file_type() {
@ -48,10 +48,7 @@ pub(in crate::logic) fn write_id3v2(data: &mut File, tag: &mut Id3v2TagRef) -> R
} }
// Formats such as WAV and AIFF store the ID3v2 tag in an 'ID3 ' chunk rather than at the beginning of the file // Formats such as WAV and AIFF store the ID3v2 tag in an 'ID3 ' chunk rather than at the beginning of the file
pub(in crate::logic) fn write_id3v2_to_chunk_file<B>( fn write_id3v2_to_chunk_file<B>(data: &mut File, tag: &mut Id3v2TagRef) -> Result<()>
data: &mut File,
tag: &mut Id3v2TagRef,
) -> Result<()>
where where
B: ByteOrder, B: ByteOrder,
{ {

View file

@ -2,12 +2,12 @@ mod properties;
mod read; mod read;
#[cfg(feature = "aiff_text_chunks")] #[cfg(feature = "aiff_text_chunks")]
pub(crate) mod tag; pub(crate) mod tag;
pub(in crate::logic) mod write; pub(crate) mod write;
use crate::error::Result; use crate::error::Result;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods; 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};

View file

@ -3,15 +3,15 @@ use super::tag::AiffTextChunks;
use super::AiffFile; use super::AiffFile;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use byteorder::BigEndian; use byteorder::BigEndian;
pub(in crate::logic::iff) fn verify_aiff<R>(data: &mut R) -> Result<()> pub(in crate::iff) fn verify_aiff<R>(data: &mut R) -> Result<()>
where where
R: Read + Seek, R: Read + Seek,
{ {
@ -25,7 +25,7 @@ where
Ok(()) Ok(())
} }
pub(in crate::logic) fn read_from<R>(data: &mut R, read_properties: bool) -> Result<AiffFile> pub(crate) fn read_from<R>(data: &mut R, read_properties: bool) -> Result<AiffFile>
where where
R: Read + Seek, R: Read + Seek,
{ {

View file

@ -1,5 +1,5 @@
use crate::error::Result; use crate::error::Result;
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Accessor, Tag, TagType}; use crate::types::tag::{Accessor, Tag, TagType};
@ -146,12 +146,12 @@ impl<'a> Into<AiffTextChunksRef<'a>> for &'a Tag {
} }
impl<'a> AiffTextChunksRef<'a> { impl<'a> AiffTextChunksRef<'a> {
pub(in crate::logic) fn write_to(&self, file: &mut File) -> Result<()> { pub(crate) fn write_to(&self, file: &mut File) -> Result<()> {
write_to(file, self) write_to(file, self)
} }
} }
pub(in crate::logic) fn write_to(data: &mut File, tag: &AiffTextChunksRef) -> Result<()> { pub(crate) fn write_to(data: &mut File, tag: &AiffTextChunksRef) -> Result<()> {
fn write_chunk(writer: &mut Vec<u8>, key: &str, value: Option<&str>) { fn write_chunk(writer: &mut Vec<u8>, key: &str, value: Option<&str>) {
if let Some(val) = value { if let Some(val) = value {
if let Ok(len) = u32::try_from(val.len()) { if let Ok(len) = u32::try_from(val.len()) {

View file

@ -1,8 +1,8 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2TagRef; use crate::id3::v2::tag::Id3v2TagRef;
#[cfg(feature = "aiff_text_chunks")] #[cfg(feature = "aiff_text_chunks")]
use crate::logic::iff::aiff::tag::AiffTextChunksRef; use crate::iff::aiff::tag::AiffTextChunksRef;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};

View file

@ -1,16 +1,16 @@
use crate::error::Result; use crate::error::Result;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::read::parse_id3v2; use crate::id3::v2::read::parse_id3v2;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::logic::id3::v2::read_id3v2_header; use crate::id3::v2::read_id3v2_header;
use byteorder::{ByteOrder, ReadBytesExt}; use byteorder::{ByteOrder, ReadBytesExt};
pub(in crate::logic) struct Chunks<B> pub(crate) struct Chunks<B>
where where
B: ByteOrder, B: ByteOrder,
{ {

13
src/iff/mod.rs Normal file
View file

@ -0,0 +1,13 @@
//! WAV/AIFF specific items
pub(crate) mod aiff;
pub(crate) mod chunk;
pub(crate) mod wav;
pub use crate::iff::aiff::AiffFile;
pub use crate::iff::wav::WavFile;
#[cfg(feature = "aiff_text_chunks")]
pub use crate::iff::aiff::tag::AiffTextChunks;
#[cfg(feature = "riff_info_list")]
pub use crate::iff::wav::tag::RiffInfoList;
pub use wav::{WavFormat, WavProperties};

View file

@ -1,17 +1,18 @@
pub(crate) mod properties; mod properties;
mod read; mod read;
#[cfg(feature = "riff_info_list")] #[cfg(feature = "riff_info_list")]
pub(crate) mod tag; pub(crate) mod tag;
pub(in crate::logic) 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::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods; 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 properties::WavProperties;
#[cfg(feature = "riff_info_list")] #[cfg(feature = "riff_info_list")]
use tag::RiffInfoList; use tag::RiffInfoList;

View file

@ -4,14 +4,14 @@ use super::tag::RiffInfoList;
use super::WavFile; use super::WavFile;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
pub(in crate::logic::iff) fn verify_wav<T>(data: &mut T) -> Result<()> pub(in crate::iff) fn verify_wav<T>(data: &mut T) -> Result<()>
where where
T: Read + Seek, T: Read + Seek,
{ {
@ -29,7 +29,7 @@ where
Ok(()) Ok(())
} }
pub(in crate::logic) fn read_from<R>(data: &mut R, read_properties: bool) -> Result<WavFile> pub(crate) fn read_from<R>(data: &mut R, read_properties: bool) -> Result<WavFile>
where where
R: Read + Seek, R: Read + Seek,
{ {

View file

@ -1,5 +1,5 @@
pub(in crate::logic::iff::wav) mod read; pub(super) mod read;
pub(in crate::logic::iff::wav) mod write; mod write;
use crate::error::Result; use crate::error::Result;
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
@ -243,12 +243,12 @@ mod tests {
let tag: Tag = riff_info.into(); let tag: Tag = riff_info.into();
crate::logic::test_utils::verify_tag(&tag, true, false); crate::tag_utils::test_utils::verify_tag(&tag, true, false);
} }
#[test] #[test]
fn tag_to_riff_info() { fn tag_to_riff_info() {
let tag = crate::logic::test_utils::create_tag(TagType::RiffInfo); let tag = crate::tag_utils::test_utils::create_tag(TagType::RiffInfo);
let riff_info: RiffInfoList = tag.into(); let riff_info: RiffInfoList = tag.into();

View file

@ -1,12 +1,12 @@
use super::RiffInfoList; use super::RiffInfoList;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use byteorder::LittleEndian; use byteorder::LittleEndian;
pub(in crate::logic::iff::wav) fn parse_riff_info<R>( pub(in crate::iff::wav) fn parse_riff_info<R>(
data: &mut R, data: &mut R,
end: u64, end: u64,
tag: &mut RiffInfoList, tag: &mut RiffInfoList,

View file

@ -1,14 +1,14 @@
use super::RiffInfoListRef; use super::RiffInfoListRef;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::iff::chunk::Chunks; use crate::iff::chunk::Chunks;
use crate::logic::iff::wav::read::verify_wav; use crate::iff::wav::read::verify_wav;
use std::fs::File; use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
pub(in crate::logic::iff::wav) fn write_riff_info( pub(in crate::iff::wav) fn write_riff_info(
data: &mut File, data: &mut File,
tag: &mut RiffInfoListRef, tag: &mut RiffInfoListRef,
) -> Result<()> { ) -> Result<()> {

View file

@ -1,8 +1,8 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2TagRef; use crate::id3::v2::tag::Id3v2TagRef;
#[cfg(feature = "riff_info_list")] #[cfg(feature = "riff_info_list")]
use crate::logic::iff::wav::tag::RiffInfoListRef; use crate::iff::wav::tag::RiffInfoListRef;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};

View file

@ -150,9 +150,15 @@
clippy::single_match_else clippy::single_match_else
)] )]
pub mod ape;
mod error; mod error;
pub(crate) mod logic; pub mod id3;
pub mod iff;
pub mod mp3;
pub mod mp4;
pub mod ogg;
mod probe; mod probe;
pub(crate) mod tag_utils;
mod types; mod types;
pub use crate::error::{LoftyError, Result}; pub use crate::error::{LoftyError, Result};
@ -174,133 +180,3 @@ pub use crate::types::picture::{MimeType, Picture, PictureType};
pub use crate::types::picture::PictureInformation; pub use crate::types::picture::PictureInformation;
pub use probe::{read_from, read_from_path}; pub use probe::{read_from, read_from_path};
#[cfg(any(feature = "id3v1", feature = "id3v2"))]
pub mod id3 {
//! ID3 specific items
//!
//! ID3 does things differently than other tags, making working with them a little more effort than other formats.
//! Check the other modules for important notes and/or warnings.
#[cfg(feature = "id3v2")]
pub mod v2 {
//! ID3v2 items and utilities
//!
//! ## Important notes
//!
//! See:
//!
//! * [Id3v2Tag]
//! * [Frame]
pub use {
crate::logic::id3::v2::flags::Id3v2TagFlags,
crate::logic::id3::v2::frame::{
EncodedTextFrame, Frame, FrameFlags, FrameID, FrameValue, LanguageFrame,
},
crate::logic::id3::v2::items::encapsulated_object::{
GEOBInformation, GeneralEncapsulatedObject,
},
crate::logic::id3::v2::items::sync_text::{
SyncTextContentType, SyncTextInformation, SynchronizedText, TimestampFormat,
},
crate::logic::id3::v2::tag::Id3v2Tag,
crate::logic::id3::v2::util::text_utils::TextEncoding,
crate::logic::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3},
crate::logic::id3::v2::Id3v2Version,
};
#[cfg(feature = "id3v2_restrictions")]
pub use crate::logic::id3::v2::items::restrictions::*;
}
#[cfg(feature = "id3v1")]
pub mod v1 {
//! ID3v1 items
//!
//! # ID3v1 notes
//!
//! See also: [Id3v1Tag]
//!
//! ## Genres
//!
//! ID3v1 stores the genre in a single byte ranging from 0 to 192 (inclusive).
//! All possible genres have been stored in the [`GENRES`] constant.
//!
//! ## Track Numbers
//!
//! ID3v1 stores the track number in a non-zero byte.
//! A track number of 0 will be treated as an empty field.
//! Additionally, there is no track total field.
pub use crate::logic::id3::v1::constants::GENRES;
pub use crate::logic::id3::v1::tag::Id3v1Tag;
}
}
pub mod ape {
//! APE specific items
//!
//! ## File notes
//!
//! It is possible for an `APE` file to contain an `ID3v2` tag. For the sake of data preservation,
//! this tag will be read, but **cannot** be written. The only tags allowed by spec are `APEv1/2` and
//! `ID3v1`.
pub use crate::logic::ape::{properties::ApeProperties, ApeFile};
#[cfg(feature = "ape")]
pub use crate::{
logic::ape::tag::{ape_tag::ApeTag, item::ApeItem},
types::picture::APE_PICTURE_TYPES,
};
}
pub mod mp3 {
//! MP3 specific items
pub use crate::logic::mp3::header::{ChannelMode, Layer, MpegVersion};
pub use crate::logic::mp3::{properties::Mp3Properties, Mp3File};
}
pub mod mp4 {
//! MP4 specific items
//!
//! ## File notes
//!
//! The only supported tag format is [`Ilst`].
#[cfg(feature = "mp4_ilst")]
pub use crate::logic::mp4::{
ilst::{
atom::{Atom, AtomData},
Ilst,
},
AtomIdent,
};
pub use crate::logic::mp4::{
properties::{Mp4Codec, Mp4Properties},
Mp4File,
};
}
pub mod ogg {
//! OPUS/FLAC/Vorbis specific items
//!
//! ## File notes
//!
//! The only supported tag format is [`VorbisComments`]
pub use crate::logic::ogg::flac::FlacFile;
pub use crate::logic::ogg::opus::{properties::OpusProperties, OpusFile};
#[cfg(feature = "vorbis_comments")]
pub use crate::logic::ogg::tag::VorbisComments;
pub use crate::logic::ogg::vorbis::{properties::VorbisProperties, VorbisFile};
}
pub mod iff {
//! WAV/AIFF specific items
pub use crate::logic::iff::aiff::AiffFile;
pub use crate::logic::iff::wav::WavFile;
#[cfg(feature = "aiff_text_chunks")]
pub use crate::logic::iff::aiff::tag::AiffTextChunks;
#[cfg(feature = "riff_info_list")]
pub use crate::logic::iff::wav::tag::RiffInfoList;
pub use crate::logic::iff::wav::properties::{WavFormat, WavProperties};
}

View file

@ -1,4 +0,0 @@
pub(crate) mod constants;
pub(in crate::logic) mod read;
pub(crate) mod tag;
pub(in crate::logic) mod write;

View file

@ -1,4 +0,0 @@
pub(crate) mod encapsulated_object;
#[cfg(feature = "id3v2_restrictions")]
pub(crate) mod restrictions;
pub(crate) mod sync_text;

View file

@ -1,3 +0,0 @@
pub(crate) mod aiff;
pub(in crate::logic) mod chunk;
pub(crate) mod wav;

View file

@ -1,21 +1,24 @@
//! MP3 specific items
mod constants; mod constants;
pub(crate) mod header; pub(crate) mod header;
pub(crate) mod properties; mod properties;
pub(crate) mod read; mod read;
pub(in crate::logic) mod write; pub(crate) mod write;
pub use header::{ChannelMode, Layer, MpegVersion};
pub use properties::Mp3Properties;
use crate::error::Result;
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
use crate::logic::ape::tag::ape_tag::ApeTag; use crate::ape::tag::ape_tag::ApeTag;
use crate::error::Result;
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1Tag; use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag; use crate::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods; 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 properties::Mp3Properties;
use std::io::{Read, Seek}; use std::io::{Read, Seek};

View file

@ -1,16 +1,16 @@
use super::header::{verify_frame_sync, Header, XingHeader}; use super::header::{verify_frame_sync, Header, XingHeader};
use super::{Mp3File, Mp3Properties}; use super::{Mp3File, Mp3Properties};
#[cfg(feature = "ape")]
use crate::ape::tag::ape_tag::ApeTag;
use crate::ape::tag::read_ape_header;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v1")]
use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")]
use crate::id3::v2::read::parse_id3v2;
use crate::id3::v2::read_id3v2_header;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::id3::v2::Id3v2Tag; use crate::id3::v2::Id3v2Tag;
#[cfg(feature = "ape")]
use crate::logic::ape::tag::ape_tag::ApeTag;
use crate::logic::ape::tag::read_ape_header;
#[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::read::parse_id3v2;
use crate::logic::id3::v2::read_id3v2_header;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
@ -85,7 +85,7 @@ where
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
{ {
id3v1_tag = Some(crate::logic::id3::v1::read::parse_id3v1(id3v1_read)); id3v1_tag = Some(crate::id3::v1::read::parse_id3v1(id3v1_read));
} }
continue; continue;
@ -105,9 +105,7 @@ where
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
{ {
ape_tag = Some(crate::logic::ape::tag::read::read_ape_tag( ape_tag = Some(crate::ape::tag::read::read_ape_tag(data, ape_header)?);
data, ape_header,
)?);
} }
continue; continue;

View file

@ -1,10 +1,10 @@
use crate::error::{LoftyError, Result};
#[cfg(feature = "ape")] #[cfg(feature = "ape")]
use crate::logic::ape::tag::ape_tag::ApeTagRef; use crate::ape::tag::ape_tag::ApeTagRef;
use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1TagRef; use crate::id3::v1::tag::Id3v1TagRef;
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2TagRef; use crate::id3::v2::tag::Id3v2TagRef;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};

View file

@ -1,4 +1,4 @@
use crate::logic::mp4::AtomIdent; use crate::mp4::AtomIdent;
use crate::types::picture::Picture; use crate::types::picture::Picture;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]

View file

@ -1,6 +1,6 @@
pub(crate) mod atom; pub(super) mod atom;
pub(in crate::logic::mp4) mod read; pub(super) mod read;
pub(in crate::logic) mod write; pub(crate) mod write;
use super::AtomIdent; use super::AtomIdent;
use crate::error::Result; use crate::error::Result;
@ -221,7 +221,7 @@ pub(crate) struct IlstRef<'a> {
} }
impl<'a> IlstRef<'a> { impl<'a> IlstRef<'a> {
pub(in crate::logic) fn write_to(&mut self, file: &mut File) -> Result<()> { pub(crate) fn write_to(&mut self, file: &mut File) -> Result<()> {
write::write_to(file, self) write::write_to(file, self)
} }
} }
@ -355,7 +355,7 @@ mod tests {
let tag: Tag = ilst.into(); let tag: Tag = ilst.into();
crate::logic::test_utils::verify_tag(&tag, false, true); crate::tag_utils::test_utils::verify_tag(&tag, false, true);
} }
#[test] #[test]
@ -368,7 +368,7 @@ mod tests {
assert_eq!(atom.data(), &data); assert_eq!(atom.data(), &data);
} }
let tag = crate::logic::test_utils::create_tag(TagType::Mp4Ilst); let tag = crate::tag_utils::test_utils::create_tag(TagType::Mp4Ilst);
let ilst: Ilst = tag.into(); let ilst: Ilst = tag.into();

View file

@ -1,8 +1,8 @@
use super::{Atom, AtomData, AtomIdent, Ilst}; use super::{Atom, AtomData, AtomIdent, Ilst};
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::text_utils::utf16_decode; use crate::id3::v2::util::text_utils::utf16_decode;
use crate::logic::mp4::atom_info::AtomInfo; use crate::mp4::atom_info::AtomInfo;
use crate::logic::mp4::read::skip_unneeded; use crate::mp4::read::skip_unneeded;
use crate::types::picture::{MimeType, Picture, PictureType}; use crate::types::picture::{MimeType, Picture, PictureType};
use std::borrow::Cow; use std::borrow::Cow;

View file

@ -1,9 +1,9 @@
use super::{AtomDataRef, IlstRef}; use super::{AtomDataRef, IlstRef};
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::mp4::ilst::{AtomIdentRef, AtomRef}; use crate::mp4::ilst::{AtomIdentRef, AtomRef};
use crate::logic::mp4::moov::Moov; use crate::mp4::moov::Moov;
use crate::logic::mp4::read::nested_atom; use crate::mp4::read::nested_atom;
use crate::logic::mp4::read::verify_mp4; use crate::mp4::read::verify_mp4;
use crate::types::picture::MimeType; use crate::types::picture::MimeType;
use crate::types::picture::Picture; use crate::types::picture::Picture;
@ -12,7 +12,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{BigEndian, WriteBytesExt}; use byteorder::{BigEndian, WriteBytesExt};
pub(in crate::logic) fn write_to(data: &mut File, tag: &mut IlstRef) -> Result<()> { pub(in crate) fn write_to(data: &mut File, tag: &mut IlstRef) -> Result<()> {
verify_mp4(data)?; verify_mp4(data)?;
let moov = Moov::find(data)?; let moov = Moov::find(data)?;

View file

@ -1,19 +1,29 @@
//! MP4 specific items
//!
//! ## File notes
//!
//! The only supported tag format is [`Ilst`].
mod atom_info; mod atom_info;
#[cfg(feature = "mp4_ilst")] #[cfg(feature = "mp4_ilst")]
pub(crate) mod ilst; pub(crate) mod ilst;
mod moov; mod moov;
pub(crate) mod properties; mod properties;
mod read; mod read;
mod trak; mod trak;
use crate::logic::tag_methods; 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::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use crate::{FileProperties, Result, TagType}; use crate::{FileProperties, Result, TagType};
#[cfg(feature = "mp4_ilst")]
pub use atom_info::AtomIdent;
#[cfg(feature = "mp4_ilst")]
use ilst::Ilst;
use properties::Mp4Properties;
use std::io::{Read, Seek}; use std::io::{Read, Seek};

View file

@ -6,7 +6,7 @@ use crate::error::{LoftyError, Result};
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
pub(in crate::logic::mp4) fn verify_mp4<R>(data: &mut R) -> Result<String> pub(in crate::mp4) fn verify_mp4<R>(data: &mut R) -> Result<String>
where where
R: Read + Seek, R: Read + Seek,
{ {

View file

@ -15,7 +15,7 @@ pub(super) struct Block {
} }
impl Block { impl Block {
pub(in crate::logic::ogg) fn read<R>(data: &mut R) -> Result<Self> pub(in crate::ogg) fn read<R>(data: &mut R) -> Result<Self>
where where
R: Read + Seek, R: Read + Seek,
{ {

View file

@ -2,12 +2,12 @@ mod block;
mod properties; mod properties;
mod read; mod read;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
pub(in crate::logic) mod write; 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::logic::tag_methods; 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;

View file

@ -2,7 +2,7 @@ use super::block::Block;
use super::FlacFile; use super::FlacFile;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
use crate::logic::ogg::{read::read_comments, tag::VorbisComments}; use crate::ogg::{read::read_comments, tag::VorbisComments};
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
use crate::types::picture::Picture; use crate::types::picture::Picture;
use crate::types::properties::FileProperties; use crate::types::properties::FileProperties;

View file

@ -1,8 +1,8 @@
use super::block::Block; use super::block::Block;
use super::read::verify_flac; use super::read::verify_flac;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ogg::tag::VorbisCommentsRef; use crate::ogg::tag::VorbisCommentsRef;
use crate::logic::ogg::write::create_comments; use crate::ogg::write::create_comments;
use crate::types::picture::{Picture, PictureInformation}; use crate::types::picture::{Picture, PictureInformation};
use std::fs::File; use std::fs::File;
@ -10,7 +10,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
pub(in crate::logic) fn write_to(data: &mut File, tag: &mut VorbisCommentsRef) -> Result<()> { pub(in crate) fn write_to(data: &mut File, tag: &mut VorbisCommentsRef) -> Result<()> {
let stream_info = verify_flac(data)?; let stream_info = verify_flac(data)?;
let stream_info_end = stream_info.end as usize; let stream_info_end = stream_info.end as usize;

View file

@ -1,13 +1,23 @@
//! OPUS/FLAC/Vorbis specific items
//!
//! ## File notes
//!
//! The only supported tag format is [`VorbisComments`]
pub(crate) mod constants; pub(crate) mod constants;
pub(crate) mod read;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod write;
pub(crate) mod flac; pub(crate) mod flac;
pub(crate) mod opus; pub(crate) mod opus;
pub(crate) mod read;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
pub(crate) mod tag; pub(crate) mod tag;
pub(crate) mod vorbis; pub(crate) mod vorbis;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod write;
pub use crate::ogg::flac::FlacFile;
pub use crate::ogg::opus::{properties::OpusProperties, OpusFile};
#[cfg(feature = "vorbis_comments")]
pub use crate::ogg::tag::VorbisComments;
pub use crate::ogg::vorbis::{properties::VorbisProperties, VorbisFile};
use crate::{LoftyError, Result}; use crate::{LoftyError, Result};
@ -16,7 +26,7 @@ use std::io::{Read, Seek};
use ogg_pager::Page; use ogg_pager::Page;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
pub fn page_from_packet(packet: &mut [u8]) -> Result<Vec<Page>> { pub(self) fn page_from_packet(packet: &mut [u8]) -> Result<Vec<Page>> {
let mut pages: Vec<Page> = Vec::new(); let mut pages: Vec<Page> = Vec::new();
let reader = &mut &packet[..]; let reader = &mut &packet[..];

View file

@ -1,4 +1,4 @@
pub(crate) mod properties; pub(super) mod properties;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
pub(super) mod write; pub(super) mod write;
@ -6,7 +6,7 @@ use super::find_last_page;
#[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::logic::ogg::constants::{OPUSHEAD, OPUSTAGS}; use crate::ogg::constants::{OPUSHEAD, OPUSTAGS};
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;

View file

@ -82,10 +82,7 @@ impl OpusProperties {
} }
} }
pub(in crate::logic::ogg) fn read_properties<R>( pub(in crate::ogg) fn read_properties<R>(data: &mut R, first_page: &Page) -> Result<OpusProperties>
data: &mut R,
first_page: &Page,
) -> Result<OpusProperties>
where where
R: Read + Seek, R: Read + Seek,
{ {

View file

@ -5,7 +5,7 @@ use std::io::{Read, Seek, SeekFrom, Write};
use ogg_pager::Page; use ogg_pager::Page;
pub(in crate::logic) fn write_to( pub(crate) fn write_to(
data: &mut File, data: &mut File,
writer: &mut Vec<u8>, writer: &mut Vec<u8>,
ser: u32, ser: u32,

View file

@ -1,5 +1,5 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ogg::constants::{OPUSHEAD, VORBIS_IDENT_HEAD}; use crate::ogg::constants::{OPUSHEAD, VORBIS_IDENT_HEAD};
use crate::probe::Probe; use crate::probe::Probe;
use crate::types::file::FileType; use crate::types::file::FileType;
use crate::types::item::{ItemKey, ItemValue, TagItem}; use crate::types::item::{ItemKey, ItemValue, TagItem};
@ -253,7 +253,7 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag[..]); let mut reader = std::io::Cursor::new(&tag[..]);
let mut parsed_tag = VorbisComments::default(); let mut parsed_tag = VorbisComments::default();
crate::logic::ogg::read::read_comments(&mut reader, &mut parsed_tag).unwrap(); crate::ogg::read::read_comments(&mut reader, &mut parsed_tag).unwrap();
assert_eq!(expected_tag, parsed_tag); assert_eq!(expected_tag, parsed_tag);
} }
@ -269,16 +269,16 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag_bytes[..]); let mut reader = std::io::Cursor::new(&tag_bytes[..]);
let mut vorbis_comments = VorbisComments::default(); let mut vorbis_comments = VorbisComments::default();
crate::logic::ogg::read::read_comments(&mut reader, &mut vorbis_comments).unwrap(); crate::ogg::read::read_comments(&mut reader, &mut vorbis_comments).unwrap();
let tag: Tag = vorbis_comments.into(); let tag: Tag = vorbis_comments.into();
crate::logic::test_utils::verify_tag(&tag, true, true); crate::tag_utils::test_utils::verify_tag(&tag, true, true);
} }
#[test] #[test]
fn tag_to_vorbis_comments() { fn tag_to_vorbis_comments() {
let tag = crate::logic::test_utils::create_tag(TagType::VorbisComments); let tag = crate::tag_utils::test_utils::create_tag(TagType::VorbisComments);
let vorbis_comments: VorbisComments = tag.into(); let vorbis_comments: VorbisComments = tag.into();

View file

@ -1,12 +1,12 @@
pub(crate) mod properties; pub(super) mod properties;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
pub(in crate::logic::ogg) mod write; pub(in crate::ogg) mod write;
use super::find_last_page; use super::find_last_page;
#[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::logic::ogg::constants::{VORBIS_COMMENT_HEAD, VORBIS_IDENT_HEAD}; use crate::ogg::constants::{VORBIS_COMMENT_HEAD, VORBIS_IDENT_HEAD};
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;

View file

@ -106,7 +106,7 @@ impl VorbisProperties {
} }
} }
pub(in crate::logic::ogg) fn read_properties<R>( pub(in crate::ogg) fn read_properties<R>(
data: &mut R, data: &mut R,
first_page: &Page, first_page: &Page,
) -> Result<VorbisProperties> ) -> Result<VorbisProperties>

View file

@ -1,5 +1,5 @@
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ogg::constants::VORBIS_SETUP_HEAD; use crate::ogg::constants::VORBIS_SETUP_HEAD;
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write}; use std::io::{Cursor, Read, Seek, SeekFrom, Write};
@ -7,7 +7,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use ogg_pager::Page; use ogg_pager::Page;
pub(in crate::logic) fn write_to( pub(crate) fn write_to(
data: &mut File, data: &mut File,
writer: &mut Vec<u8>, writer: &mut Vec<u8>,
first_md_content: Vec<u8>, first_md_content: Vec<u8>,

View file

@ -1,8 +1,8 @@
use super::{page_from_packet, verify_signature}; use super::{page_from_packet, verify_signature};
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ogg::constants::OPUSTAGS; use crate::ogg::constants::OPUSTAGS;
use crate::logic::ogg::constants::VORBIS_COMMENT_HEAD; use crate::ogg::constants::VORBIS_COMMENT_HEAD;
use crate::logic::ogg::tag::VorbisCommentsRef; use crate::ogg::tag::VorbisCommentsRef;
use crate::types::picture::PictureInformation; use crate::types::picture::PictureInformation;
use crate::types::tag::{Tag, TagType}; use crate::types::tag::{Tag, TagType};
@ -13,8 +13,9 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use ogg_pager::Page; use ogg_pager::Page;
pub(in crate::logic) fn write_to(data: &mut File, tag: &Tag, sig: &[u8]) -> Result<()> { pub(in crate) fn write_to(data: &mut File, tag: &Tag, sig: &[u8]) -> Result<()> {
match tag.tag_type() { match tag.tag_type() {
#[cfg(feature = "vorbis_comments")]
TagType::VorbisComments => write(data, &mut Into::<VorbisCommentsRef>::into(tag), sig), TagType::VorbisComments => write(data, &mut Into::<VorbisCommentsRef>::into(tag), sig),
_ => Err(LoftyError::UnsupportedTag), _ => Err(LoftyError::UnsupportedTag),
} }

View file

@ -1,13 +1,13 @@
use crate::ape::ApeFile;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::logic::ape::ApeFile; use crate::iff::aiff::AiffFile;
use crate::logic::iff::aiff::AiffFile; use crate::iff::wav::WavFile;
use crate::logic::iff::wav::WavFile; use crate::mp3::header::verify_frame_sync;
use crate::logic::mp3::header::verify_frame_sync; use crate::mp3::Mp3File;
use crate::logic::mp3::Mp3File; use crate::mp4::Mp4File;
use crate::logic::mp4::Mp4File; use crate::ogg::flac::FlacFile;
use crate::logic::ogg::flac::FlacFile; use crate::ogg::opus::OpusFile;
use crate::logic::ogg::opus::OpusFile; use crate::ogg::vorbis::VorbisFile;
use crate::logic::ogg::vorbis::VorbisFile;
use crate::types::file::{AudioFile, FileType, TaggedFile}; use crate::types::file::{AudioFile, FileType, TaggedFile};
use std::fs::File; use std::fs::File;

View file

@ -1,48 +1,45 @@
pub(crate) mod ape;
pub(crate) mod id3;
pub(crate) mod iff;
pub(crate) mod mp3;
pub(crate) mod mp4;
pub(crate) mod ogg;
use crate::error::{LoftyError, Result}; use crate::error::{LoftyError, Result};
use crate::types::file::FileType;
use crate::types::tag::Tag;
#[cfg(feature = "mp4_ilst")] #[cfg(feature = "mp4_ilst")]
use mp4::ilst::IlstRef; use crate::mp4::ilst::IlstRef;
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
use ogg::{ use crate::ogg::{
constants::{OPUSTAGS, VORBIS_COMMENT_HEAD}, constants::{OPUSTAGS, VORBIS_COMMENT_HEAD},
tag::VorbisCommentsRef, tag::VorbisCommentsRef,
}; };
use crate::types::file::FileType;
use crate::types::tag::Tag;
use std::fs::File; use std::fs::File;
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
pub(crate) fn write_tag(tag: &Tag, file: &mut File, file_type: FileType) -> Result<()> { pub(crate) fn write_tag(tag: &Tag, file: &mut File, file_type: FileType) -> Result<()> {
match file_type { match file_type {
FileType::AIFF => iff::aiff::write::write_to(file, tag), FileType::AIFF => crate::iff::aiff::write::write_to(file, tag),
FileType::APE => ape::write::write_to(file, tag), FileType::APE => crate::ape::write::write_to(file, tag),
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
FileType::FLAC => ogg::flac::write::write_to(file, &mut Into::<VorbisCommentsRef>::into(tag)), FileType::FLAC => {
FileType::MP3 => mp3::write::write_to(file, tag), crate::ogg::flac::write::write_to(file, &mut Into::<VorbisCommentsRef>::into(tag))
},
FileType::MP3 => crate::mp3::write::write_to(file, tag),
#[cfg(feature = "mp4_ilst")] #[cfg(feature = "mp4_ilst")]
FileType::MP4 => mp4::ilst::write::write_to(file, &mut Into::<IlstRef>::into(tag)), FileType::MP4 => crate::mp4::ilst::write::write_to(file, &mut Into::<IlstRef>::into(tag)),
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
FileType::Opus => ogg::write::write_to(file, tag, OPUSTAGS), FileType::Opus => crate::ogg::write::write_to(file, tag, OPUSTAGS),
#[cfg(feature = "vorbis_comments")] #[cfg(feature = "vorbis_comments")]
FileType::Vorbis => ogg::write::write_to(file, tag, VORBIS_COMMENT_HEAD), FileType::Vorbis => crate::ogg::write::write_to(file, tag, VORBIS_COMMENT_HEAD),
FileType::WAV => iff::wav::write::write_to(file, tag), FileType::WAV => crate::iff::wav::write::write_to(file, tag),
_ => Err(LoftyError::UnsupportedTag), _ => Err(LoftyError::UnsupportedTag),
} }
} }
macro_rules! tag_methods { macro_rules! tag_methods {
($( (
$(
$(#[$attr:meta])?; $(#[$attr:meta])?;
$display_name:tt, $display_name:tt,
$name:ident, $name:ident,
$ty:ty);* $ty:ty
);*
) => { ) => {
paste::paste! { paste::paste! {
$( $(
@ -68,11 +65,11 @@ macro_rules! tag_methods {
} }
} }
pub(in crate::logic) use tag_methods; pub(crate) use tag_methods;
#[cfg(test)] #[cfg(test)]
// Used for tag conversion tests // Used for tag conversion tests
mod test_utils { pub(crate) mod test_utils {
use crate::{ItemKey, Tag, TagType}; use crate::{ItemKey, Tag, TagType};
pub(crate) fn create_tag(tag_type: TagType) -> Tag { pub(crate) fn create_tag(tag_type: TagType) -> Tag {

View file

@ -283,7 +283,7 @@ impl FileType {
} }
pub(crate) fn from_buffer_inner(buf: &[u8]) -> Result<(Option<Self>, u32)> { pub(crate) fn from_buffer_inner(buf: &[u8]) -> Result<(Option<Self>, u32)> {
use crate::logic::id3::v2::unsynch_u32; use crate::id3::v2::unsynch_u32;
if buf.is_empty() { if buf.is_empty() {
return Err(LoftyError::EmptyFile); return Err(LoftyError::EmptyFile);
@ -306,7 +306,7 @@ impl FileType {
} }
fn quick_type_guess(buf: &[u8]) -> Option<Self> { fn quick_type_guess(buf: &[u8]) -> Option<Self> {
use crate::logic::mp3::header::verify_frame_sync; use crate::mp3::header::verify_frame_sync;
match buf.first().unwrap() { match buf.first().unwrap() {
77 if buf.starts_with(b"MAC") => Some(Self::APE), 77 if buf.starts_with(b"MAC") => Some(Self::APE),

View file

@ -610,7 +610,7 @@ impl TagItem {
pub(crate) fn re_map(&self, tag_type: TagType) -> Option<()> { pub(crate) fn re_map(&self, tag_type: TagType) -> Option<()> {
#[cfg(feature = "id3v1")] #[cfg(feature = "id3v1")]
if tag_type == TagType::Id3v1 { if tag_type == TagType::Id3v1 {
use crate::logic::id3::v1::constants::VALID_ITEMKEYS; use crate::id3::v1::constants::VALID_ITEMKEYS;
return VALID_ITEMKEYS.contains(&self.item_key).then(|| ()); return VALID_ITEMKEYS.contains(&self.item_key).then(|| ());
} }

View file

@ -1,6 +1,6 @@
use crate::{LoftyError, Result}; use crate::{LoftyError, Result};
#[cfg(feature = "id3v2")] #[cfg(feature = "id3v2")]
use {crate::logic::id3::v2::util::text_utils::TextEncoding, crate::logic::id3::v2::Id3v2Version}; use {crate::id3::v2::util::text_utils::TextEncoding, crate::id3::v2::Id3v2Version};
use std::borrow::Cow; use std::borrow::Cow;
#[cfg(any(feature = "vorbis_comments", feature = "ape", feature = "id3v2"))] #[cfg(any(feature = "vorbis_comments", feature = "ape", feature = "id3v2"))]
@ -587,13 +587,9 @@ impl Picture {
data.write_u8(self.pic_type.as_u8())?; data.write_u8(self.pic_type.as_u8())?;
match &self.description { match &self.description {
Some(description) => { Some(description) => data.write_all(
data.write_all(&*crate::logic::id3::v2::util::text_utils::encode_text( &*crate::id3::v2::util::text_utils::encode_text(description, text_encoding, true),
description, )?,
text_encoding,
true,
))?
},
None => data.write_u8(0)?, None => data.write_u8(0)?,
} }
@ -643,18 +639,14 @@ impl Picture {
}, },
} }
} else { } else {
(crate::logic::id3::v2::util::text_utils::decode_text( (crate::id3::v2::util::text_utils::decode_text(&mut cursor, TextEncoding::UTF8, true)?)
&mut cursor,
TextEncoding::UTF8,
true,
)?)
.map_or(MimeType::None, |mime_type| MimeType::from_str(&*mime_type)) .map_or(MimeType::None, |mime_type| MimeType::from_str(&*mime_type))
}; };
let picture_type = PictureType::from_u8(cursor.read_u8()?); let picture_type = PictureType::from_u8(cursor.read_u8()?);
let description = let description =
crate::logic::id3::v2::util::text_utils::decode_text(&mut cursor, encoding, true)? crate::id3::v2::util::text_utils::decode_text(&mut cursor, encoding, true)?
.map(Cow::from); .map(Cow::from);
let mut data = Vec::new(); let mut data = Vec::new();

View file

@ -289,7 +289,7 @@ impl Tag {
match probe.file_type() { match probe.file_type() {
Some(file_type) => { Some(file_type) => {
if file_type.supports_tag_type(self.tag_type()) { if file_type.supports_tag_type(self.tag_type()) {
crate::logic::write_tag(self, probe.into_inner(), file_type) crate::tag_utils::write_tag(self, probe.into_inner(), file_type)
} else { } else {
Err(LoftyError::UnsupportedTag) Err(LoftyError::UnsupportedTag)
} }
@ -354,7 +354,7 @@ impl TagType {
if file_type.supports_tag_type(self) { if file_type.supports_tag_type(self) {
let file = probe.into_inner(); let file = probe.into_inner();
return crate::logic::write_tag(&Tag::new(*self), file, file_type).is_ok(); return crate::tag_utils::write_tag(&Tag::new(*self), file, file_type).is_ok();
} }
} }
} }