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;
pub(crate) mod properties;
pub(crate) mod read;
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::logic::id3::v1::tag::Id3v1Tag;
use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods;
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 properties::ApeProperties;
#[cfg(feature = "ape")]
use tag::ape_tag::ApeTag;
use std::io::{Read, Seek};

View file

@ -2,13 +2,13 @@ use super::constants::APE_PREAMBLE;
#[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::{LoftyError, Result};
use crate::logic::ape::tag::read_ape_header;
#[cfg(feature = "id3v1")]
use crate::logic::id3::v1::tag::Id3v1Tag;
use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::{read::parse_id3v2, tag::Id3v2Tag};
use crate::logic::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use crate::id3::v2::{read::parse_id3v2, tag::Id3v2Tag};
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
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::logic::ape::tag::item::{ApeItem, ApeItemRef};
use crate::types::item::{ItemKey, ItemValue, TagItem};
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(super) items: Box<dyn Iterator<Item = ApeItemRef<'a>> + 'a>,
}
@ -239,7 +239,7 @@ mod tests {
use crate::ape::{ApeItem, ApeTag};
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};
#[test]
@ -300,7 +300,7 @@ mod tests {
let mut reader = Cursor::new(tag);
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());
@ -321,11 +321,11 @@ mod tests {
let mut reader = Cursor::new(tag_bytes);
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();
crate::logic::test_utils::verify_tag(&tag, true, true);
crate::tag_utils::test_utils::verify_tag(&tag, true, true);
}
#[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();

View file

@ -1,5 +1,5 @@
use crate::ape::constants::INVALID_KEYS;
use crate::error::{LoftyError, Result};
use crate::logic::ape::constants::INVALID_KEYS;
use crate::types::item::{ItemValue, ItemValueRef, TagItem};
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 key: &'a str,
pub value: ItemValueRef<'a>,

View file

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

View file

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

View file

@ -1,8 +1,8 @@
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::logic::ape::constants::APE_PREAMBLE;
use crate::logic::ape::tag::ape_tag::ApeTagRef;
use crate::logic::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
use crate::probe::Probe;
use crate::types::file::FileType;
use crate::types::item::ItemValueRef;
@ -10,11 +10,11 @@ use crate::types::item::ItemValueRef;
use std::fs::File;
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};
#[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()?;
match probe.file_type() {

View file

@ -1,15 +1,15 @@
use crate::error::{LoftyError, Result};
#[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")]
use crate::logic::id3::v1::tag::Id3v1TagRef;
use crate::id3::v1::tag::Id3v1TagRef;
#[allow(unused_imports)]
use crate::types::tag::{Tag, TagType};
use std::fs::File;
#[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() {
#[cfg(feature = "ape")]
TagType::Ape => Into::<ApeTagRef>::into(tag).write_to(data),

View file

@ -1,7 +1,8 @@
use ogg_pager::PageError;
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>;
/// Errors that could occur within Lofty
@ -21,7 +22,7 @@ pub enum LoftyError {
// Picture related errors
#[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),
/// Provided an invalid picture
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")]
pub(crate) mod v1;
pub(crate) mod v2;
pub mod v1;
pub mod v2;
use crate::error::{LoftyError, Result};
use v2::{read_id3v2_header, Id3v2Header};
@ -37,10 +42,7 @@ where
}
#[cfg(feature = "id3v1")]
pub(in crate::logic) fn find_id3v1<R>(
data: &mut R,
read: bool,
) -> Result<(bool, Option<v1::tag::Id3v1Tag>)>
pub(crate) fn find_id3v1<R>(data: &mut R, read: bool) -> Result<(bool, Option<v1::tag::Id3v1Tag>)>
where
R: Read + Seek,
{
@ -74,7 +76,7 @@ where
}
#[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
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::logic::id3::v1::constants::GENRES;
use crate::id3::v1::constants::GENRES;
use crate::types::item::{ItemKey, ItemValue, TagItem};
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 artist: Option<&'a str>,
pub album: Option<&'a str>,
@ -263,7 +263,7 @@ mod tests {
.read_exact(&mut tag)
.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);
}
@ -276,16 +276,16 @@ mod tests {
.read_exact(&mut tag_bytes)
.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();
crate::logic::test_utils::verify_tag(&tag, true, true);
crate::tag_utils::test_utils::verify_tag(&tag, true, true);
}
#[test]
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();

View file

