mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-14 22:52:32 +00:00
Add ID3v2 tag flags and restrictions
This commit is contained in:
parent
c5a1af5ccd
commit
0c41b3e15e
3 changed files with 127 additions and 8 deletions
80
src/logic/id3/v2/restrictions.rs
Normal file
80
src/logic/id3/v2/restrictions.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
#[derive(Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Restrictions on the tag size
|
||||
pub enum TagSizeRestrictions {
|
||||
/// No more than 128 frames and 1 MB total tag size
|
||||
S_128F_1M,
|
||||
/// No more than 64 frames and 128 KB total tag size
|
||||
S_64F_128K,
|
||||
/// No more than 32 frames and 40 KB total tag size
|
||||
S_32F_40K,
|
||||
/// No more than 32 frames and 4 KB total tag size
|
||||
S_32F_4K,
|
||||
}
|
||||
|
||||
impl Default for TagSizeRestrictions {
|
||||
fn default() -> Self {
|
||||
Self::S_128F_1M
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Restrictions on text field sizes
|
||||
pub enum TextSizeRestrictions {
|
||||
/// No size restrictions
|
||||
None,
|
||||
/// No longer than 1024 characters
|
||||
C_1024,
|
||||
/// No longer than 128 characters
|
||||
C_128,
|
||||
/// No longer than 30 characters
|
||||
C_30,
|
||||
}
|
||||
|
||||
impl Default for TextSizeRestrictions {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Restrictions on all image sizes
|
||||
pub enum ImageSizeRestrictions {
|
||||
/// No size restrictions
|
||||
None,
|
||||
/// All images are 256x256 or smaller
|
||||
P_256,
|
||||
/// All images are 64x64 or smaller
|
||||
P_64,
|
||||
/// All images are **exactly** 64x64
|
||||
P_64_64,
|
||||
}
|
||||
|
||||
impl Default for ImageSizeRestrictions {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
/// Restrictions on the content of an ID3v2 tag
|
||||
pub struct TagRestrictions {
|
||||
/// Restriction on the size of the tag. See [`TagSizeRestrictions`]
|
||||
pub size: TagSizeRestrictions,
|
||||
/// Text encoding restrictions
|
||||
///
|
||||
/// `false` - No restrictions
|
||||
/// `true` - Strings are only encoded with [`TextEncoding::Latin1`](crate::TextEncoding::Latin1) or [`TextEncoding::UTF8`](crate::TextEncoding::UTF8)
|
||||
pub text_encoding: bool,
|
||||
/// Restrictions on all text field sizes. See [`TextSizeRestrictions`]
|
||||
pub text_fields_size: TextSizeRestrictions,
|
||||
/// Image encoding restrictions
|
||||
///
|
||||
/// `false` - No restrictions
|
||||
/// `true` - Images can only be `PNG` or `JPEG`
|
||||
pub image_encoding: bool,
|
||||
/// Restrictions on all image sizes. See [`ImageSizeRestrictions`]
|
||||
pub image_size: ImageSizeRestrictions,
|
||||
}
|
|
@ -22,7 +22,7 @@ macro_rules! first_key {
|
|||
// Keys should appear in order of popularity.
|
||||
macro_rules! item_keys {
|
||||
(ALLOWED_UNKNOWN => [$($unknown_tag_type:pat),+]; $($variant:ident => [$($($tag_type:pat)|* => $($key:tt)|+),+]),+) => {
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
#[non_exhaustive]
|
||||
/// A generic representation of a tag's key
|
||||
|
@ -44,7 +44,7 @@ macro_rules! item_keys {
|
|||
///
|
||||
/// NOTE: If used with ID3v2, this will only check against the ID3v2.4 keys.
|
||||
/// If you wish to use a V2 or V3 key, see [`upgrade_v2`](crate::id3::upgrade_v2) and [`upgrade_v3`](crate::id3::upgrade_v3)
|
||||
pub const fn from_key(tag_type: &TagType, key: &str) -> Option<Self> {
|
||||
pub fn from_key(tag_type: &TagType, key: &str) -> Option<Self> {
|
||||
match tag_type {
|
||||
$(
|
||||
$(
|
||||
|
@ -62,7 +62,7 @@ macro_rules! item_keys {
|
|||
///
|
||||
/// NOTE: Since all ID3v2 tags are upgraded to [`Id3v2Version::V4`](crate::id3::Id3v2Version), the
|
||||
/// version provided does not matter. They cannot be downgraded.
|
||||
pub const fn map_key(&self, tag_type: &TagType) -> Option<&str> {
|
||||
pub fn map_key(&self, tag_type: &TagType) -> Option<&str> {
|
||||
match (tag_type, self) {
|
||||
$(
|
||||
$(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::item::ItemKey;
|
||||
use super::picture::{Picture, PictureType};
|
||||
use crate::logic::id3::v2::restrictions::TagRestrictions;
|
||||
use crate::logic::id3::v2::Id3v2Version;
|
||||
|
||||
#[cfg(feature = "quick_tag_accessors")]
|
||||
|
@ -13,7 +14,7 @@ macro_rules! common_items {
|
|||
$(
|
||||
#[doc = "Gets the " $name]
|
||||
pub fn $name(&self) -> Option<&str> {
|
||||
if let Some(ItemValue::Text(txt)) = self.get_item_ref(&ItemKey::$item_key).map(|i| i.value()) {
|
||||
if let Some(ItemValue::Text(txt)) = self.get_item_ref(&ItemKey::$item_key).map(TagItem::value) {
|
||||
return Some(&*txt)
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ macro_rules! common_items {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
/// **(ID3v2/APEv2 ONLY)** Various flags to describe the content of an item
|
||||
///
|
||||
|
@ -93,6 +95,7 @@ impl Default for TagItemFlags {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Represents a tag item (key/value)
|
||||
pub struct TagItem {
|
||||
item_key: ItemKey,
|
||||
|
@ -149,11 +152,12 @@ impl TagItem {
|
|||
&self.flags
|
||||
}
|
||||
|
||||
pub(crate) fn re_map(self, tag_type: &TagType) -> Option<Self> {
|
||||
self.item_key.map_key(tag_type).is_some().then(|| self)
|
||||
pub(crate) fn re_map(&self, tag_type: &TagType) -> Option<()> {
|
||||
self.item_key.map_key(tag_type).is_some().then(|| ())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Represents a tag item's value
|
||||
///
|
||||
/// NOTES:
|
||||
|
@ -166,10 +170,43 @@ pub enum ItemValue {
|
|||
Text(String),
|
||||
/// **(APE/ID3v2 ONLY)** Any UTF-8 encoded locator of external information
|
||||
Locator(String),
|
||||
/// **(APE ONLY)** Binary information, most likely a picture
|
||||
/// **(APE/ID3v2 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>),
|
||||
/// **(ID3v2 ONLY)** The content of a synchronized text frame, see [`SynchronizedText`](crate::id3::SynchronizedText)
|
||||
SynchronizedText(Vec<(u32, String)>),
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
/// **(ID3v2 ONLY)** Flags that apply to the entire tag
|
||||
pub struct TagFlags {
|
||||
/// Whether or not all frames are unsynchronised. See [`TagItemFlags::unsynchronization`]
|
||||
pub unsynchronisation: bool,
|
||||
/// Whether or not the header is followed by an extended header
|
||||
pub extended_header: bool,
|
||||
/// Indicates if the tag is in an experimental stage
|
||||
pub experimental: bool,
|
||||
/// Indicates that the tag includes a footer
|
||||
pub footer: bool,
|
||||
/// Whether or not to include a CRC-32 in the extended header
|
||||
///
|
||||
/// NOTE: This **requires** `extended_header` to be set. Otherwise, it will be ignored.
|
||||
///
|
||||
/// This is calculated if the tag is written
|
||||
pub crc: bool,
|
||||
/// Restrictions on the tag
|
||||
///
|
||||
/// NOTE: This **requires** `extended_header` to be set. Otherwise, it will be ignored.
|
||||
///
|
||||
/// In addition to being setting this flag, all restrictions must be provided. See [`TagRestrictions`]
|
||||
pub restrictions: (bool, TagRestrictions),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Represents a parsed tag
|
||||
///
|
||||
/// NOTE: Items and pictures are separated
|
||||
|
@ -177,6 +214,7 @@ pub struct Tag {
|
|||
tag_type: TagType,
|
||||
pictures: Vec<Picture>,
|
||||
items: Vec<TagItem>,
|
||||
flags: TagFlags,
|
||||
}
|
||||
|
||||
impl IntoIterator for Tag {
|
||||
|
@ -222,6 +260,7 @@ impl Tag {
|
|||
tag_type,
|
||||
pictures: vec![],
|
||||
items: vec![],
|
||||
flags: TagFlags::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +338,7 @@ impl Tag {
|
|||
/// When dealing with ID3v2, it may be necessary to use [`insert_item_unchecked`](Tag::insert_item_unchecked).
|
||||
/// See [`id3`](crate::id3) for an explanation.
|
||||
pub fn insert_item(&mut self, item: TagItem) -> bool {
|
||||
if let Some(item) = item.re_map(&self.tag_type) {
|
||||
if item.re_map(&self.tag_type).is_some() {
|
||||
self.insert_item_unchecked(item);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue