Leave GEOB/SYLT parsing up to the user, fix docs

This commit is contained in:
Serial 2021-09-13 18:35:20 -04:00
parent ffba428c98
commit 556aaea287
7 changed files with 29 additions and 40 deletions

View file

@ -141,6 +141,9 @@ pub use crate::types::{
#[cfg(any(feature = "id3v2", feature = "ape"))]
pub use crate::types::item::TagItemFlags;
#[cfg(feature = "id3v2")]
pub use crate::types::tag::TagFlags;
mod types;
/// Various concrete file types, used when inference is unnecessary

View file

@ -1,6 +1,4 @@
use crate::error::Result;
use crate::logic::id3::v2::util::encapsulated_object::GeneralEncapsulatedObject;
use crate::logic::id3::v2::util::sync_text::SynchronizedText;
use crate::logic::id3::v2::util::text_utils::decode_text;
use crate::logic::id3::v2::{Id3v2Frame, Id3v2Version, LanguageSpecificFrame, TextEncoding};
use crate::types::picture::Picture;
@ -28,19 +26,15 @@ pub(crate) fn parse_content(
"WXXX" => FrameContent::Item(parse_user_defined(content, true)?),
"COMM" | "USLT" => FrameContent::Item(parse_text_language(id, content)?),
"SYLT" => FrameContent::Item({
let sync_text = SynchronizedText::parse(content)?;
TagItem::new(
ItemKey::Id3v2Specific(Id3v2Frame::SyncText(sync_text.information)),
ItemValue::SynchronizedText(sync_text.content),
ItemKey::Id3v2Specific(Id3v2Frame::SyncText),
ItemValue::Binary(content.to_vec()),
)
}),
"GEOB" => FrameContent::Item({
let geob = GeneralEncapsulatedObject::parse(content)?;
TagItem::new(
ItemKey::Id3v2Specific(Id3v2Frame::EncapsulatedObject(geob.information)),
ItemValue::Binary(geob.data),
ItemKey::Id3v2Specific(Id3v2Frame::EncapsulatedObject),
ItemValue::Binary(content.to_vec()),
)
}),
_ if id.starts_with('T') => FrameContent::Item(parse_text(id, content)?),

View file

@ -1,6 +1,4 @@
use crate::logic::id3::decode_u32;
use crate::logic::id3::v2::util::encapsulated_object::GEOBInformation;
use crate::logic::id3::v2::util::sync_text::SyncTextInformation;
use crate::Result;
use std::io::{Read, Seek, SeekFrom};
@ -97,12 +95,12 @@ pub enum Id3v2Frame {
UserURL(TextEncoding, String),
/// Represents a "SYLT" frame
///
/// Due to the amount of information needed, it is contained in a separate struct, [`SyncTextInformation`]
SyncText(SyncTextInformation),
/// Nothing is required here, the entire frame is stored as [`ItemValue::Binary`](crate::ItemValue::Binary). For parsing see [`SynchronizedText::parse`](crate::id3::SynchronizedText::parse)
SyncText,
/// Represents a "GEOB" frame
///
/// Due to the amount of information needed, it is contained in a separate struct, [`GEOBInformation`]
EncapsulatedObject(GEOBInformation),
/// Nothing is required here, the entire frame is stored as [`ItemValue::Binary`](crate::ItemValue::Binary). For parsing see [`GeneralEncapsulatedObject::parse`](crate::id3::GeneralEncapsulatedObject::parse)
EncapsulatedObject,
/// When an ID3v2.2 key couldn't be upgraded
///
/// This **will not** be written. It is up to the user to upgrade and store the key as [`ItemKey::Unknown`](crate::ItemKey::Unknown).

View file

@ -13,8 +13,8 @@ pub struct GEOBInformation {
pub mime_type: Option<String>,
/// The file's name
pub file_name: Option<String>,
/// A description of the content
pub description: String,
/// A unique content descriptor
pub descriptor: String,
}
/// Allows for encapsulation of any file type inside an ID3v2 tag
@ -45,7 +45,7 @@ impl GeneralEncapsulatedObject {
let mime_type = decode_text(&mut cursor, TextEncoding::Latin1, true)?;
let file_name = decode_text(&mut cursor, encoding, true)?;
let description = decode_text(&mut cursor, encoding, true)?.unwrap_or_else(String::new);
let descriptor = decode_text(&mut cursor, encoding, true)?.unwrap_or_else(String::new);
let mut data = Vec::new();
cursor.read_to_end(&mut data)?;
@ -55,7 +55,7 @@ impl GeneralEncapsulatedObject {
encoding,
mime_type,
file_name,
description,
descriptor,
},
data,
})

View file

@ -194,10 +194,8 @@ fn build_ilst(tag: &Tag) -> Result<Vec<u8>> {
.iter()
.filter_map(|i| {
let key = i.key().map_key(&TagType::Mp4Atom).unwrap();
let valid_value = std::mem::discriminant(&ItemValue::SynchronizedText(Vec::new()))
!= std::mem::discriminant(i.value())
&& std::mem::discriminant(&ItemValue::Binary(Vec::new()))
!= std::mem::discriminant(i.value());
let valid_value = std::mem::discriminant(&ItemValue::Binary(Vec::new()))
!= std::mem::discriminant(i.value());
((key.chars().count() == 4 || key.starts_with("----")) && valid_value)
.then(|| (key, i.value()))

View file

@ -427,11 +427,8 @@ item_keys!(
#[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.
/// NOTE: The [Locator][crate::ItemValue::Locator] and [Binary][crate::ItemValue::Binary] variants are only applicable to ID3v2, APEv2, and MP4 ilst 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),
@ -439,9 +436,10 @@ pub enum ItemValue {
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.
/// In the case of ID3v2, this is the type of a [`Id3v2Frame::EncapsulatedObject`](crate::id3::Id3v2Frame::EncapsulatedObject),
/// [`Id3v2Frame::SyncText`](crate::id3::Id3v2Frame::SyncText), and any unknown frame.
///
/// For APEv2, no uses of this item type are documented, there's no telling what it could be.
/// For APEv2 and MP4, the only use is for unknown items.
Binary(Vec<u8>),
/// Any 32 bit unsigned integer
///
@ -459,9 +457,6 @@ pub enum ItemValue {
///
/// 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"))]
@ -533,7 +528,7 @@ impl TagItem {
///
/// * 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.
/// * It is pointless to do this if you plan on using [`Tag::insert_item`](crate::Tag::insert_item), as it does validity checks itself.
pub fn new_checked(
tag_type: &TagType,
item_key: ItemKey,

View file

@ -45,7 +45,7 @@ macro_rules! common_items {
#[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`]
/// Whether or not all frames are unsynchronised. See [`TagItemFlags::unsynchronisation`](crate::TagItemFlags::unsynchronisation)
pub unsynchronisation: bool,
/// Whether or not the header is followed by an extended header
pub extended_header: bool,
@ -160,6 +160,7 @@ impl Tag {
self.items.len() as u32
}
#[cfg(feature = "id3v2")]
/// Returns the [`TagFlags`]
pub fn flags(&self) -> &TagFlags {
&self.flags
@ -206,7 +207,7 @@ impl Tag {
///
/// NOTES:
///
/// * This **will** respect [`TagItemFlags::read_only`]
/// * This **will** respect [`TagItemFlags::read_only`](crate::TagItemFlags::read_only)
/// * This **will** verify an [`ItemKey`] mapping exists for the target [`TagType`]
///
/// # Warning
@ -226,7 +227,7 @@ impl Tag {
///
/// Notes:
///
/// * This **will not** respect [`TagItemFlags::read_only`]
/// * This **will not** respect [`TagItemFlags::read_only`](crate::TagItemFlags::read_only)
/// * This **will not** verify an [`ItemKey`] mapping exists
/// * This **will not** allow writing item keys that are out of spec (keys are verified before writing)
///
@ -244,8 +245,8 @@ impl Tag {
///
/// # Errors
///
/// * A [`FileType`] couldn't be determined from the File
/// * Attempting to write a tag to a format that does not support it. See [`FileType::supports_tag_type`]
/// * A [`FileType`](crate::FileType) couldn't be determined from the File
/// * Attempting to write a tag to a format that does not support it. See [`FileType::supports_tag_type`](crate::FileType::supports_tag_type)
pub fn save_to(&self, file: &mut File) -> Result<()> {
match Probe::new().file_type(file) {
Some(file_type) => {