@ -1,6 +1,6 @@
use super::tag::Id3v1TagRef;
use crate::error::{LoftyError, Result};
use crate::logic::id3::find_id3v1;
use crate::id3::find_id3v1;
use crate::probe::Probe;
use crate::types::file::FileType;
@ -10,7 +10,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::WriteBytesExt;
#[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()?;
match probe.file_type() {

View file

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

View file

@ -1,7 +1,7 @@
use super::FrameFlags;
use crate::error::{LoftyError, Result};
use crate::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
use crate::id3::v2::FrameID;
use crate::logic::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
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, 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[5],
frame_header[6],

View file

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

View file

@ -1,9 +1,9 @@
use super::header::{parse_header, parse_v2_header};
use super::Frame;
use crate::error::{LoftyError, Result};
use crate::id3::v2::frame::content::parse_content;
use crate::id3::v2::FrameValue;
use crate::logic::id3::v2::frame::content::parse_content;
use crate::logic::id3::v2::Id3v2Version;
use crate::id3::v2::Id3v2Version;
use std::io::Read;
@ -28,7 +28,7 @@ impl Frame {
reader.read_exact(&mut content)?;
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 {

View file

@ -1,5 +1,5 @@
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};

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 crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::text_utils;
use crate::logic::id3::v2::util::text_utils::{
use crate::id3::v2::util::text_utils;
use crate::id3::v2::util::text_utils::{
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")]
pub(crate) mod frame;
mod frame;
#[cfg(feature = "id3v2")]
pub(crate) mod items;
mod items;
#[cfg(feature = "id3v2")]
pub(crate) mod read;
#[cfg(feature = "id3v2")]
pub(crate) mod tag;
pub(crate) mod util;
#[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};
#[cfg(feature = "id3v2_restrictions")]
use crate::logic::id3::v2::items::restrictions::TagRestrictions;
use flags::Id3v2TagFlags;
use crate::id3::v2::items::restrictions::TagRestrictions;
use std::io::Read;

View file

@ -4,7 +4,7 @@ use super::frame::{Frame, FrameID, FrameValue};
use super::util::text_utils::TextEncoding;
use super::Id3v2Version;
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::tag::{Accessor, Tag, TagType};
@ -300,7 +300,7 @@ pub(crate) struct 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)
}
}
@ -333,7 +333,7 @@ mod tests {
use crate::id3::v2::{Frame, FrameFlags, FrameValue, Id3v2Tag, LanguageFrame, TextEncoding};
use crate::{Tag, TagType};
use crate::logic::id3::v2::read_id3v2_header;
use crate::id3::v2::read_id3v2_header;
use std::io::Read;
#[test]
@ -439,7 +439,7 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag[..]);
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);
}
@ -456,11 +456,11 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag_bytes[..]);
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();
crate::logic::test_utils::verify_tag(&tag, true, true);
crate::tag_utils::test_utils::verify_tag(&tag, true, true);
}
#[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();

View file

@ -6,7 +6,7 @@ pub(crate) mod upgrade;
use crate::error::{LoftyError, Result};
#[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 discard = false;

View file

@ -1,23 +1,39 @@
use std::collections::HashMap;
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
pub fn upgrade_v2(key: &str) -> Option<&'static str> {
match key {
$(
$($v2_key)|* => Some($id3v24_from_v2),
)+
_ => None
}
V2KEYS.get(key).map(|s| *s)
}
/// Upgrade an ID3v2.3 key to an ID3v2.4 key
pub fn upgrade_v3(key: &str) -> Option<&'static str> {
match key {
$(
$($v3_key)|* => Some($id3v24_from_v3),
)+
_ => None
}
V3KEYS.get(key).map(|s| *s)
}
}
}

View file

@ -1,12 +1,12 @@
use crate::error::Result;
use crate::logic::iff::chunk::Chunks;
use crate::iff::chunk::Chunks;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
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
B: ByteOrder,
{

View file

@ -1,13 +1,13 @@
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::logic::id3::v2::frame::{FrameFlags, FrameRef, FrameValueRef};
use crate::logic::id3::v2::synch_u32;
use std::io::Write;
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,
frames: &mut dyn Iterator<Item = FrameRef<'a>>,
) -> Result<()>

View file

