Move TagItem structs out of types::tag

This commit is contained in:
Serial 2021-09-13 17:08:16 -04:00
parent 12fc701e1d
commit 58354679c5
18 changed files with 195 additions and 187 deletions

View file

@ -133,11 +133,14 @@ pub use crate::probe::Probe;
pub use crate::types::{
file::{FileType, TaggedFile},
item::ItemKey,
item::{ItemKey, ItemValue, TagItem},
properties::FileProperties,
tag::{ItemValue, Tag, TagItem, TagItemFlags, TagType},
tag::{Tag, TagType},
};
#[cfg(any(feature = "id3v2", feature = "ape"))]
pub use crate::types::item::TagItemFlags;
mod types;
/// Various concrete file types, used when inference is unnecessary

View file

@ -1,7 +1,7 @@
use crate::error::{LoftyError, Result};
use crate::logic::ape::constants::INVALID_KEYS;
use crate::types::item::ItemKey;
use crate::types::tag::{ItemValue, Tag, TagItem, TagItemFlags, TagType};
use crate::types::item::{ItemKey, ItemValue, TagItem, TagItemFlags};
use crate::types::tag::{Tag, TagType};
use std::io::{Read, Seek, SeekFrom};
use std::ops::Neg;

View file

@ -4,8 +4,9 @@ use crate::logic::ape::constants::APE_PREAMBLE;
use crate::logic::id3::find_lyrics3v2;
use crate::logic::id3::v1::find_id3v1;
use crate::logic::id3::v2::find_id3v2;
use crate::types::item::{ItemValue, TagItem};
use crate::types::picture::Picture;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::tag::{Tag, TagType};
use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};

View file

@ -1,7 +1,7 @@
use super::constants::GENRES;
use crate::error::Result;
use crate::types::item::ItemKey;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Tag, TagType};
use byteorder::WriteBytesExt;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};

View file

@ -1,6 +1,6 @@
use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::util::upgrade::{upgrade_v2, upgrade_v3};
use crate::types::tag::TagItemFlags;
use crate::types::item::TagItemFlags;
use std::io::Read;

View file

@ -4,7 +4,7 @@ mod header;
use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::frame::content::{parse_content, FrameContent};
use crate::logic::id3::v2::Id3v2Version;
use crate::types::tag::TagItemFlags;
use crate::types::item::TagItemFlags;
use header::{parse_header, parse_v2_header};
use std::io::Read;

View file

@ -1,9 +1,9 @@
use super::AiffFile;
use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::read::parse_id3v2;
use crate::types::item::ItemKey;
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::properties::FileProperties;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::tag::{Tag, TagType};
use std::io::{Read, Seek, SeekFrom};
use std::time::Duration;

View file

@ -1,7 +1,7 @@
use super::read::verify_aiff;
use crate::error::{LoftyError, Result};
use crate::types::item::ItemKey;
use crate::types::tag::{ItemValue, Tag, TagType};
use crate::types::item::{ItemKey, ItemValue};
use crate::types::tag::{Tag, TagType};
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};

View file

@ -1,9 +1,9 @@
use super::WavFile;
use crate::error::{LoftyError, Result};
use crate::logic::id3::v2::read::parse_id3v2;
use crate::types::item::ItemKey;
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::properties::FileProperties;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::tag::{Tag, TagType};
use std::io::{Read, Seek, SeekFrom};
use std::time::Duration;

View file

@ -1,6 +1,7 @@
use super::read::verify_wav;
use crate::error::{LoftyError, Result};
use crate::types::tag::{ItemValue, Tag, TagType};
use crate::types::item::ItemValue;
use crate::types::tag::{Tag, TagType};
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};

View file

@ -3,9 +3,9 @@ use crate::logic::id3::v2::util::text_utils::utf16_decode;
use crate::logic::id3::v2::TextEncoding;
use crate::logic::mp4::atom::Atom;
use crate::logic::mp4::read::skip_unneeded;
use crate::types::item::ItemKey;
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::picture::{MimeType, Picture, PictureInformation, PictureType};
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::tag::{Tag, TagType};
use std::borrow::Cow;
use std::io::{Cursor, Read, Seek, SeekFrom};

View file

