Accessor: Move to lofty::tag

This commit is contained in:
Serial 2024-04-14 12:35:02 -04:00 committed by Alex
parent ca8a3cb5b9
commit adea986132
15 changed files with 141 additions and 156 deletions

View file

@ -27,7 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ⚠️ Important ⚠️: Moved to `lofty::options` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374))
- **AudioFile**/**TaggedFileExt**/**TaggedFile**/**BoundTaggedFile**:
- ⚠️ Important ⚠️: Moved to `lofty::file` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374))
- **Tag**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**:
- **Tag**/**Accessor**/**TagType**/**TagExt**/**TagItem**/**ItemKey**/**ItemValue**:
- ⚠️ Important ⚠️: Moved to `lofty::tag` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/374))
### Fixed

View file

@ -7,8 +7,8 @@ use crate::config::WriteOptions;
use crate::error::{LoftyError, Result};
use crate::id3::v2::util::pairs::{format_number_pair, set_number, NUMBER_PAIR_KEYS};
use crate::tag::item::ItemValueRef;
use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;
@ -769,7 +769,6 @@ mod tests {
#[test]
fn track_number_tag_to_ape() {
use crate::traits::Accessor;
let track_number = 1;
let mut tag = Tag::new(TagType::Ape);
@ -787,7 +786,6 @@ mod tests {
#[test]
fn track_total_tag_to_ape() {
use crate::traits::Accessor;
let track_total = 2;
let mut tag = Tag::new(TagType::Ape);
@ -805,7 +803,6 @@ mod tests {
#[test]
fn track_number_and_track_total_tag_to_ape() {
use crate::traits::Accessor;
let track_number = 1;
let track_total = 2;
@ -829,7 +826,6 @@ mod tests {
#[test]
fn disk_number_tag_to_ape() {
use crate::traits::Accessor;
let disk_number = 1;
let mut tag = Tag::new(TagType::Ape);
@ -847,7 +843,6 @@ mod tests {
#[test]
fn disk_total_tag_to_ape() {
use crate::traits::Accessor;
let disk_total = 2;
let mut tag = Tag::new(TagType::Ape);
@ -865,7 +860,6 @@ mod tests {
#[test]
fn disk_number_and_disk_total_tag_to_ape() {
use crate::traits::Accessor;
let disk_number = 1;
let disk_total = 2;

View file

@ -1,8 +1,8 @@
use crate::config::WriteOptions;
use crate::error::{LoftyError, Result};
use crate::id3::v1::constants::GENRES;
use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;

View file

@ -18,8 +18,8 @@ use crate::id3::v2::util::pairs::{
};
use crate::id3::v2::KeyValueFrame;
use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE};
use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding};
use std::borrow::Cow;

View file

@ -438,7 +438,6 @@ fn popm_frame() {
#[test]
fn multi_value_frame_to_tag() {
use crate::traits::Accessor;
let mut tag = Id3v2Tag::default();
tag.set_artist(String::from("foo\0bar\0baz"));
@ -450,7 +449,6 @@ fn multi_value_frame_to_tag() {
#[test]
fn multi_item_tag_to_id3v2() {
use crate::traits::Accessor;
let mut tag = Tag::new(TagType::Id3v2);
tag.push_unchecked(TagItem::new(
@ -823,7 +821,6 @@ fn set_disk_total_and_disk() {
#[test]
fn track_number_tag_to_id3v2() {
use crate::traits::Accessor;
let track_number = 1;
let mut tag = Tag::new(TagType::Id3v2);
@ -841,7 +838,6 @@ fn track_number_tag_to_id3v2() {
#[test]
fn track_total_tag_to_id3v2() {
use crate::traits::Accessor;
let track_total = 2;
let mut tag = Tag::new(TagType::Id3v2);
@ -859,7 +855,6 @@ fn track_total_tag_to_id3v2() {
#[test]
fn track_number_and_track_total_tag_to_id3v2() {
use crate::traits::Accessor;
let track_number = 1;
let track_total = 2;
@ -883,7 +878,6 @@ fn track_number_and_track_total_tag_to_id3v2() {
#[test]
fn disk_number_tag_to_id3v2() {
use crate::traits::Accessor;
let disk_number = 1;
let mut tag = Tag::new(TagType::Id3v2);
@ -901,7 +895,6 @@ fn disk_number_tag_to_id3v2() {
#[test]
fn disk_total_tag_to_id3v2() {
use crate::traits::Accessor;
let disk_total = 2;
let mut tag = Tag::new(TagType::Id3v2);
@ -919,7 +912,6 @@ fn disk_total_tag_to_id3v2() {
#[test]
fn disk_number_and_disk_total_tag_to_id3v2() {
use crate::traits::Accessor;
let disk_number = 1;
let disk_total = 2;

View file

@ -2,8 +2,8 @@ use crate::config::WriteOptions;
use crate::error::{LoftyError, Result};
use crate::iff::chunk::Chunks;
use crate::macros::err;
use crate::tag::{ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;

View file

@ -3,8 +3,8 @@ mod write;
use crate::config::WriteOptions;
use crate::error::{LoftyError, Result};
use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;

View file

@ -194,6 +194,6 @@ pub mod prelude {
pub use crate::error::LoftyError;
pub use crate::file::{AudioFile, TaggedFileExt};
pub use crate::tag::{ItemKey, TagExt};
pub use crate::traits::{Accessor, MergeTag, SplitTag};
pub use crate::tag::{Accessor, ItemKey, TagExt};
pub use crate::traits::{MergeTag, SplitTag};
}

View file

@ -9,8 +9,8 @@ use crate::config::WriteOptions;
use crate::error::LoftyError;
use crate::mp4::ilst::atom::AtomDataStorage;
use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE};
use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use atom::{AdvisoryRating, Atom, AtomData};
use std::borrow::Cow;

View file

@ -6,8 +6,8 @@ use crate::ogg::picture_storage::OggPictureStorage;
use crate::ogg::write::OGGFormat;
use crate::picture::{Picture, PictureInformation};
use crate::probe::Probe;
use crate::tag::{try_parse_year, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;

View file

@ -134,8 +134,7 @@ mod tests {
use crate::id3::v2::Id3v2Tag;
use crate::properties::FileProperties;
use crate::resolve::{register_custom_resolver, FileResolver};
use crate::tag::TagType;
use crate::traits::Accessor;
use crate::tag::{Accessor, TagType};
use std::fs::File;
use std::io::{Read, Seek};

119
src/tag/accessor.rs Normal file
View file

@ -0,0 +1,119 @@
use std::borrow::Cow;
// This defines the `Accessor` trait, used to define unified getters/setters for commonly
// accessed tag values.
//
// Usage:
//
// accessor_trait! {
// [field_name]<type>
// }
//
// * `field_name` is the name of the method to access the field. If a name consists of multiple segments,
// such as `track_number`, they should be separated by spaces like so: [track number]<type>.
//
// * `type` is the return type for `Accessor::field_name`. By default, this type will also be used
// in the setter.
//
// An owned type can also be specified for the setter:
//
// accessor_trait! {
// field_name<type, owned_type>
// }
macro_rules! accessor_trait {
($([$($name:tt)+] < $($ty:ty),+ >),+ $(,)?) => {
/// Provides accessors for common items
///
/// This attempts to only provide methods for items that all tags have in common,
/// but there may be exceptions.
pub trait Accessor {
$(
accessor_trait! { @GETTER [$($name)+] $($ty),+ }
accessor_trait! { @SETTER [$($name)+] $($ty),+ }
accessor_trait! { @REMOVE [$($name)+] $($ty),+ }
)+
}
};
(@GETTER [$($name:tt)+] $ty:ty $(, $_ty:tt)?) => {
accessor_trait! { @GET_METHOD [$($name)+] Option<$ty> }
};
(@SETTER [$($name:tt)+] $_ty:ty, $owned_ty:tt) => {
accessor_trait! { @SETTER [$($name)+] $owned_ty }
};
(@SETTER [$($name:tt)+] $ty:ty) => {
accessor_trait! { @SET_METHOD [$($name)+] $ty }
};
(@REMOVE [$($name:tt)+] $_ty:ty, $owned_ty:tt) => {
accessor_trait! { @REMOVE [$($name)+] $owned_ty }
};
(@REMOVE [$($name:tt)+] $ty:ty) => {
accessor_trait! { @REMOVE_METHOD [$($name)+], $ty }
};
(@GET_METHOD [$name:tt $($other:tt)*] Option<$ret_ty:ty>) => {
paste::paste! {
#[doc = "Returns the " $name $(" " $other)*]
/// # Example
///
/// ```rust
/// use lofty::{Tag, Accessor};
///
/// # let tag_type = lofty::TagType::Id3v2;
/// let mut tag = Tag::new(tag_type);
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"]
/// ```
fn [<
$name $(_ $other)*
>] (&self) -> Option<$ret_ty> { None }
}
};
(@SET_METHOD [$name:tt $($other:tt)*] $owned_ty:ty) => {
paste::paste! {
#[doc = "Sets the " $name $(" " $other)*]
/// # Example
///
/// ```rust,ignore
/// use lofty::{Tag, Accessor};
///
/// let mut tag = Tag::new(tag_type);
#[doc = "tag.set_" $name $(_ $other)* "(value);"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"]
/// ```
fn [<
set_ $name $(_ $other)*
>] (&mut self , _value: $owned_ty) {}
}
};
(@REMOVE_METHOD [$name:tt $($other:tt)*], $ty:ty) => {
paste::paste! {
#[doc = "Removes the " $name $(" " $other)*]
/// # Example
///
/// ```rust,ignore
/// use lofty::{Tag, Accessor};
///
/// let mut tag = Tag::new(tag_type);
#[doc = "tag.set_" $name $(_ $other)* "(value);"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"]
///
#[doc = "tag.remove_" $name $(_ $other)* "();"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"]
/// ```
fn [<
remove_ $name $(_ $other)*
>] (&mut self) {}
}
};
}
accessor_trait! {
[artist]<Cow<'_, str>, String>, [title ]<Cow<'_, str>, String>,
[album ]<Cow<'_, str>, String>, [genre ]<Cow<'_, str>, String>,
[track ]<u32>, [track total]<u32>,
[disk ]<u32>, [disk total ]<u32>,
[year ]<u32>, [comment ]<Cow<'_, str>, String>,
}

View file

@ -1,5 +1,6 @@
//! Utilities for generic tag handling
mod accessor;
pub(crate) mod item;
mod tag_type;
mod tagext;
@ -10,7 +11,7 @@ use crate::error::{LoftyError, Result};
use crate::macros::err;
use crate::picture::{Picture, PictureType};
use crate::probe::Probe;
use crate::traits::{Accessor, MergeTag, SplitTag};
use crate::traits::{MergeTag, SplitTag};
use std::borrow::Cow;
use std::fs::File;
@ -18,6 +19,7 @@ use std::io::Write;
use std::path::Path;
// Exports
pub use accessor::Accessor;
pub use item::{ItemKey, ItemValue, TagItem};
pub use tag_type::TagType;
pub use tagext::TagExt;

View file

@ -1,6 +1,5 @@
use crate::config::WriteOptions;
use crate::tag::Tag;
use crate::traits::Accessor;
use crate::tag::{Accessor, Tag};
use std::fs::File;
use std::path::Path;

View file

@ -1,123 +1,3 @@
use std::borrow::Cow;
// This defines the `Accessor` trait, used to define unified getters/setters for commonly
// accessed tag values.
//
// Usage:
//
// accessor_trait! {
// [field_name]<type>
// }
//
// * `field_name` is the name of the method to access the field. If a name consists of multiple segments,
// such as `track_number`, they should be separated by spaces like so: [track number]<type>.
//
// * `type` is the return type for `Accessor::field_name`. By default, this type will also be used
// in the setter.
//
// An owned type can also be specified for the setter:
//
// accessor_trait! {
// field_name<type, owned_type>
// }
macro_rules! accessor_trait {
($([$($name:tt)+] < $($ty:ty),+ >),+ $(,)?) => {
/// Provides accessors for common items
///
/// This attempts to only provide methods for items that all tags have in common,
/// but there may be exceptions.
pub trait Accessor {
$(
accessor_trait! { @GETTER [$($name)+] $($ty),+ }
accessor_trait! { @SETTER [$($name)+] $($ty),+ }
accessor_trait! { @REMOVE [$($name)+] $($ty),+ }
)+
}
};
(@GETTER [$($name:tt)+] $ty:ty $(, $_ty:tt)?) => {
accessor_trait! { @GET_METHOD [$($name)+] Option<$ty> }
};
(@SETTER [$($name:tt)+] $_ty:ty, $owned_ty:tt) => {
accessor_trait! { @SETTER [$($name)+] $owned_ty }
};
(@SETTER [$($name:tt)+] $ty:ty) => {
accessor_trait! { @SET_METHOD [$($name)+] $ty }
};
(@REMOVE [$($name:tt)+] $_ty:ty, $owned_ty:tt) => {
accessor_trait! { @REMOVE [$($name)+] $owned_ty }
};
(@REMOVE [$($name:tt)+] $ty:ty) => {
accessor_trait! { @REMOVE_METHOD [$($name)+], $ty }
};
(@GET_METHOD [$name:tt $($other:tt)*] Option<$ret_ty:ty>) => {
paste::paste! {
#[doc = "Returns the " $name $(" " $other)*]
/// # Example
///
/// ```rust
/// use lofty::{Tag, Accessor};
///
/// # let tag_type = lofty::TagType::Id3v2;
/// let mut tag = Tag::new(tag_type);
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"]
/// ```
fn [<
$name $(_ $other)*
>] (&self) -> Option<$ret_ty> { None }
}
};
(@SET_METHOD [$name:tt $($other:tt)*] $owned_ty:ty) => {
paste::paste! {
#[doc = "Sets the " $name $(" " $other)*]
/// # Example
///
/// ```rust,ignore
/// use lofty::{Tag, Accessor};
///
/// let mut tag = Tag::new(tag_type);
#[doc = "tag.set_" $name $(_ $other)* "(value);"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"]
/// ```
fn [<
set_ $name $(_ $other)*
>] (&mut self , _value: $owned_ty) {}
}
};
(@REMOVE_METHOD [$name:tt $($other:tt)*], $ty:ty) => {
paste::paste! {
#[doc = "Removes the " $name $(" " $other)*]
/// # Example
///
/// ```rust,ignore
/// use lofty::{Tag, Accessor};
///
/// let mut tag = Tag::new(tag_type);
#[doc = "tag.set_" $name $(_ $other)* "(value);"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), Some(value));"]
///
#[doc = "tag.remove_" $name $(_ $other)* "();"]
///
#[doc = "assert_eq!(tag." $name $(_ $other)* "(), None);"]
/// ```
fn [<
remove_ $name $(_ $other)*
>] (&mut self) {}
}
};
}
accessor_trait! {
[artist]<Cow<'_, str>, String>, [title ]<Cow<'_, str>, String>,
[album ]<Cow<'_, str>, String>, [genre ]<Cow<'_, str>, String>,
[track ]<u32>, [track total]<u32>,
[disk ]<u32>, [disk total ]<u32>,
[year ]<u32>, [comment ]<Cow<'_, str>, String>,
}
use crate::tag::Tag;
/// Split (and merge) tags.