@ -3,8 +3,8 @@ mod frame;
use super::Id3v2TagFlags;
use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::tag::Id3v2TagRef;
use crate::logic::id3::{find_id3v2, v2::synch_u32};
use crate::id3::v2::tag::Id3v2TagRef;
use crate::id3::{find_id3v2, v2::synch_u32};
use crate::probe::Probe;
use crate::types::file::FileType;
@ -14,7 +14,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
#[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()?;
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
pub(in crate::logic) fn write_id3v2_to_chunk_file<B>(
data: &mut File,
tag: &mut Id3v2TagRef,
) -> Result<()>
fn write_id3v2_to_chunk_file<B>(data: &mut File, tag: &mut Id3v2TagRef) -> Result<()>
where
B: ByteOrder,
{

View file

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

View file

@ -3,15 +3,15 @@ use super::tag::AiffTextChunks;
use super::AiffFile;
use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag;
use crate::logic::iff::chunk::Chunks;
use crate::id3::v2::tag::Id3v2Tag;
use crate::iff::chunk::Chunks;
use crate::types::properties::FileProperties;
use std::io::{Read, Seek, SeekFrom};
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
R: Read + Seek,
{
@ -25,7 +25,7 @@ where
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
R: Read + Seek,
{

View file

@ -1,5 +1,5 @@
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::tag::{Accessor, Tag, TagType};
@ -146,12 +146,12 @@ impl<'a> Into<AiffTextChunksRef<'a>> for &'a Tag {
}
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)
}
}
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>) {
if let Some(val) = value {
if let Ok(len) = u32::try_from(val.len()) {

View file

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

View file

@ -1,16 +1,16 @@
use crate::error::Result;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::read::parse_id3v2;
use crate::id3::v2::read::parse_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::marker::PhantomData;
use crate::logic::id3::v2::read_id3v2_header;
use crate::id3::v2::read_id3v2_header;
use byteorder::{ByteOrder, ReadBytesExt};
pub(in crate::logic) struct Chunks<B>
pub(crate) struct Chunks<B>
where
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;
#[cfg(feature = "riff_info_list")]
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;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods;
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 properties::WavProperties;
#[cfg(feature = "riff_info_list")]
use tag::RiffInfoList;

View file

@ -4,14 +4,14 @@ use super::tag::RiffInfoList;
use super::WavFile;
use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag;
use crate::logic::iff::chunk::Chunks;
use crate::id3::v2::tag::Id3v2Tag;
use crate::iff::chunk::Chunks;
use std::io::{Read, Seek, SeekFrom};
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
T: Read + Seek,
{
@ -29,7 +29,7 @@ where
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
R: Read + Seek,
{

View file

@ -1,5 +1,5 @@
pub(in crate::logic::iff::wav) mod read;
pub(in crate::logic::iff::wav) mod write;
pub(super) mod read;
mod write;
use crate::error::Result;
use crate::types::item::{ItemKey, ItemValue, TagItem};
@ -243,12 +243,12 @@ mod tests {
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]
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();

View file

@ -1,12 +1,12 @@
use super::RiffInfoList;
use crate::error::{LoftyError, Result};
use crate::logic::iff::chunk::Chunks;
use crate::iff::chunk::Chunks;
use std::io::{Read, Seek, SeekFrom};
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,
end: u64,
tag: &mut RiffInfoList,

View file

@ -1,14 +1,14 @@
use super::RiffInfoListRef;
use crate::error::{LoftyError, Result};
use crate::logic::iff::chunk::Chunks;
use crate::logic::iff::wav::read::verify_wav;
use crate::iff::chunk::Chunks;
use crate::iff::wav::read::verify_wav;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
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,
tag: &mut RiffInfoListRef,
) -> Result<()> {

View file

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

View file

@ -150,9 +150,15 @@
clippy::single_match_else
)]
pub mod ape;
mod error;
pub(crate) mod logic;
pub mod id3;
pub mod iff;
pub mod mp3;
pub mod mp4;
pub mod ogg;
mod probe;
pub(crate) mod tag_utils;
mod types;
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 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;
pub(crate) mod header;
pub(crate) mod properties;
pub(crate) mod read;
pub(in crate::logic) mod write;
mod properties;
mod read;
pub(crate) mod write;
pub use header::{ChannelMode, Layer, MpegVersion};
pub use properties::Mp3Properties;
use crate::error::Result;
#[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")]
use crate::logic::id3::v1::tag::Id3v1Tag;
use crate::id3::v1::tag::Id3v1Tag;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2Tag;
use crate::logic::tag_methods;
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 properties::Mp3Properties;
use std::io::{Read, Seek};

View file

@ -1,16 +1,16 @@
use super::header::{verify_frame_sync, Header, XingHeader};
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};
#[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")]
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};
@ -85,7 +85,7 @@ where
#[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;
@ -105,9 +105,7 @@ where
#[cfg(feature = "ape")]
{
ape_tag = Some(crate::logic::ape::tag::read::read_ape_tag(
data, ape_header,
)?);
ape_tag = Some(crate::ape::tag::read::read_ape_tag(data, ape_header)?);
}
continue;

View file

@ -1,10 +1,10 @@
use crate::error::{LoftyError, Result};
#[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")]
use crate::logic::id3::v1::tag::Id3v1TagRef;
use crate::id3::v1::tag::Id3v1TagRef;
#[cfg(feature = "id3v2")]
use crate::logic::id3::v2::tag::Id3v2TagRef;
use crate::id3::v2::tag::Id3v2TagRef;
#[allow(unused_imports)]
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;
#[derive(Debug, PartialEq, Clone)]

View file

@ -1,6 +1,6 @@
pub(crate) mod atom;
pub(in crate::logic::mp4) mod read;
pub(in crate::logic) mod write;
pub(super) mod atom;
pub(super) mod read;
pub(crate) mod write;
use super::AtomIdent;
use crate::error::Result;
@ -221,7 +221,7 @@ pub(crate) struct 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)
}
}
@ -355,7 +355,7 @@ mod tests {
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]
@ -368,7 +368,7 @@ mod tests {
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();

View file

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

View file

@ -1,9 +1,9 @@
use super::{AtomDataRef, IlstRef};
use crate::error::{LoftyError, Result};
use crate::logic::mp4::ilst::{AtomIdentRef, AtomRef};
use crate::logic::mp4::moov::Moov;
use crate::logic::mp4::read::nested_atom;
use crate::logic::mp4::read::verify_mp4;
use crate::mp4::ilst::{AtomIdentRef, AtomRef};
use crate::mp4::moov::Moov;
use crate::mp4::read::nested_atom;
use crate::mp4::read::verify_mp4;
use crate::types::picture::MimeType;
use crate::types::picture::Picture;
@ -12,7 +12,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
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)?;
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;
#[cfg(feature = "mp4_ilst")]
pub(crate) mod ilst;
mod moov;
pub(crate) mod properties;
mod properties;
mod read;
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::{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};

