mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-04 18:09:11 +00:00
traits: Move {Split,Merge}Tag to lofty::tag
This commit is contained in:
parent
e8fdbf4cdd
commit
bf6e83876d
12 changed files with 90 additions and 88 deletions
|
@ -7,8 +7,9 @@ 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, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{
|
||||
try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType,
|
||||
};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::config::WriteOptions;
|
||||
use crate::error::{LoftyError, Result};
|
||||
use crate::id3::v1::constants::GENRES;
|
||||
use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
|
|
@ -18,8 +18,9 @@ use crate::id3::v2::util::pairs::{
|
|||
};
|
||||
use crate::id3::v2::KeyValueFrame;
|
||||
use crate::picture::{Picture, PictureType, TOMBSTONE_PICTURE};
|
||||
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{
|
||||
try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType,
|
||||
};
|
||||
use crate::util::text::{decode_text, TextDecodeOptions, TextEncoding};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
|
|
@ -2,8 +2,7 @@ use crate::config::WriteOptions;
|
|||
use crate::error::{LoftyError, Result};
|
||||
use crate::iff::chunk::Chunks;
|
||||
use crate::macros::err;
|
||||
use crate::tag::{Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
|
|
@ -3,8 +3,9 @@ mod write;
|
|||
|
||||
use crate::config::WriteOptions;
|
||||
use crate::error::{LoftyError, Result};
|
||||
use crate::tag::{try_parse_year, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{
|
||||
try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType,
|
||||
};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
|
|
@ -194,6 +194,5 @@ pub mod prelude {
|
|||
|
||||
pub use crate::error::LoftyError;
|
||||
pub use crate::file::{AudioFile, TaggedFileExt};
|
||||
pub use crate::tag::{Accessor, ItemKey, TagExt};
|
||||
pub use crate::traits::{MergeTag, SplitTag};
|
||||
pub use crate::tag::{Accessor, ItemKey, MergeTag, SplitTag, TagExt};
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ 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, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{
|
||||
try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType,
|
||||
};
|
||||
use atom::{AdvisoryRating, Atom, AtomData};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
|
|
@ -6,8 +6,9 @@ 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, Accessor, ItemKey, ItemValue, Tag, TagExt, TagItem, TagType};
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
use crate::tag::{
|
||||
try_parse_year, Accessor, ItemKey, ItemValue, MergeTag, SplitTag, Tag, TagExt, TagItem, TagType,
|
||||
};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
mod accessor;
|
||||
pub(crate) mod item;
|
||||
mod split_merge_tag;
|
||||
mod tag_ext;
|
||||
mod tag_type;
|
||||
mod tagext;
|
||||
pub(crate) mod utils;
|
||||
|
||||
use crate::config::WriteOptions;
|
||||
|
@ -11,7 +12,6 @@ use crate::error::{LoftyError, Result};
|
|||
use crate::macros::err;
|
||||
use crate::picture::{Picture, PictureType};
|
||||
use crate::probe::Probe;
|
||||
use crate::traits::{MergeTag, SplitTag};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
|
@ -21,8 +21,9 @@ use std::path::Path;
|
|||
// Exports
|
||||
pub use accessor::Accessor;
|
||||
pub use item::{ItemKey, ItemValue, TagItem};
|
||||
pub use split_merge_tag::{MergeTag, SplitTag};
|
||||
pub use tag_ext::TagExt;
|
||||
pub use tag_type::TagType;
|
||||
pub use tagext::TagExt;
|
||||
|
||||
macro_rules! impl_accessor {
|
||||
($($item_key:ident => $name:tt),+) => {
|
||||
|
|
68
src/tag/split_merge_tag.rs
Normal file
68
src/tag/split_merge_tag.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use super::Tag;
|
||||
|
||||
/// Split (and merge) tags.
|
||||
///
|
||||
/// Useful and required for implementing lossless read/modify/write round trips.
|
||||
/// Its counterpart `MergeTag` is used for recombining the results later.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use lofty::config::{ParseOptions, WriteOptions};
|
||||
/// use lofty::mpeg::MpegFile;
|
||||
/// use lofty::prelude::*;
|
||||
///
|
||||
/// // Read the tag from a file
|
||||
/// # fn main() -> lofty::error::Result<()> {
|
||||
/// # let mut file = std::fs::OpenOptions::new().write(true).open("/path/to/file.mp3")?;
|
||||
/// # let parse_options = ParseOptions::default();
|
||||
/// let mut mpeg_file = <MpegFile as AudioFile>::read_from(&mut file, parse_options)?;
|
||||
/// let mut id3v2 = mpeg_file
|
||||
/// .id3v2_mut()
|
||||
/// .map(std::mem::take)
|
||||
/// .unwrap_or_default();
|
||||
///
|
||||
/// // Split: ID3v2 -> [`lofty::Tag`]
|
||||
/// let (mut remainder, mut tag) = id3v2.split_tag();
|
||||
///
|
||||
/// // Modify the metadata in the generic [`lofty::Tag`], independent
|
||||
/// // of the underlying tag and file format.
|
||||
/// tag.insert_text(ItemKey::TrackTitle, "Track Title".to_owned());
|
||||
/// tag.remove_key(&ItemKey::Composer);
|
||||
///
|
||||
/// // ID3v2 <- [`lofty::Tag`]
|
||||
/// let id3v2 = remainder.merge_tag(tag);
|
||||
///
|
||||
/// // Write the changes back into the file
|
||||
/// mpeg_file.set_id3v2(id3v2);
|
||||
/// mpeg_file.save_to(&mut file, WriteOptions::default())?;
|
||||
///
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub trait SplitTag {
|
||||
/// The remainder of the split operation that is not represented
|
||||
/// in the resulting `Tag`.
|
||||
type Remainder: MergeTag;
|
||||
|
||||
/// Extract and split generic contents into a [`Tag`].
|
||||
///
|
||||
/// Returns the remaining content that cannot be represented in the
|
||||
/// resulting `Tag` in `Self::Remainder`. This is useful if the
|
||||
/// modified [`Tag`] is merged later using [`MergeTag::merge_tag`].
|
||||
fn split_tag(self) -> (Self::Remainder, Tag);
|
||||
}
|
||||
|
||||
/// The counterpart of [`SplitTag`].
|
||||
pub trait MergeTag {
|
||||
/// The resulting tag.
|
||||
type Merged: SplitTag;
|
||||
|
||||
/// Merge a generic [`Tag`] back into the remainder of [`SplitTag::split_tag`].
|
||||
///
|
||||
/// Restores the original representation merged with the contents of
|
||||
/// `tag` for further processing, e.g. writing back into a file.
|
||||
///
|
||||
/// Multi-valued items in `tag` with identical keys might get lost
|
||||
/// depending on the support for multi-valued fields in `self`.
|
||||
fn merge_tag(self, tag: Tag) -> Self::Merged;
|
||||
}
|
|
@ -1,72 +1,3 @@
|
|||
use crate::tag::Tag;
|
||||
|
||||
/// Split (and merge) tags.
|
||||
///
|
||||
/// Useful and required for implementing lossless read/modify/write round trips.
|
||||
/// Its counterpart `MergeTag` is used for recombining the results later.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use lofty::config::{ParseOptions, WriteOptions};
|
||||
/// use lofty::mpeg::MpegFile;
|
||||
/// use lofty::prelude::*;
|
||||
///
|
||||
/// // Read the tag from a file
|
||||
/// # fn main() -> lofty::error::Result<()> {
|
||||
/// # let mut file = std::fs::OpenOptions::new().write(true).open("/path/to/file.mp3")?;
|
||||
/// # let parse_options = ParseOptions::default();
|
||||
/// let mut mpeg_file = <MpegFile as AudioFile>::read_from(&mut file, parse_options)?;
|
||||
/// let mut id3v2 = mpeg_file
|
||||
/// .id3v2_mut()
|
||||
/// .map(std::mem::take)
|
||||
/// .unwrap_or_default();
|
||||
///
|
||||
/// // Split: ID3v2 -> [`lofty::Tag`]
|
||||
/// let (mut remainder, mut tag) = id3v2.split_tag();
|
||||
///
|
||||
/// // Modify the metadata in the generic [`lofty::Tag`], independent
|
||||
/// // of the underlying tag and file format.
|
||||
/// tag.insert_text(ItemKey::TrackTitle, "Track Title".to_owned());
|
||||
/// tag.remove_key(&ItemKey::Composer);
|
||||
///
|
||||
/// // ID3v2 <- [`lofty::Tag`]
|
||||
/// let id3v2 = remainder.merge_tag(tag);
|
||||
///
|
||||
/// // Write the changes back into the file
|
||||
/// mpeg_file.set_id3v2(id3v2);
|
||||
/// mpeg_file.save_to(&mut file, WriteOptions::default())?;
|
||||
///
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub trait SplitTag {
|
||||
/// The remainder of the split operation that is not represented
|
||||
/// in the resulting `Tag`.
|
||||
type Remainder: MergeTag;
|
||||
|
||||
/// Extract and split generic contents into a [`Tag`].
|
||||
///
|
||||
/// Returns the remaining content that cannot be represented in the
|
||||
/// resulting `Tag` in `Self::Remainder`. This is useful if the
|
||||
/// modified [`Tag`] is merged later using [`MergeTag::merge_tag`].
|
||||
fn split_tag(self) -> (Self::Remainder, Tag);
|
||||
}
|
||||
|
||||
/// The counterpart of [`SplitTag`].
|
||||
pub trait MergeTag {
|
||||
/// The resulting tag.
|
||||
type Merged: SplitTag;
|
||||
|
||||
/// Merge a generic [`Tag`] back into the remainder of [`SplitTag::split_tag`].
|
||||
///
|
||||
/// Restores the original representation merged with the contents of
|
||||
/// `tag` for further processing, e.g. writing back into a file.
|
||||
///
|
||||
/// Multi-valued items in `tag` with identical keys might get lost
|
||||
/// depending on the support for multi-valued fields in `self`.
|
||||
fn merge_tag(self, tag: Tag) -> Self::Merged;
|
||||
}
|
||||
|
||||
// TODO: https://github.com/rust-lang/rust/issues/59359
|
||||
pub(crate) trait SeekStreamLen: std::io::Seek {
|
||||
fn stream_len(&mut self) -> crate::error::Result<u64> {
|
||||
|
|
Loading…
Reference in a new issue