multitag/
data.rs

1//! Useful types for representing audio metadata information.
2//!
3//! The types in this module are typically returned by methods on [`Tag`](crate::Tag).
4
5use crate::{Error, Result};
6use id3::frame::Picture as Id3Picture;
7use id3::frame::Timestamp as Id3Timestamp;
8use metaflac::block::Picture as FlacPicture;
9use mp4ameta::Img as Mp4Picture;
10use mp4ameta::ImgFmt as Mp4ImageFmt;
11use opusmeta::picture::Picture as OpusPicture;
12use std::str::FromStr;
13
14/// Represents the album that a song is part of.
15#[derive(Clone, Debug, Default)]
16pub struct Album {
17    pub title: Option<String>,
18    pub artist: Option<String>,
19    pub cover: Option<Picture>,
20}
21
22/// Stores picture data.
23#[derive(Clone, Debug)]
24pub struct Picture {
25    pub data: Vec<u8>,
26    pub mime_type: String,
27}
28
29impl From<Id3Picture> for Picture {
30    fn from(value: Id3Picture) -> Self {
31        Self {
32            data: value.data,
33            mime_type: value.mime_type,
34        }
35    }
36}
37
38impl From<FlacPicture> for Picture {
39    fn from(value: FlacPicture) -> Self {
40        Self {
41            data: value.data,
42            mime_type: value.mime_type,
43        }
44    }
45}
46
47impl From<Mp4Picture<&[u8]>> for Picture {
48    fn from(value: Mp4Picture<&[u8]>) -> Self {
49        Self {
50            data: value.data.to_vec(),
51            mime_type: match value.fmt {
52                Mp4ImageFmt::Bmp => "image/bmp".into(),
53                Mp4ImageFmt::Jpeg => "image/jpeg".into(),
54                Mp4ImageFmt::Png => "image/png".into(),
55            },
56        }
57    }
58}
59
60impl TryFrom<Picture> for Mp4Picture<Vec<u8>> {
61    type Error = Error;
62
63    fn try_from(value: Picture) -> Result<Self> {
64        let image_fmt = match value.mime_type.as_str() {
65            "image/bmp" => Ok(Mp4ImageFmt::Bmp),
66            "image/jpeg" => Ok(Mp4ImageFmt::Jpeg),
67            "image/png" => Ok(Mp4ImageFmt::Png),
68            _ => Err(Error::InvalidImageFormat),
69        }?;
70
71        Ok(Self {
72            fmt: image_fmt,
73            data: value.data,
74        })
75    }
76}
77
78impl From<OpusPicture> for Picture {
79    fn from(value: OpusPicture) -> Self {
80        Self {
81            data: value.data,
82            mime_type: value.mime_type,
83        }
84    }
85}
86
87impl From<Picture> for OpusPicture {
88    fn from(value: Picture) -> Self {
89        let mut picture = OpusPicture::new();
90        picture.mime_type = value.mime_type;
91        picture.data = value.data;
92
93        picture
94    }
95}
96
97impl std::fmt::Display for Picture {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        write!(
100            f,
101            "Picture data ({}, {} bytes)",
102            self.mime_type,
103            self.data.len()
104        )
105    }
106}
107
108/// Represents a date and time according to the ID3v2.4 spec.
109#[derive(Clone, Copy, Debug, Default)]
110pub struct Timestamp {
111    pub year: i32,
112    pub month: Option<u8>,
113    pub day: Option<u8>,
114    pub hour: Option<u8>,
115    pub minute: Option<u8>,
116    pub second: Option<u8>,
117}
118
119impl From<Id3Timestamp> for Timestamp {
120    fn from(value: Id3Timestamp) -> Self {
121        Self {
122            year: value.year,
123            month: value.month,
124            day: value.day,
125            hour: value.hour,
126            minute: value.minute,
127            second: value.second,
128        }
129    }
130}
131
132impl From<Timestamp> for Id3Timestamp {
133    fn from(value: Timestamp) -> Self {
134        Self {
135            year: value.year,
136            month: value.month,
137            day: value.day,
138            hour: value.hour,
139            minute: value.minute,
140            second: value.second,
141        }
142    }
143}
144
145impl FromStr for Timestamp {
146    type Err = Error;
147
148    fn from_str(s: &str) -> Result<Self> {
149        Ok(Id3Timestamp::from_str(s)
150            .map_err(|_| Error::TimestampParseError)?
151            .into())
152    }
153}
154
155impl std::fmt::Display for Timestamp {
156    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157        write!(f, "{}", Id3Timestamp::from(*self))
158    }
159}