View file

@ -6,7 +6,7 @@ use crate::error::{LoftyError, Result};
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
R: Read + Seek,
{

View file

@ -15,7 +15,7 @@ pub(super) struct 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
R: Read + Seek,
{

View file

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

View file

@ -2,7 +2,7 @@ use super::block::Block;
use super::FlacFile;
use crate::error::{LoftyError, Result};
#[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")]
use crate::types::picture::Picture;
use crate::types::properties::FileProperties;

View file

@ -1,8 +1,8 @@
use super::block::Block;
use super::read::verify_flac;
use crate::error::{LoftyError, Result};
use crate::logic::ogg::tag::VorbisCommentsRef;
use crate::logic::ogg::write::create_comments;
use crate::ogg::tag::VorbisCommentsRef;
use crate::ogg::write::create_comments;
use crate::types::picture::{Picture, PictureInformation};
use std::fs::File;
@ -10,7 +10,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
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_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 read;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod write;
pub(crate) mod flac;
pub(crate) mod opus;
pub(crate) mod read;
#[cfg(feature = "vorbis_comments")]
pub(crate) mod tag;
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};
@ -16,7 +26,7 @@ use std::io::{Read, Seek};
use ogg_pager::Page;
#[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 reader = &mut &packet[..];

View file

@ -1,4 +1,4 @@
pub(crate) mod properties;
pub(super) mod properties;
#[cfg(feature = "vorbis_comments")]
pub(super) mod write;
@ -6,7 +6,7 @@ use super::find_last_page;
#[cfg(feature = "vorbis_comments")]
use super::tag::VorbisComments;
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::properties::FileProperties;
use crate::types::tag::TagType;

View file

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

View file

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

View file

@ -1,5 +1,5 @@
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::types::file::FileType;
use crate::types::item::{ItemKey, ItemValue, TagItem};
@ -253,7 +253,7 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag[..]);
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);
}
@ -269,16 +269,16 @@ mod tests {
let mut reader = std::io::Cursor::new(&tag_bytes[..]);
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();
crate::logic::test_utils::verify_tag(&tag, true, true);
crate::tag_utils::test_utils::verify_tag(&tag, true, true);
}
#[test]
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();

View file

@ -1,12 +1,12 @@
pub(crate) mod properties;
pub(super) mod properties;
#[cfg(feature = "vorbis_comments")]
pub(in crate::logic::ogg) mod write;
pub(in crate::ogg) mod write;
use super::find_last_page;
#[cfg(feature = "vorbis_comments")]
use super::tag::VorbisComments;
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::properties::FileProperties;
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,
first_page: &Page,
) -> Result<VorbisProperties>