@ -2,14 +2,15 @@ use crate::error::{LoftyError, Result};
use crate::logic::mp4::moov::Moov;
use crate::logic::mp4::read::nested_atom;
use crate::logic::mp4::read::verify_mp4;
use crate::types::tag::{ItemValue, Tag, TagType};
use crate::picture::MimeType;
use crate::types::item::ItemValue;
use crate::types::picture::Picture;
use crate::types::tag::{Tag, TagType};
use std::convert::TryInto;
use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use crate::picture::MimeType;
use crate::types::picture::Picture;
use byteorder::{BigEndian, WriteBytesExt};
pub(in crate::logic) fn write_to(data: &mut File, tag: &Tag) -> Result<()> {

View file

@ -3,8 +3,8 @@ use super::read::verify_flac;
use crate::error::{LoftyError, Result};
use crate::logic::ogg::write::create_comments;
use crate::picture::Picture;
use crate::types::item::ItemKey;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Tag, TagType};
use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};

View file

@ -2,9 +2,9 @@ use super::verify_signature;
use crate::error::{LoftyError, Result};
use crate::logic::ogg::constants::OPUSHEAD;
use crate::picture::Picture;
use crate::types::item::ItemKey;
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::properties::FileProperties;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::tag::{Tag, TagType};
use std::io::{Read, Seek, SeekFrom};

View file

@ -2,8 +2,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::types::item::ItemKey;
use crate::types::tag::{ItemValue, Tag, TagItem, TagType};
use crate::types::item::{ItemKey, ItemValue, TagItem};
use crate::types::tag::{Tag, TagType};
use std::convert::TryFrom;
use std::fs::File;

View file

@ -1,6 +1,6 @@
use super::item::ItemKey;
use super::item::{ItemKey, ItemValue, TagItem};
use super::properties::FileProperties;
use super::tag::{ItemValue, Tag, TagItem, TagType};
use super::tag::{Tag, TagType};
use crate::error::{LoftyError, Result};
use crate::logic::ape::ApeFile;
use crate::logic::iff::aiff::AiffFile;

View file

