TagExt: Add TagExt::contains

This commit is contained in:
Serial 2022-11-05 09:54:37 -04:00
parent 193a4ed7c7
commit 544aa7a411
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
9 changed files with 78 additions and 3 deletions

View file

@ -211,6 +211,11 @@ impl Accessor for ApeTag {
impl TagExt for ApeTag {
type Err = LoftyError;
type RefKey<'a> = &'a str;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.items.iter().any(|i| i.key().eq_ignore_ascii_case(key))
}
fn is_empty(&self) -> bool {
self.items.is_empty()

View file

@ -168,6 +168,20 @@ impl Accessor for ID3v1Tag {
impl TagExt for ID3v1Tag {
type Err = LoftyError;
type RefKey<'a> = &'a ItemKey;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
match key {
ItemKey::TrackTitle => self.title.is_some(),
ItemKey::AlbumTitle => self.album.is_some(),
ItemKey::TrackArtist => self.artist.is_some(),
ItemKey::TrackNumber => self.track_number.is_some(),
ItemKey::Year => self.year.is_some(),
ItemKey::Genre => self.genre.is_some(),
ItemKey::Comment => self.comment.is_some(),
_ => false,
}
}
fn is_empty(&self) -> bool {
self.title.is_none()

View file

@ -420,6 +420,11 @@ impl Accessor for ID3v2Tag {
impl TagExt for ID3v2Tag {
type Err = LoftyError;
type RefKey<'a> = &'a FrameID;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.frames.iter().any(|frame| &frame.id == key)
}
fn is_empty(&self) -> bool {
self.frames.is_empty()

View file

@ -137,6 +137,17 @@ impl AIFFTextChunks {
impl TagExt for AIFFTextChunks {
type Err = LoftyError;
type RefKey<'a> = &'a ItemKey;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
match key {
ItemKey::TrackTitle => self.name.is_some(),
ItemKey::TrackArtist => self.author.is_some(),
ItemKey::CopyrightMessage => self.copyright.is_some(),
ItemKey::Comment => self.annotations.is_some() || self.comments.is_some(),
_ => false,
}
}
fn is_empty(&self) -> bool {
matches!(

View file

@ -131,6 +131,13 @@ impl Accessor for RIFFInfoList {
impl TagExt for RIFFInfoList {
type Err = LoftyError;
type RefKey<'a> = &'a str;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.items
.iter()
.any(|(item_key, _)| item_key.eq_ignore_ascii_case(key))
}
fn is_empty(&self) -> bool {
self.items.is_empty()

View file

@ -325,6 +325,11 @@ impl Accessor for Ilst {
impl TagExt for Ilst {
type Err = LoftyError;
type RefKey<'a> = &'a AtomIdent;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.atoms.iter().any(|atom| &atom.ident == key)
}
fn is_empty(&self) -> bool {
self.atoms.is_empty()

View file

@ -368,6 +368,13 @@ impl Accessor for VorbisComments {
impl TagExt for VorbisComments {
type Err = LoftyError;
type RefKey<'a> = &'a str;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.items
.iter()
.any(|(item_key, _)| item_key.eq_ignore_ascii_case(key))
}
fn is_empty(&self) -> bool {
self.items.is_empty() && self.pictures.is_empty()

View file

@ -507,6 +507,11 @@ impl Tag {
impl TagExt for Tag {
type Err = LoftyError;
type RefKey<'a> = &'a ItemKey;
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool {
self.items.iter().any(|item| item.key() == key)
}
fn is_empty(&self) -> bool {
self.items.is_empty() && self.pictures.is_empty()

View file

@ -131,10 +131,26 @@ use std::path::Path;
pub trait TagExt: Accessor + Into<Tag> + Sized {
/// The associated error which can be returned from IO operations
type Err;
/// The type of key used in the tag for non-mutating functions
type RefKey<'a>
where
Self: 'a;
// TODO:
// type Key;
// fn contains(key: Key) -> bool;
/// Whether the tag contains an item with the key
///
/// # Example
///
/// ```rust
/// use lofty::{Accessor, ItemKey, Tag, TagExt};
/// # let tag_type = lofty::TagType::ID3v2;
///
/// let mut tag = Tag::new(tag_type);
/// assert!(tag.is_empty());
///
/// tag.set_artist(String::from("Foo artist"));
/// assert!(tag.contains(&ItemKey::TrackArtist));
/// ```
fn contains<'a>(&'a self, key: Self::RefKey<'a>) -> bool;
/// Whether the tag has any items
///