mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-14 06:32:33 +00:00
Accessor: Add {set_, remove_}track
This commit is contained in:
parent
829b3e0e95
commit
28fe204058
9 changed files with 341 additions and 187 deletions
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
- **WavPack** support
|
||||
- `Accessor::{set_, remove_}track`
|
||||
|
||||
### Changed
|
||||
- Bitrates in properties will be rounded up, similar to FFmpeg and TagLib
|
||||
|
@ -21,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `RiffInfo` -> `RIFFInfo`
|
||||
- `AiffText` -> `AIFFText`
|
||||
- All types implementing `PartialEq` now implement `Eq`
|
||||
- `Ilst::track_number` has been moved to the `Accessor::track` implementation
|
||||
|
||||
## [0.6.3] - 2022-05-18
|
||||
|
||||
|
|
|
@ -16,35 +16,33 @@ use std::path::Path;
|
|||
macro_rules! impl_accessor {
|
||||
($($name:ident => $($key:literal)|+;)+) => {
|
||||
paste::paste! {
|
||||
impl Accessor for ApeTag {
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
$(
|
||||
if let Some(i) = self.get_key($key) {
|
||||
if let ItemValue::Text(val) = i.value() {
|
||||
return Some(val)
|
||||
}
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
$(
|
||||
if let Some(i) = self.get_key($key) {
|
||||
if let ItemValue::Text(val) = i.value() {
|
||||
return Some(val)
|
||||
}
|
||||
)+
|
||||
}
|
||||
)+
|
||||
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(ApeItem {
|
||||
read_only: false,
|
||||
key: String::from(crate::tag::item::first_key!($($key)|*)),
|
||||
value: ItemValue::Text(value)
|
||||
})
|
||||
}
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(ApeItem {
|
||||
read_only: false,
|
||||
key: String::from(crate::tag::item::first_key!($($key)|*)),
|
||||
value: ItemValue::Text(value)
|
||||
})
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
$(
|
||||
self.remove_key($key);
|
||||
)+
|
||||
}
|
||||
)+
|
||||
}
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
$(
|
||||
self.remove_key($key);
|
||||
)+
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,13 +77,6 @@ pub struct ApeTag {
|
|||
pub(super) items: Vec<ApeItem>,
|
||||
}
|
||||
|
||||
impl_accessor!(
|
||||
artist => "Artist";
|
||||
title => "Title";
|
||||
album => "Album";
|
||||
genre => "GENRE";
|
||||
);
|
||||
|
||||
impl ApeTag {
|
||||
/// Get an [`ApeItem`] by key
|
||||
///
|
||||
|
@ -121,6 +112,41 @@ impl ApeTag {
|
|||
}
|
||||
}
|
||||
|
||||
impl Accessor for ApeTag {
|
||||
impl_accessor!(
|
||||
artist => "Artist";
|
||||
title => "Title";
|
||||
album => "Album";
|
||||
genre => "GENRE";
|
||||
);
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
if let Some(ApeItem {
|
||||
value: ItemValue::Text(ref text),
|
||||
..
|
||||
}) = self.get_key("Track")
|
||||
{
|
||||
if let Ok(ret) = text.parse::<u32>() {
|
||||
return Some(ret);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
self.insert(ApeItem {
|
||||
read_only: false,
|
||||
key: String::from("Track"),
|
||||
value: ItemValue::Text(value.to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.remove_key("Track");
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for ApeTag {
|
||||
type Err = LoftyError;
|
||||
|
||||
|
|
|
@ -115,6 +115,18 @@ impl Accessor for Id3v1Tag {
|
|||
fn remove_genre(&mut self) {
|
||||
self.genre = None
|
||||
}
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
self.track_number.map(u32::from)
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
self.track_number = Some(value as u8);
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.track_number = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for Id3v1Tag {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(feature = "id3v2_restrictions")]
|
||||
use super::restrictions::TagRestrictions;
|
||||
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
/// Flags that apply to the entire tag
|
||||
pub struct Id3v2TagFlags {
|
||||
|
|
|
@ -19,39 +19,37 @@ use std::io::Write;
|
|||
use std::path::Path;
|
||||
|
||||
macro_rules! impl_accessor {
|
||||
($($name:ident, $id:literal;)+) => {
|
||||
($($name:ident => $id:literal;)+) => {
|
||||
paste::paste! {
|
||||
impl Accessor for Id3v2Tag {
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
if let Some(f) = self.get($id) {
|
||||
if let FrameValue::Text {
|
||||
ref value,
|
||||
..
|
||||
} = f.content() {
|
||||
return Some(value)
|
||||
}
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
if let Some(f) = self.get($id) {
|
||||
if let FrameValue::Text {
|
||||
ref value,
|
||||
..
|
||||
} = f.content() {
|
||||
return Some(value)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(Frame {
|
||||
id: FrameID::Valid(String::from($id)),
|
||||
value: FrameValue::Text {
|
||||
encoding: TextEncoding::UTF8,
|
||||
value,
|
||||
},
|
||||
flags: FrameFlags::default()
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove($id)
|
||||
}
|
||||
)+
|
||||
}
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(Frame {
|
||||
id: FrameID::Valid(String::from($id)),
|
||||
value: FrameValue::Text {
|
||||
encoding: TextEncoding::UTF8,
|
||||
value,
|
||||
},
|
||||
flags: FrameFlags::default()
|
||||
});
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove($id)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,13 +97,6 @@ pub struct Id3v2Tag {
|
|||
frames: Vec<Frame>,
|
||||
}
|
||||
|
||||
impl_accessor!(
|
||||
title, "TIT2";
|
||||
artist, "TPE1";
|
||||
album, "TALB";
|
||||
genre, "TCON";
|
||||
);
|
||||
|
||||
impl IntoIterator for Id3v2Tag {
|
||||
type Item = Frame;
|
||||
type IntoIter = std::vec::IntoIter<Frame>;
|
||||
|
@ -272,6 +263,46 @@ impl Id3v2Tag {
|
|||
}
|
||||
}
|
||||
|
||||
impl Accessor for Id3v2Tag {
|
||||
impl_accessor!(
|
||||
title => "TIT2";
|
||||
artist => "TPE1";
|
||||
album => "TALB";
|
||||
genre => "TCON";
|
||||
);
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
if let Some(Frame {
|
||||
value: FrameValue::Text { ref value, .. },
|
||||
..
|
||||
}) = self.get("TRCK")
|
||||
{
|
||||
if let Some(track_num) = value.split(&['\0', '/'][..]).next() {
|
||||
if let Ok(ret) = track_num.parse::<u32>() {
|
||||
return Some(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
self.insert(Frame {
|
||||
id: FrameID::Valid(String::from("TRCK")),
|
||||
value: FrameValue::Text {
|
||||
value: value.to_string(),
|
||||
encoding: TextEncoding::UTF8,
|
||||
},
|
||||
flags: FrameFlags::default(),
|
||||
});
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.remove("TRCK");
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for Id3v2Tag {
|
||||
type Err = LoftyError;
|
||||
|
||||
|
|
|
@ -11,23 +11,21 @@ use std::io::Write;
|
|||
use std::path::Path;
|
||||
|
||||
macro_rules! impl_accessor {
|
||||
($($name:ident, $key:literal;)+) => {
|
||||
($($name:ident => $key:literal;)+) => {
|
||||
paste::paste! {
|
||||
impl Accessor for RiffInfoList {
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
self.get($key)
|
||||
}
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
self.get($key)
|
||||
}
|
||||
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(String::from($key), value)
|
||||
}
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(String::from($key), value)
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove($key)
|
||||
}
|
||||
)+
|
||||
}
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove($key)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +50,6 @@ pub struct RiffInfoList {
|
|||
pub(crate) items: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
impl_accessor!(
|
||||
artist, "IART";
|
||||
title, "INAM";
|
||||
album, "IPRD";
|
||||
genre, "IGNR";
|
||||
);
|
||||
|
||||
impl RiffInfoList {
|
||||
/// Get an item by key
|
||||
pub fn get(&self, key: &str) -> Option<&str> {
|
||||
|
@ -99,6 +90,31 @@ impl RiffInfoList {
|
|||
}
|
||||
}
|
||||
|
||||
impl Accessor for RiffInfoList {
|
||||
impl_accessor!(
|
||||
artist => "IART";
|
||||
title => "INAM";
|
||||
album => "IPRD";
|
||||
genre => "IGNR";
|
||||
);
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
if let Some(item) = self.get("IPRT") {
|
||||
return item.parse::<u32>().ok();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
self.insert(String::from("IPRT"), value.to_string());
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.remove("IPRT");
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for RiffInfoList {
|
||||
type Err = LoftyError;
|
||||
|
||||
|
|
|
@ -24,32 +24,30 @@ const ALBUM: AtomIdent = AtomIdent::Fourcc(*b"\xa9alb");
|
|||
const GENRE: AtomIdent = AtomIdent::Fourcc(*b"\xa9gen");
|
||||
|
||||
macro_rules! impl_accessor {
|
||||
($($name:ident, $const:ident;)+) => {
|
||||
($($name:ident => $const:ident;)+) => {
|
||||
paste::paste! {
|
||||
impl Accessor for Ilst {
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
if let Some(atom) = self.atom(&$const) {
|
||||
if let AtomData::UTF8(val) | AtomData::UTF16(val) = atom.data() {
|
||||
return Some(val)
|
||||
}
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
if let Some(atom) = self.atom(&$const) {
|
||||
if let AtomData::UTF8(val) | AtomData::UTF16(val) = atom.data() {
|
||||
return Some(val)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.replace_atom(Atom {
|
||||
ident: $const,
|
||||
data: AtomDataStorage::Single(AtomData::UTF8(value)),
|
||||
})
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove_atom(&$const)
|
||||
}
|
||||
)+
|
||||
}
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.replace_atom(Atom {
|
||||
ident: $const,
|
||||
data: AtomDataStorage::Single(AtomData::UTF8(value)),
|
||||
})
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
self.remove_atom(&$const)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,13 +83,6 @@ pub struct Ilst {
|
|||
pub(crate) atoms: Vec<Atom>,
|
||||
}
|
||||
|
||||
impl_accessor!(
|
||||
artist, ARTIST;
|
||||
title, TITLE;
|
||||
album, ALBUM;
|
||||
genre, GENRE;
|
||||
);
|
||||
|
||||
impl Ilst {
|
||||
/// Returns all of the tag's atoms
|
||||
pub fn atoms(&self) -> &[Atom] {
|
||||
|
@ -190,11 +181,6 @@ impl Ilst {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns the track number
|
||||
pub fn track_number(&self) -> Option<u16> {
|
||||
self.extract_number(*b"trkn", 4)
|
||||
}
|
||||
|
||||
/// Returns the total number of tracks
|
||||
pub fn track_total(&self) -> Option<u16> {
|
||||
self.extract_number(*b"trkn", 6)
|
||||
|
@ -228,6 +214,36 @@ impl Ilst {
|
|||
}
|
||||
}
|
||||
|
||||
impl Accessor for Ilst {
|
||||
impl_accessor!(
|
||||
artist => ARTIST;
|
||||
title => TITLE;
|
||||
album => ALBUM;
|
||||
genre => GENRE;
|
||||
);
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
self.extract_number(*b"trkn", 4).map(u32::from)
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
let value = (value as u16).to_be_bytes();
|
||||
let track_total = self.track_total().unwrap_or(0).to_be_bytes();
|
||||
|
||||
self.replace_atom(Atom {
|
||||
ident: AtomIdent::Fourcc(*b"trkn"),
|
||||
data: AtomDataStorage::Single(AtomData::Unknown {
|
||||
code: 0,
|
||||
data: vec![0, 0, value[0], value[1], track_total[0], track_total[1]],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.remove_atom(&AtomIdent::Fourcc(*b"trkn"));
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for Ilst {
|
||||
type Err = LoftyError;
|
||||
|
||||
|
|
|
@ -13,23 +13,21 @@ use std::io::{Cursor, Write};
|
|||
use std::path::Path;
|
||||
|
||||
macro_rules! impl_accessor {
|
||||
($($name:ident, $key:literal;)+) => {
|
||||
($($name:ident => $key:literal;)+) => {
|
||||
paste::paste! {
|
||||
impl Accessor for VorbisComments {
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
self.get($key)
|
||||
}
|
||||
$(
|
||||
fn $name(&self) -> Option<&str> {
|
||||
self.get($key)
|
||||
}
|
||||
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(String::from($key), value, true)
|
||||
}
|
||||
fn [<set_ $name>](&mut self, value: String) {
|
||||
self.insert(String::from($key), value, true)
|
||||
}
|
||||
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
let _ = self.remove($key);
|
||||
}
|
||||
)+
|
||||
}
|
||||
fn [<remove_ $name>](&mut self) {
|
||||
let _ = self.remove($key);
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +50,6 @@ pub struct VorbisComments {
|
|||
pub(crate) pictures: Vec<(Picture, PictureInformation)>,
|
||||
}
|
||||
|
||||
impl_accessor!(
|
||||
artist, "ARTIST";
|
||||
title, "TITLE";
|
||||
album, "ALBUM";
|
||||
genre, "GENRE";
|
||||
);
|
||||
|
||||
impl VorbisComments {
|
||||
/// Returns the vendor string
|
||||
pub fn vendor(&self) -> &str {
|
||||
|
@ -157,6 +148,31 @@ impl VorbisComments {
|
|||
}
|
||||
}
|
||||
|
||||
impl Accessor for VorbisComments {
|
||||
impl_accessor!(
|
||||
artist => "ARTIST";
|
||||
title => "TITLE";
|
||||
album => "ALBUM";
|
||||
genre => "GENRE";
|
||||
);
|
||||
|
||||
fn track(&self) -> Option<u32> {
|
||||
if let Some(item) = self.get("TRACKNUMBER") {
|
||||
return item.parse::<u32>().ok();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_track(&mut self, value: u32) {
|
||||
self.insert(String::from("TRACKNUMBER"), value.to_string(), true);
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
let _ = self.remove("TRACKNUMBER");
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExt for VorbisComments {
|
||||
type Err = LoftyError;
|
||||
|
||||
|
|
123
src/traits.rs
123
src/traits.rs
|
@ -1,5 +1,22 @@
|
|||
// This defines the `Accessor` trait, used to define unified getters/setters for commonly
|
||||
// accessed tag values.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// accessor_trait! {
|
||||
// field_name<type>
|
||||
// }
|
||||
//
|
||||
// Where `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:ident),+) => {
|
||||
($($name:ident < $($ty:ty),+ >),+ $(,)?) => {
|
||||
/// Provides accessors for common items
|
||||
///
|
||||
/// This attempts to only provide methods for items that all tags have in common,
|
||||
|
@ -7,56 +24,74 @@ macro_rules! accessor_trait {
|
|||
pub trait Accessor {
|
||||
paste::paste! {
|
||||
$(
|
||||
#[doc = "Returns the " $name]
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use lofty::{Tag, Accessor};
|
||||
/// # let tag_type = lofty::TagType::ID3v2;
|
||||
///
|
||||
/// let mut tag = Tag::new(tag_type);
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), None);"]
|
||||
/// ```
|
||||
fn $name(&self) -> Option<&str> { None }
|
||||
#[doc = "Sets the " $name]
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use lofty::{Tag, Accessor};
|
||||
/// # let tag_type = lofty::TagType::ID3v2;
|
||||
///
|
||||
#[doc = "let mut tag = Tag::new(tag_type);\ntag.set_" $name "(String::from(\"Foo " $name "\"));"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), Some(\"Foo " $name "\"));"]
|
||||
/// ```
|
||||
fn [<set_ $name>](&mut self, _value: String) {}
|
||||
#[doc = "Removes the " $name]
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use lofty::{Tag, Accessor};
|
||||
/// # let tag_type = lofty::TagType::ID3v2;
|
||||
///
|
||||
#[doc = "let mut tag = Tag::new(tag_type);\ntag.set_" $name "(String::from(\"Foo " $name "\"));"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), Some(\"Foo " $name "\"));"]
|
||||
///
|
||||
#[doc = "tag.remove_" $name "();"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), None);"]
|
||||
/// ```
|
||||
fn [<remove_ $name>](&mut self) {}
|
||||
accessor_trait! { @GETTER $name $($ty),+ }
|
||||
|
||||
accessor_trait! { @SETTER $name $($ty),+ }
|
||||
|
||||
accessor_trait! { @REMOVE $name $($ty),+ }
|
||||
)+
|
||||
}
|
||||
}
|
||||
};
|
||||
(@GETTER $name:ident $ty:ty $(, $_ty:tt)?) => {
|
||||
paste::paste! {
|
||||
#[doc = "Returns the " $name]
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use lofty::{Tag, Accessor};
|
||||
///
|
||||
/// let mut tag = Tag::new(tag_type);
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), None);"]
|
||||
/// ```
|
||||
fn $name(&self) -> Option<$ty> { None }
|
||||
}
|
||||
};
|
||||
(@SETTER $name:ident $_ty:ty, $owned_ty:tt) => {
|
||||
accessor_trait! { @SETTER $name $owned_ty }
|
||||
};
|
||||
(@SETTER $name:ident $ty:ty $(, $_ty:tt)?) => {
|
||||
paste::paste! {
|
||||
#[doc = "Sets the " $name]
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use lofty::{Tag, Accessor};
|
||||
///
|
||||
#[doc = "let mut tag = Tag::new(tag_type);\ntag.set_" $name "(value);"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), Some(value));"]
|
||||
/// ```
|
||||
fn [<set_ $name>](&mut self, _value: $ty) {}
|
||||
}
|
||||
};
|
||||
(@REMOVE $name:ident $ty:ty $(, $_ty:tt)?) => {
|
||||
paste::paste! {
|
||||
#[doc = "Removes the " $name]
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use lofty::{Tag, Accessor};
|
||||
///
|
||||
#[doc = "let mut tag = Tag::new(tag_type);\ntag.set_" $name "(value);"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), Some(value));"]
|
||||
///
|
||||
#[doc = "tag.remove_" $name "();"]
|
||||
///
|
||||
#[doc = "assert_eq!(tag." $name "(), None);"]
|
||||
/// ```
|
||||
fn [<remove_ $name>](&mut self) {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
accessor_trait! {
|
||||
artist, title,
|
||||
album, genre
|
||||
artist<&str, String>, title<&str, String>,
|
||||
album<&str, String>, genre<&str, String>,
|
||||
track<u32>
|
||||
}
|
||||
|
||||
use crate::tag::Tag;
|
||||
|
|
Loading…
Reference in a new issue