@ -423,3 +423,161 @@ item_keys!(
TagType::VorbisComments => "LYRICS", TagType::Ape => "Lyrics"
]
);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// Represents a tag item's value
///
/// NOTES:
///
/// * The [Locator][ItemValue::Locator] variant is only applicable to APE and ID3v2 tags.
/// * The [Binary][ItemValue::Binary] variant is only applicable to APE tags.
/// * Attempting to write either to another file/tag type will **not** error, they will just be ignored.
pub enum ItemValue {
/// Any UTF-8 encoded text
Text(String),
/// **(APE/ID3v2 ONLY)** Any UTF-8 encoded locator of external information
Locator(String),
/// **(APE/ID3v2/MP4 ONLY)** Binary information
///
/// In the case of ID3v2, this is the type of a [`Id3v2Frame::EncapsulatedObject`](crate::id3::Id3v2Frame::EncapsulatedObject) **and** any unknown frame.
///
/// For APEv2, no uses of this item type are documented, there's no telling what it could be.
Binary(Vec<u8>),
/// Any 32 bit unsigned integer
///
/// This is most commonly used for items such as track and disc numbers
UInt(u32),
/// **(MP4 ONLY)** Any 64 bit unsigned integer
///
/// There are no common [`ItemKey`]s that use this
UInt64(u64),
/// Any 32 bit signed integer
///
/// There are no common [`ItemKey`]s that use this
Int(i32),
/// **(MP4 ONLY)** Any 64 bit signed integer
///
/// There are no common [`ItemKey`]s that use this
Int64(i64),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** The content of a synchronized text frame, see [`SynchronizedText`](crate::id3::SynchronizedText)
SynchronizedText(Vec<(u32, String)>),
}
#[cfg(any(feature = "id3v2", feature = "ape"))]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
#[allow(clippy::struct_excessive_bools)]
/// **(ID3v2/APEv2 ONLY)** Various flags to describe the content of an item
///
/// It is not an error to attempt to write flags to a format that doesn't support them.
/// They will just be ignored.
pub struct TagItemFlags {
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Preserve frame on tag edit
pub tag_alter_preservation: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Preserve frame on file edit
pub file_alter_preservation: bool,
#[cfg(any(feature = "id3v2", feature = "ape"))]
/// **(ID3v2/APEv2 ONLY)** Item cannot be written to
pub read_only: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame belongs in a group
///
/// In addition to setting this flag, a group identifier byte must be added.
/// All frames with the same group identifier byte belong to the same group.
pub grouping_identity: (bool, u8),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is zlib compressed
///
/// It is **required** `data_length_indicator` be set if this is set.
pub compression: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is encrypted
///
/// NOTE: Since the encryption method is unknown, lofty cannot do anything with these frames
///
/// In addition to setting this flag, an encryption method symbol must be added.
/// The method symbol **must** be > 0x80.
pub encryption: (bool, u8),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is unsynchronised
///
/// In short, this makes all "0xFF 0x00" combinations into "0xFF 0x00 0x00" to avoid confusion
/// with the MPEG frame header, which is often identified by its "frame sync" (11 set bits).
/// It is preferred an ID3v2 tag is either *completely* unsynchronised or not unsynchronised at all.
pub unsynchronisation: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame has a data length indicator
///
/// The data length indicator is the size of the frame if the flags were all zeroed out.
/// This is usually used in combination with `compression` and `encryption` (depending on encryption method).
///
/// In addition to setting this flag, the final size must be added.
pub data_length_indicator: (bool, u32),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// Represents a tag item (key/value)
pub struct TagItem {
pub(crate) item_key: ItemKey,
pub(crate) item_value: ItemValue,
#[cfg(any(feature = "id3v2", feature = "ape"))]
pub(crate) flags: TagItemFlags,
}
impl TagItem {
/// Create a new [`TagItem`]
///
/// NOTES:
///
/// * This will check for validity based on the [`TagType`].
/// * If the [`ItemKey`] does not map to a key in the target format, `None` will be returned.
/// * It is pointless to do this if you plan on using [`Tag::insert_item`], as it does validity checks itself.
pub fn new_checked(
tag_type: &TagType,
item_key: ItemKey,
item_value: ItemValue,
) -> Option<Self> {
item_key.map_key(tag_type).is_some().then(|| Self {
item_key,
item_value,
flags: TagItemFlags::default(),
})
}
/// Create a new [`TagItem`]
pub fn new(item_key: ItemKey, item_value: ItemValue) -> Self {
Self {
item_key,
item_value,
flags: TagItemFlags::default(),
}
}
#[cfg(any(feature = "id3v2", feature = "ape"))]
/// Returns a reference to the [`TagItemFlags`]
pub fn flags(&self) -> &TagItemFlags {
&self.flags
}
#[cfg(any(feature = "id3v2", feature = "ape"))]
/// Set the item's flags
pub fn set_flags(&mut self, flags: TagItemFlags) {
self.flags = flags
}
/// Returns a reference to the [`ItemKey`]
pub fn key(&self) -> &ItemKey {
&self.item_key
}
/// Returns a reference to the [`ItemValue`]
pub fn value(&self) -> &ItemValue {
&self.item_value
}
pub(crate) fn re_map(&self, tag_type: &TagType) -> Option<()> {
self.item_key.map_key(tag_type).is_some().then(|| ())
}
}

View file

@ -1,13 +1,12 @@
use super::item::ItemKey;
use super::item::{ItemKey, ItemValue, TagItem};
use super::picture::{Picture, PictureType};
use crate::error::Result;
use crate::error::{LoftyError, Result};
#[cfg(feature = "id3v2_restrictions")]
use crate::logic::id3::v2::restrictions::TagRestrictions;
use crate::probe::Probe;
use std::fs::File;
use crate::LoftyError;
#[cfg(feature = "quick_tag_accessors")]
use paste::paste;
@ -41,161 +40,6 @@ macro_rules! common_items {
}
}
#[cfg(any(feature = "id3v2", feature = "ape"))]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
#[allow(clippy::struct_excessive_bools)]
/// **(ID3v2/APEv2 ONLY)** Various flags to describe the content of an item
///
/// It is not an error to attempt to write flags to a format that doesn't support them.
/// They will just be ignored.
pub struct TagItemFlags {
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Preserve frame on tag edit
pub tag_alter_preservation: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Preserve frame on file edit
pub file_alter_preservation: bool,
#[cfg(any(feature = "id3v2", feature = "ape"))]
/// **(ID3v2/APEv2 ONLY)** Item cannot be written to
pub read_only: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame belongs in a group
///
/// In addition to setting this flag, a group identifier byte must be added.
/// All frames with the same group identifier byte belong to the same group.
pub grouping_identity: (bool, u8),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is zlib compressed
///
/// It is **required** `data_length_indicator` be set if this is set.
pub compression: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is encrypted
///
/// NOTE: Since the encryption method is unknown, lofty cannot do anything with these frames
///
/// In addition to setting this flag, an encryption method symbol must be added.
/// The method symbol **must** be > 0x80.
pub encryption: (bool, u8),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame is unsynchronised
///
/// In short, this makes all "0xFF 0x00" combinations into "0xFF 0x00 0x00" to avoid confusion
/// with the MPEG frame header, which is often identified by its "frame sync" (11 set bits).
/// It is preferred an ID3v2 tag is either *completely* unsynchronised or not unsynchronised at all.
pub unsynchronisation: bool,
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** Frame has a data length indicator
///
/// The data length indicator is the size of the frame if the flags were all zeroed out.
/// This is usually used in combination with `compression` and `encryption` (depending on encryption method).
///
/// In addition to setting this flag, the final size must be added.
pub data_length_indicator: (bool, u32),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// Represents a tag item (key/value)
pub struct TagItem {
item_key: ItemKey,
item_value: ItemValue,
flags: TagItemFlags,
}
impl TagItem {
/// Create a new [`TagItem`]
///
/// NOTES:
///
/// * This will check for validity based on the [`TagType`].
/// * If the [`ItemKey`] does not map to a key in the target format, `None` will be returned.
/// * It is pointless to do this if you plan on using [`Tag::insert_item`], as it does validity checks itself.
pub fn new_checked(
tag_type: &TagType,
item_key: ItemKey,
item_value: ItemValue,
) -> Option<Self> {
item_key.map_key(tag_type).is_some().then(|| Self {
item_key,
item_value,
flags: TagItemFlags::default(),
})
}
/// Create a new [`TagItem`]
pub fn new(item_key: ItemKey, item_value: ItemValue) -> Self {
Self {
item_key,
item_value,
flags: TagItemFlags::default(),
}
}
/// Set the item's flags
pub fn set_flags(&mut self, flags: TagItemFlags) {
self.flags = flags
}
/// Returns a reference to the [`ItemKey`]
pub fn key(&self) -> &ItemKey {
&self.item_key
}
/// Returns a reference to the [`ItemValue`]
pub fn value(&self) -> &ItemValue {
&self.item_value
}
/// Returns a reference to the [`TagItemFlags`]
pub fn flags(&self) -> &TagItemFlags {
&self.flags
}
pub(crate) fn re_map(&self, tag_type: &TagType) -> Option<()> {
self.item_key.map_key(tag_type).is_some().then(|| ())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// Represents a tag item's value
///
/// NOTES:
///
/// * The [Locator][ItemValue::Locator] variant is only applicable to APE and ID3v2 tags.
/// * The [Binary][ItemValue::Binary] variant is only applicable to APE tags.
/// * Attempting to write either to another file/tag type will **not** error, they will just be ignored.
pub enum ItemValue {
/// Any UTF-8 encoded text
Text(String),
/// **(APE/ID3v2 ONLY)** Any UTF-8 encoded locator of external information
Locator(String),
/// **(APE/ID3v2/MP4 ONLY)** Binary information
///
/// In the case of ID3v2, this is the type of a [`Id3v2Frame::EncapsulatedObject`](crate::id3::Id3v2Frame::EncapsulatedObject) **and** any unknown frame.
///
/// For APEv2, no uses of this item type are documented, there's no telling what it could be.
Binary(Vec<u8>),
/// Any 32 bit unsigned integer
///
/// This is most commonly used for items such as track and disc numbers
UInt(u32),
/// **(MP4 ONLY)** Any 64 bit unsigned integer
///
/// There are no common [`ItemKey`]s that use this
UInt64(u64),
/// Any 32 bit signed integer
///
/// There are no common [`ItemKey`]s that use this
Int(i32),
/// **(MP4 ONLY)** Any 64 bit signed integer
///
/// There are no common [`ItemKey`]s that use this
Int64(i64),
#[cfg(feature = "id3v2")]
/// **(ID3v2 ONLY)** The content of a synchronized text frame, see [`SynchronizedText`](crate::id3::SynchronizedText)
SynchronizedText(Vec<(u32, String)>),
}
#[cfg(feature = "id3v2")]
#[derive(Default, Copy, Clone)]
#[allow(clippy::struct_excessive_bools)]