View file

@ -1,5 +1,5 @@
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::io::{Cursor, Read, Seek, SeekFrom, Write};
@ -7,7 +7,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, ReadBytesExt};
use ogg_pager::Page;
pub(in crate::logic) fn write_to(
pub(crate) fn write_to(
data: &mut File,
writer: &mut Vec<u8>,
first_md_content: Vec<u8>,

View file

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

View file

@ -1,13 +1,13 @@
use crate::ape::ApeFile;
use crate::error::{LoftyError, Result};
use crate::logic::ape::ApeFile;
use crate::logic::iff::aiff::AiffFile;
use crate::logic::iff::wav::WavFile;
use crate::logic::mp3::header::verify_frame_sync;
use crate::logic::mp3::Mp3File;
use crate::logic::mp4::Mp4File;
use crate::logic::ogg::flac::FlacFile;
use crate::logic::ogg::opus::OpusFile;
use crate::logic::ogg::vorbis::VorbisFile;
use crate::iff::aiff::AiffFile;
use crate::iff::wav::WavFile;
use crate::mp3::header::verify_frame_sync;
use crate::mp3::Mp3File;
use crate::mp4::Mp4File;
use crate::ogg::flac::FlacFile;
use crate::ogg::opus::OpusFile;
use crate::ogg::vorbis::VorbisFile;
use crate::types::file::{AudioFile, FileType, TaggedFile};
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::types::file::FileType;
use crate::types::tag::Tag;
#[cfg(feature = "mp4_ilst")]
use mp4::ilst::IlstRef;
use crate::mp4::ilst::IlstRef;
#[cfg(feature = "vorbis_comments")]
use ogg::{
use crate::ogg::{
constants::{OPUSTAGS, VORBIS_COMMENT_HEAD},
tag::VorbisCommentsRef,
};
use crate::types::file::FileType;
use crate::types::tag::Tag;
use std::fs::File;
#[allow(unreachable_patterns)]
pub(crate) fn write_tag(tag: &Tag, file: &mut File, file_type: FileType) -> Result<()> {
match file_type {
FileType::AIFF => iff::aiff::write::write_to(file, tag),
FileType::APE => ape::write::write_to(file, tag),
FileType::AIFF => crate::iff::aiff::write::write_to(file, tag),
FileType::APE => crate::ape::write::write_to(file, tag),
#[cfg(feature = "vorbis_comments")]
FileType::FLAC => ogg::flac::write::write_to(file, &mut Into::<VorbisCommentsRef>::into(tag)),
FileType::MP3 => mp3::write::write_to(file, tag),
FileType::FLAC => {
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")]
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")]
FileType::Opus => ogg::write::write_to(file, tag, OPUSTAGS),
FileType::Opus => crate::ogg::write::write_to(file, tag, OPUSTAGS),
#[cfg(feature = "vorbis_comments")]
FileType::Vorbis => ogg::write::write_to(file, tag, VORBIS_COMMENT_HEAD),
FileType::WAV => iff::wav::write::write_to(file, tag),
FileType::Vorbis => crate::ogg::write::write_to(file, tag, VORBIS_COMMENT_HEAD),
FileType::WAV => crate::iff::wav::write::write_to(file, tag),
_ => Err(LoftyError::UnsupportedTag),
}
}
macro_rules! tag_methods {
($(
(
$(
$(#[$attr:meta])?;
$display_name:tt,
$name:ident,
$ty:ty);*
$ty:ty
);*
) => {
paste::paste! {
$(
@ -68,11 +65,11 @@ macro_rules! tag_methods {
}
}
pub(in crate::logic) use tag_methods;
pub(crate) use tag_methods;
#[cfg(test)]
// Used for tag conversion tests
mod test_utils {
pub(crate) mod test_utils {
use crate::{ItemKey, Tag, TagType};
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)> {
use crate::logic::id3::v2::unsynch_u32;
use crate::id3::v2::unsynch_u32;
if buf.is_empty() {
return Err(LoftyError::EmptyFile);
@ -306,7 +306,7 @@ impl FileType {
}
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() {
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<()> {
#[cfg(feature = "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(|| ());
}

View file

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

View file

@ -289,7 +289,7 @@ impl Tag {
match probe.file_type() {
Some(file_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 {
Err(LoftyError::UnsupportedTag)
}
@ -354,7 +354,7 @@ impl TagType {
if file_type.supports_tag_type(self) {
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();
}
}
}