ID3v2: Add Id3v2Tag::remove_user_text

This commit is contained in:
Serial 2023-07-10 21:26:39 -04:00 committed by Alex
parent 58cad46d8d
commit cc338a3bc5
2 changed files with 52 additions and 3 deletions

View file

@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **ID3v2**:
- `Id3v2ErrorKind::UnsupportedFrameId` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/212))
- `FrameValue::KeyValue` for TIPL/TMCL frames ([PR](https://github.com/Serial-ATA/lofty-rs/pull/214))
- `Id3v2Tag::get_user_text` and `Id3v2Tag::insert_user_text` for working with TXXX frames ([PR](https://github.com/Serial-ATA/lofty-rs/pull/232))
- `Id3v2Tag::get_user_text`, `Id3v2Tag::insert_user_text`, and `Id3v2Tag::remove_user_text` for working with TXXX frames ([PR](https://github.com/Serial-ATA/lofty-rs/pull/232))
- **ParseOptions**: `ParseOptions::max_junk_bytes`, allowing the parser to sift through junk bytes to find required information, rather than
immediately declare a file invalid. ([discussion](https://github.com/Serial-ATA/lofty-rs/discussions/219)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/227))
- **WavPack**: `WavPackProperties` now contains the channel mask, accessible through `WavPackProperties::channel_mask()` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/230))

View file

@ -283,6 +283,42 @@ impl Id3v2Tag {
replaced
}
/// Removes a user-defined text frame (`TXXX`) by its description
///
/// This will return the matching frame.
///
/// # Examples
///
/// ```rust
/// use lofty::id3::v2::Id3v2Tag;
/// use lofty::TagExt;
///
/// let mut tag = Id3v2Tag::new();
/// assert!(tag.is_empty());
///
/// // Add a new "TXXX" frame identified by "SOME_DESCRIPTION"
/// let _ = tag.insert_user_text(String::from("SOME_DESCRIPTION"), String::from("Some value"));
/// assert!(!tag.is_empty());
///
/// // Now we can remove it by its description
/// let value = tag.remove_user_text("SOME_DESCRIPTION");
/// assert!(tag.is_empty());
/// ```
pub fn remove_user_text(&mut self, description: &str) -> Option<Frame<'static>> {
self.frames
.iter()
.position(|frame| {
matches!(frame, Frame {
value:
FrameValue::UserText(ExtendedTextFrame {
description: desc, ..
}),
..
} if desc == description)
})
.map(|pos| self.frames.remove(pos))
}
/// Removes a [`Frame`] by id
pub fn remove(&mut self, id: &str) {
self.frames.retain(|f| f.id_str() != id)
@ -2198,6 +2234,8 @@ mod tests {
fn get_set_user_defined_text() {
let description = String::from("FOO_BAR");
let content = String::from("Baz!\0Qux!");
let description2 = String::from("FOO_BAR_2");
let content2 = String::new();
let mut id3v2 = Id3v2Tag::default();
let txxx_frame = Frame::new(
@ -2218,8 +2256,8 @@ mod tests {
"TXXX",
ExtendedTextFrame {
encoding: TextEncoding::UTF8,
description: String::from("FOO_BAR_2"),
content: String::new(),
description: description2.clone(),
content: content2.clone(),
},
FrameFlags::default(),
)
@ -2238,6 +2276,17 @@ mod tests {
assert!(id3v2
.insert_user_text(description.clone(), content.clone())
.is_none());
assert!(id3v2
.insert_user_text(description2.clone(), content2.clone())
.is_none());
assert_eq!(id3v2.get_user_text(description.as_str()), Some(&*content));
// Remove one frame
assert!(id3v2.remove_user_text(&description).is_some());
assert!(!id3v2.is_empty());
// Now clear the remaining item
assert!(id3v2.remove_user_text(&description2).is_some());
assert!(id3v2.is_empty());
}
}