1use std::borrow::Cow;
11use std::collections::VecDeque;
12use std::convert::From;
13use std::fmt;
14use std::num::NonZeroU32;
15
16use crate::errors::Result;
17use crate::io::MediaSourceStream;
18
19#[derive(Copy, Clone, Debug)]
27pub enum Limit {
28 None,
30 Default,
32 Maximum(usize),
34}
35
36impl Limit {
37 pub fn limit_or_default(&self, default: usize) -> Option<usize> {
40 match self {
41 Limit::None => None,
42 Limit::Default => Some(default),
43 Limit::Maximum(max) => Some(*max),
44 }
45 }
46}
47
48impl Default for Limit {
49 fn default() -> Self {
50 Limit::Default
51 }
52}
53
54#[derive(Copy, Clone, Debug, Default)]
56pub struct MetadataOptions {
57 pub limit_metadata_bytes: Limit,
61
62 pub limit_visual_bytes: Limit,
64}
65
66#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
73pub enum StandardVisualKey {
74 FileIcon,
75 OtherIcon,
76 FrontCover,
77 BackCover,
78 Leaflet,
79 Media,
80 LeadArtistPerformerSoloist,
81 ArtistPerformer,
82 Conductor,
83 BandOrchestra,
84 Composer,
85 Lyricist,
86 RecordingLocation,
87 RecordingSession,
88 Performance,
89 ScreenCapture,
90 Illustration,
91 BandArtistLogo,
92 PublisherStudioLogo,
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
99pub enum StandardTagKey {
100 AcoustidFingerprint,
101 AcoustidId,
102 Album,
103 AlbumArtist,
104 Arranger,
105 Artist,
106 Bpm,
107 Comment,
108 Compilation,
109 Composer,
110 Conductor,
111 ContentGroup,
112 Copyright,
113 Date,
114 Description,
115 DiscNumber,
116 DiscSubtitle,
117 DiscTotal,
118 EncodedBy,
119 Encoder,
120 EncoderSettings,
121 EncodingDate,
122 Engineer,
123 Ensemble,
124 Genre,
125 IdentAsin,
126 IdentBarcode,
127 IdentCatalogNumber,
128 IdentEanUpn,
129 IdentIsrc,
130 IdentPn,
131 IdentPodcast,
132 IdentUpc,
133 Label,
134 Language,
135 License,
136 Lyricist,
137 Lyrics,
138 MediaFormat,
139 MixDj,
140 MixEngineer,
141 Mood,
142 MovementName,
143 MovementNumber,
144 MusicBrainzAlbumArtistId,
145 MusicBrainzAlbumId,
146 MusicBrainzArtistId,
147 MusicBrainzDiscId,
148 MusicBrainzGenreId,
149 MusicBrainzLabelId,
150 MusicBrainzOriginalAlbumId,
151 MusicBrainzOriginalArtistId,
152 MusicBrainzRecordingId,
153 MusicBrainzReleaseGroupId,
154 MusicBrainzReleaseStatus,
155 MusicBrainzReleaseTrackId,
156 MusicBrainzReleaseType,
157 MusicBrainzTrackId,
158 MusicBrainzWorkId,
159 Opus,
160 OriginalAlbum,
161 OriginalArtist,
162 OriginalDate,
163 OriginalFile,
164 OriginalWriter,
165 Owner,
166 Part,
167 PartTotal,
168 Performer,
169 Podcast,
170 PodcastCategory,
171 PodcastDescription,
172 PodcastKeywords,
173 Producer,
174 PurchaseDate,
175 Rating,
176 ReleaseCountry,
177 ReleaseDate,
178 Remixer,
179 ReplayGainAlbumGain,
180 ReplayGainAlbumPeak,
181 ReplayGainTrackGain,
182 ReplayGainTrackPeak,
183 Script,
184 SortAlbum,
185 SortAlbumArtist,
186 SortArtist,
187 SortComposer,
188 SortTrackTitle,
189 TaggingDate,
190 TrackNumber,
191 TrackSubtitle,
192 TrackTitle,
193 TrackTotal,
194 TvEpisode,
195 TvEpisodeTitle,
196 TvNetwork,
197 TvSeason,
198 TvShowTitle,
199 Url,
200 UrlArtist,
201 UrlCopyright,
202 UrlInternetRadio,
203 UrlLabel,
204 UrlOfficial,
205 UrlPayment,
206 UrlPodcast,
207 UrlPurchase,
208 UrlSource,
209 Version,
210 Writer,
211}
212
213#[derive(Clone, Debug)]
219pub enum Value {
220 Binary(Box<[u8]>),
222 Boolean(bool),
224 Flag,
227 Float(f64),
229 SignedInt(i64),
231 String(String),
233 UnsignedInt(u64),
235}
236
237macro_rules! impl_from_for_value {
238 ($value:ident, $from:ty, $conv:expr) => {
239 impl From<$from> for Value {
240 fn from($value: $from) -> Self {
241 $conv
242 }
243 }
244 };
245}
246
247impl_from_for_value!(v, &[u8], Value::Binary(Box::from(v)));
248impl_from_for_value!(v, bool, Value::Boolean(v));
249impl_from_for_value!(v, f32, Value::Float(f64::from(v)));
250impl_from_for_value!(v, f64, Value::Float(v));
251impl_from_for_value!(v, i8, Value::SignedInt(i64::from(v)));
252impl_from_for_value!(v, i16, Value::SignedInt(i64::from(v)));
253impl_from_for_value!(v, i32, Value::SignedInt(i64::from(v)));
254impl_from_for_value!(v, i64, Value::SignedInt(v));
255impl_from_for_value!(v, u8, Value::UnsignedInt(u64::from(v)));
256impl_from_for_value!(v, u16, Value::UnsignedInt(u64::from(v)));
257impl_from_for_value!(v, u32, Value::UnsignedInt(u64::from(v)));
258impl_from_for_value!(v, u64, Value::UnsignedInt(v));
259impl_from_for_value!(v, &str, Value::String(String::from(v)));
260impl_from_for_value!(v, String, Value::String(v));
261impl_from_for_value!(v, Cow<'_, str>, Value::String(String::from(v)));
262
263fn buffer_to_hex_string(buf: &[u8]) -> String {
264 let mut output = String::with_capacity(5 * buf.len());
265
266 for ch in buf {
267 let u = (ch & 0xf0) >> 4;
268 let l = ch & 0x0f;
269 output.push_str("\\0x");
270 output.push(if u < 10 { (b'0' + u) as char } else { (b'a' + u - 10) as char });
271 output.push(if l < 10 { (b'0' + l) as char } else { (b'a' + l - 10) as char });
272 }
273
274 output
275}
276
277impl fmt::Display for Value {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 match self {
281 Value::Binary(ref buf) => f.write_str(&buffer_to_hex_string(buf)),
282 Value::Boolean(boolean) => fmt::Display::fmt(boolean, f),
283 Value::Flag => write!(f, "<flag>"),
284 Value::Float(float) => fmt::Display::fmt(float, f),
285 Value::SignedInt(int) => fmt::Display::fmt(int, f),
286 Value::String(ref string) => fmt::Display::fmt(string, f),
287 Value::UnsignedInt(uint) => fmt::Display::fmt(uint, f),
288 }
289 }
290}
291
292#[derive(Clone, Debug)]
294pub struct Tag {
295 pub std_key: Option<StandardTagKey>,
302 pub key: String,
306 pub value: Value,
308}
309
310impl Tag {
311 pub fn new(std_key: Option<StandardTagKey>, key: &str, value: Value) -> Tag {
313 Tag { std_key, key: key.to_string(), value }
314 }
315
316 pub fn is_known(&self) -> bool {
319 self.std_key.is_some()
320 }
321}
322
323impl fmt::Display for Tag {
324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
325 match self.std_key {
326 Some(ref std_key) => {
327 write!(f, "{{ std_key={:?}, key=\"{}\", value={} }}", std_key, self.key, self.value)
328 }
329 None => write!(f, "{{ key=\"{}\", value={} }}", self.key, self.value),
330 }
331 }
332}
333
334#[derive(Copy, Clone, Debug, Default)]
336pub struct Size {
337 pub width: u32,
339 pub height: u32,
341}
342
343#[derive(Copy, Clone, Debug)]
345pub enum ColorMode {
346 Discrete,
348 Indexed(NonZeroU32),
352}
353
354#[derive(Clone, Debug)]
356pub struct Visual {
357 pub media_type: String,
359 pub dimensions: Option<Size>,
364 pub bits_per_pixel: Option<NonZeroU32>,
369 pub color_mode: Option<ColorMode>,
374 pub usage: Option<StandardVisualKey>,
376 pub tags: Vec<Tag>,
378 pub data: Box<[u8]>,
380}
381
382#[derive(Clone, Debug)]
384pub struct VendorData {
385 pub ident: String,
387 pub data: Box<[u8]>,
389}
390
391#[derive(Clone, Debug, Default)]
393pub struct MetadataRevision {
394 tags: Vec<Tag>,
395 visuals: Vec<Visual>,
396 vendor_data: Vec<VendorData>,
397}
398
399impl MetadataRevision {
400 pub fn tags(&self) -> &[Tag] {
405 &self.tags
406 }
407
408 pub fn visuals(&self) -> &[Visual] {
410 &self.visuals
411 }
412
413 pub fn vendor_data(&self) -> &[VendorData] {
415 &self.vendor_data
416 }
417}
418
419#[derive(Clone, Debug, Default)]
421pub struct MetadataBuilder {
422 metadata: MetadataRevision,
423}
424
425impl MetadataBuilder {
426 pub fn new() -> Self {
428 MetadataBuilder { metadata: Default::default() }
429 }
430
431 pub fn add_tag(&mut self, tag: Tag) -> &mut Self {
433 self.metadata.tags.push(tag);
434 self
435 }
436
437 pub fn add_visual(&mut self, visual: Visual) -> &mut Self {
439 self.metadata.visuals.push(visual);
440 self
441 }
442
443 pub fn add_vendor_data(&mut self, vendor_data: VendorData) -> &mut Self {
445 self.metadata.vendor_data.push(vendor_data);
446 self
447 }
448
449 pub fn metadata(self) -> MetadataRevision {
451 self.metadata
452 }
453}
454
455#[derive(Debug)]
457pub struct Metadata<'a> {
458 revisions: &'a mut VecDeque<MetadataRevision>,
459}
460
461impl<'a> Metadata<'a> {
462 pub fn is_latest(&self) -> bool {
464 self.revisions.len() <= 1
465 }
466
467 pub fn current(&self) -> Option<&MetadataRevision> {
469 self.revisions.front()
470 }
471
472 pub fn skip_to_latest(&mut self) -> Option<&MetadataRevision> {
475 loop {
476 if self.pop().is_none() {
477 break;
478 }
479 }
480 self.current()
481 }
482
483 pub fn pop(&mut self) -> Option<MetadataRevision> {
488 if self.revisions.len() > 1 {
489 self.revisions.pop_front()
490 }
491 else {
492 None
493 }
494 }
495}
496
497#[derive(Clone, Debug, Default)]
499pub struct MetadataLog {
500 revisions: VecDeque<MetadataRevision>,
501}
502
503impl MetadataLog {
504 pub fn metadata(&mut self) -> Metadata<'_> {
506 Metadata { revisions: &mut self.revisions }
507 }
508
509 pub fn push(&mut self, rev: MetadataRevision) {
511 self.revisions.push_back(rev);
512 }
513}
514
515pub trait MetadataReader: Send + Sync {
516 fn new(options: &MetadataOptions) -> Self
518 where
519 Self: Sized;
520
521 fn read_all(&mut self, reader: &mut MediaSourceStream) -> Result<MetadataRevision>;
523}