mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 14:12:31 +00:00
Fully document the crate
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
42d0069bf0
commit
83a0f84b9e
12 changed files with 101 additions and 10 deletions
|
@ -16,6 +16,7 @@ use std::time::Duration;
|
|||
impl_tag!(ApeTag, ApeInnerTag, TagType::Ape);
|
||||
|
||||
impl ApeTag {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn read_from_path<P>(path: P) -> Result<Self>
|
||||
where
|
||||
|
|
|
@ -20,6 +20,7 @@ use std::time::Duration;
|
|||
impl_tag!(Id3v2Tag, Id3v2InnerTag, TagType::Id3v2(Id3Format::Default));
|
||||
|
||||
impl Id3v2Tag {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn read_from_path<P>(path: P, format: &Id3Format) -> Result<Self>
|
||||
where
|
||||
|
@ -59,8 +60,8 @@ impl std::convert::TryFrom<id3::frame::Picture> for Picture {
|
|||
|
||||
Ok(Self {
|
||||
pic_type,
|
||||
data,
|
||||
mime_type,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::time::Duration;
|
|||
impl_tag!(Mp4Tag, Mp4InnerTag, TagType::Mp4);
|
||||
|
||||
impl Mp4Tag {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn read_from_path<P>(path: P) -> Result<Self>
|
||||
where
|
||||
|
|
|
@ -27,6 +27,7 @@ impl Default for RiffInnerTag {
|
|||
}
|
||||
|
||||
impl RiffTag {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn read_from_path<P>(path: P) -> Result<Self>
|
||||
where
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::components::logic;
|
|||
use crate::tag::VorbisFormat;
|
||||
use crate::{
|
||||
impl_tag, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Error, MimeType, Picture,
|
||||
Result, TagType, ToAny, ToAnyTag, PictureType
|
||||
PictureType, Result, TagType, ToAny, ToAnyTag,
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
@ -184,6 +184,7 @@ impl_tag!(
|
|||
);
|
||||
|
||||
impl VorbisTag {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_errors_doc)]
|
||||
pub fn read_from_path<P>(path: P, format: VorbisFormat) -> Result<Self>
|
||||
where
|
||||
|
@ -350,7 +351,7 @@ impl AudioTagEdit for VorbisTag {
|
|||
Some(pictures) => {
|
||||
for pic in pictures {
|
||||
if pic.pic_type == PictureType::CoverFront {
|
||||
return Some(pic.clone())
|
||||
return Some(pic.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,7 +376,7 @@ impl AudioTagEdit for VorbisTag {
|
|||
|
||||
let encoded = base64::encode(encoded);
|
||||
|
||||
if let Ok(Some(pic))= picture_from_data(&*encoded) {
|
||||
if let Ok(Some(pic)) = picture_from_data(&*encoded) {
|
||||
if let Some(mut pictures) = self.inner.pictures.clone() {
|
||||
pictures.retain(|p| p.pic_type != PictureType::CoverFront);
|
||||
pictures.push(pic);
|
||||
|
|
18
src/error.rs
18
src/error.rs
|
@ -5,44 +5,60 @@ pub enum Error {
|
|||
#[error("Failed to guess the metadata format based on the file extension.")]
|
||||
UnknownFileExtension,
|
||||
|
||||
/// Unable to guess the format
|
||||
#[error("No format could be determined from the provided file.")]
|
||||
UnknownFormat,
|
||||
/// Provided an empty file
|
||||
#[error("File contains no data")]
|
||||
EmptyFile,
|
||||
/// Provided a file with invalid/malformed data
|
||||
#[error("File has invalid data")]
|
||||
InvalidData,
|
||||
|
||||
/// Unsupported file extension
|
||||
#[error("Unsupported format: {0}")]
|
||||
UnsupportedFormat(String),
|
||||
/// Picture has an unsupported mime type
|
||||
#[error("Unsupported mime type: {0}")]
|
||||
UnsupportedMimeType(String),
|
||||
|
||||
/// Any error from [`ape`]
|
||||
#[error(transparent)]
|
||||
ApeTag(#[from] ape::Error),
|
||||
/// Any error from [`metaflac`]
|
||||
#[error(transparent)]
|
||||
FlacTag(#[from] metaflac::Error),
|
||||
/// Any error from [`id3`]
|
||||
#[error(transparent)]
|
||||
Id3Tag(#[from] id3::Error),
|
||||
/// Any error from [`mp3_duration`]
|
||||
#[cfg(feature = "duration")]
|
||||
#[error(transparent)]
|
||||
Mp3Duration(#[from] mp3_duration::MP3DurationError),
|
||||
/// Any error from [`mp4ameta`]
|
||||
#[error(transparent)]
|
||||
Mp4Tag(#[from] mp4ameta::Error),
|
||||
/// Any error from [`opus_headers`]
|
||||
#[error(transparent)]
|
||||
OpusTag(#[from] opus_headers::ParseError),
|
||||
/// Any error from [`lewton`]
|
||||
#[error(transparent)]
|
||||
Lewton(#[from] lewton::VorbisError),
|
||||
/// Any error from [`ogg`]
|
||||
#[error(transparent)]
|
||||
Ogg(#[from] ogg::OggReadError),
|
||||
/// Errors that arise while reading/writing to wav files
|
||||
#[error("{0}")]
|
||||
Wav(String),
|
||||
|
||||
/// Failed to convert data to a picture
|
||||
#[error("")]
|
||||
NotAPicture,
|
||||
|
||||
/// If a string isn't Utf8
|
||||
#[error(transparent)]
|
||||
Utf8(#[from] std::str::Utf8Error),
|
||||
/// Unable to convert bytes to a String
|
||||
#[error(transparent)]
|
||||
FromUtf8(#[from] std::string::FromUtf8Error),
|
||||
/// Represents all cases of `std::io::Error`.
|
||||
|
@ -51,5 +67,5 @@ pub enum Error {
|
|||
IO(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
/// Type alias for the result of tag operations.
|
||||
/// Type for the result of tag operations.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
//! unnecessary copies.
|
||||
|
||||
#![warn(clippy::pedantic)]
|
||||
#![warn(missing_docs)]
|
||||
#![allow(
|
||||
clippy::too_many_lines,
|
||||
clippy::cast_precision_loss,
|
||||
|
|
|
@ -21,6 +21,7 @@ macro_rules! impl_tag {
|
|||
}
|
||||
|
||||
impl $tag {
|
||||
/// Creates a new default tag
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
|
|
@ -4,28 +4,40 @@ use crate::{Album, AnyTag, Picture, Result, TagType};
|
|||
|
||||
use std::fs::{File, OpenOptions};
|
||||
|
||||
/// Combination of [`AudioTagEdit`], [`AudioTagWrite`], and [`ToAnyTag`]
|
||||
pub trait AudioTag: AudioTagEdit + AudioTagWrite + ToAnyTag {}
|
||||
|
||||
/// Implementors of this trait are able to read and write audio metadata.
|
||||
///
|
||||
/// Constructor methods e.g. `from_file` should be implemented separately.
|
||||
pub trait AudioTagEdit {
|
||||
/// Returns the track title
|
||||
fn title(&self) -> Option<&str>;
|
||||
/// Sets the track title
|
||||
fn set_title(&mut self, title: &str);
|
||||
/// Removes the track title
|
||||
fn remove_title(&mut self);
|
||||
|
||||
/// Returns the artist(s) as a string
|
||||
fn artist_str(&self) -> Option<&str>;
|
||||
/// Sets the artist string
|
||||
fn set_artist(&mut self, artist: &str);
|
||||
|
||||
/// Splits the artist string into a `Vec`
|
||||
fn artists_vec(&self) -> Option<Vec<&str>> {
|
||||
self.artist_str().map(|a| a.split('/').collect())
|
||||
}
|
||||
/// Removes the artist string
|
||||
fn remove_artist(&mut self);
|
||||
|
||||
/// Returns the track year
|
||||
fn year(&self) -> Option<i32>;
|
||||
/// Sets the track year
|
||||
fn set_year(&mut self, year: i32);
|
||||
/// Removes the track year
|
||||
fn remove_year(&mut self);
|
||||
|
||||
/// Returns the track's [`Album`]
|
||||
fn album(&self) -> Album<'_> {
|
||||
Album {
|
||||
title: self.album_title(),
|
||||
|
@ -34,60 +46,85 @@ pub trait AudioTagEdit {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the album title
|
||||
fn album_title(&self) -> Option<&str>;
|
||||
/// Sets the album title
|
||||
fn set_album_title(&mut self, v: &str);
|
||||
/// Removes the album title
|
||||
fn remove_album_title(&mut self);
|
||||
|
||||
/// Returns the album artist string
|
||||
fn album_artist_str(&self) -> Option<&str>;
|
||||
/// Splits the artist string into a `Vec`
|
||||
fn album_artists_vec(&self) -> Option<Vec<&str>> {
|
||||
self.album_artist_str().map(|a| a.split('/').collect())
|
||||
}
|
||||
/// Sets the album artist string
|
||||
fn set_album_artist(&mut self, artist: &str);
|
||||
/// Removes the album artist string
|
||||
fn remove_album_artists(&mut self);
|
||||
|
||||
/// Returns the album cover
|
||||
fn album_cover(&self) -> Option<Picture>;
|
||||
/// Sets the album cover
|
||||
fn set_album_cover(&mut self, cover: Picture);
|
||||
/// Removes the album cover
|
||||
fn remove_album_cover(&mut self);
|
||||
|
||||
/// Returns the track number and total tracks
|
||||
fn track(&self) -> (Option<u32>, Option<u32>) {
|
||||
(self.track_number(), self.total_tracks())
|
||||
}
|
||||
/// Sets the track number
|
||||
fn set_track(&mut self, track: u32) {
|
||||
self.set_track_number(track);
|
||||
}
|
||||
/// Removes the track number and total tracks
|
||||
fn remove_track(&mut self) {
|
||||
self.remove_track_number();
|
||||
self.remove_total_tracks();
|
||||
}
|
||||
|
||||
/// Returns the track number
|
||||
fn track_number(&self) -> Option<u32>;
|
||||
/// Sets the track number
|
||||
fn set_track_number(&mut self, track_number: u32);
|
||||
/// Removes the track number
|
||||
fn remove_track_number(&mut self);
|
||||
|
||||
/// Returns the total tracks
|
||||
fn total_tracks(&self) -> Option<u32>;
|
||||
/// Sets the total tracks
|
||||
fn set_total_tracks(&mut self, total_track: u32);
|
||||
/// Removes the total tracks
|
||||
fn remove_total_tracks(&mut self);
|
||||
|
||||
/// Returns the disc number and total discs
|
||||
fn disc(&self) -> (Option<u32>, Option<u32>) {
|
||||
(self.disc_number(), self.total_discs())
|
||||
}
|
||||
fn set_disc(&mut self, disc: u32) {
|
||||
self.set_disc_number(disc);
|
||||
}
|
||||
/// Removes the disc number and total discs
|
||||
fn remove_disc(&mut self) {
|
||||
self.remove_disc_number();
|
||||
self.remove_total_discs();
|
||||
}
|
||||
|
||||
/// Returns the disc number
|
||||
fn disc_number(&self) -> Option<u32>;
|
||||
/// Sets the disc number
|
||||
fn set_disc_number(&mut self, disc_number: u32);
|
||||
/// Removes the disc number
|
||||
fn remove_disc_number(&mut self);
|
||||
|
||||
/// Returns the total discs
|
||||
fn total_discs(&self) -> Option<u32>;
|
||||
/// Sets the total discs
|
||||
fn set_total_discs(&mut self, total_discs: u32);
|
||||
/// Removes the total discs
|
||||
fn remove_total_discs(&mut self);
|
||||
}
|
||||
|
||||
/// Functions for writing to a file
|
||||
pub trait AudioTagWrite {
|
||||
/// Write tag to a [`File`][std::fs::File]
|
||||
///
|
||||
|
@ -107,7 +144,9 @@ pub trait AudioTagWrite {
|
|||
}
|
||||
}
|
||||
|
||||
/// Conversions between tag types
|
||||
pub trait ToAnyTag: ToAny {
|
||||
/// Converts the tag to [`AnyTag`]
|
||||
fn to_anytag(&self) -> AnyTag<'_>;
|
||||
|
||||
/// Convert the tag type, which can be lossy.
|
||||
|
@ -129,8 +168,11 @@ pub trait ToAnyTag: ToAny {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tag conversion to `Any`
|
||||
pub trait ToAny {
|
||||
/// Convert tag to `Any`
|
||||
fn to_any(&self) -> &dyn std::any::Any;
|
||||
/// Mutably convert tag to `Any`
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn to_any_mut(&mut self) -> &mut dyn std::any::Any;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ use super::picture::Picture;
|
|||
/// A struct for representing an album for convenience.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Album<'a> {
|
||||
/// The title of the album
|
||||
pub title: Option<&'a str>,
|
||||
/// A `Vec` of the album artists
|
||||
pub artists: Option<Vec<&'a str>>,
|
||||
/// The album's front cover
|
||||
// TODO: also store the back cover
|
||||
pub cover: Option<Picture>,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,25 @@ use crate::Album;
|
|||
/// Used to convert between tags
|
||||
#[derive(Default, Debug)]
|
||||
pub struct AnyTag<'a> {
|
||||
/// The track title
|
||||
pub title: Option<&'a str>,
|
||||
/// The track artists
|
||||
pub artists: Option<Vec<&'a str>>,
|
||||
/// The track [`Album`]
|
||||
pub album: Album<'a>,
|
||||
/// Collection of user comments
|
||||
pub comments: Option<Vec<&'a str>>,
|
||||
/// The track year
|
||||
pub year: Option<i32>,
|
||||
/// The track date
|
||||
pub date: Option<&'a str>,
|
||||
/// The track number
|
||||
pub track_number: Option<u32>,
|
||||
/// The total tracks
|
||||
pub total_tracks: Option<u32>,
|
||||
/// The disc number
|
||||
pub disc_number: Option<u32>,
|
||||
/// The total discs
|
||||
pub total_discs: Option<u32>,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,15 @@ use std::convert::TryFrom;
|
|||
/// Mime types for covers.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum MimeType {
|
||||
/// PNG image
|
||||
Png,
|
||||
/// JPEG image
|
||||
Jpeg,
|
||||
/// TIFF image
|
||||
Tiff,
|
||||
/// BMP image
|
||||
Bmp,
|
||||
/// GIF image
|
||||
Gif,
|
||||
}
|
||||
|
||||
|
@ -47,8 +52,11 @@ impl From<MimeType> for String {
|
|||
/// The picture type
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum PictureType {
|
||||
/// Represents the front cover of an album
|
||||
CoverFront,
|
||||
/// Represents the back cover of an album
|
||||
CoverBack,
|
||||
/// Covers all other possible types
|
||||
Other,
|
||||
}
|
||||
|
||||
|
@ -65,17 +73,21 @@ impl From<&id3PicType> for PictureType {
|
|||
/// Represents a picture, with its data and mime type.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Picture {
|
||||
/// The picture type
|
||||
pub pic_type: PictureType,
|
||||
pub data: Vec<u8>,
|
||||
/// The picture's mimetype
|
||||
pub mime_type: MimeType,
|
||||
/// The picture's actual data
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Picture {
|
||||
/// Create a new `Picture`
|
||||
pub fn new(pic_type: PictureType, data: Vec<u8>, mime_type: MimeType) -> Self {
|
||||
Self {
|
||||
pic_type,
|
||||
data,
|
||||
mime_type,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue