symphonia_metadata/
flac.rs1use std::num::NonZeroU32;
11
12use symphonia_core::errors::{decode_error, Result};
13use symphonia_core::io::ReadBytes;
14use symphonia_core::meta::{ColorMode, MetadataBuilder, Size, StandardTagKey, Tag, Value, Visual};
15
16use crate::{id3v2, vorbis};
17
18fn printable_ascii_to_string(bytes: &[u8]) -> Option<String> {
21 let mut result = String::with_capacity(bytes.len());
22
23 for c in bytes {
24 match c {
25 0x00 => break,
26 0x20..=0x7e => result.push(char::from(*c)),
27 _ => return None,
28 }
29 }
30
31 Some(result)
32}
33
34pub fn read_comment_block<B: ReadBytes>(
36 reader: &mut B,
37 metadata: &mut MetadataBuilder,
38) -> Result<()> {
39 vorbis::read_comment_no_framing(reader, metadata)
40}
41
42pub fn read_picture_block<B: ReadBytes>(
44 reader: &mut B,
45 metadata: &mut MetadataBuilder,
46) -> Result<()> {
47 let type_enc = reader.read_be_u32()?;
48
49 let media_type_len = reader.read_be_u32()? as usize;
51
52 let mut media_type_buf = vec![0u8; media_type_len];
54 reader.read_buf_exact(&mut media_type_buf)?;
55
56 let media_type = match printable_ascii_to_string(&media_type_buf) {
58 Some(s) => s,
59 None => return decode_error("meta (flac): picture mime-type contains invalid characters"),
60 };
61
62 let desc_len = reader.read_be_u32()? as usize;
64
65 let mut desc_buf = vec![0u8; desc_len];
67 reader.read_buf_exact(&mut desc_buf)?;
68
69 let desc = String::from_utf8_lossy(&desc_buf);
70
71 let tags = vec![Tag::new(Some(StandardTagKey::Description), "DESCRIPTION", Value::from(desc))];
73
74 let width = reader.read_be_u32()?;
76 let height = reader.read_be_u32()?;
77
78 let dimensions = if width > 0 && height > 0 { Some(Size { width, height }) } else { None };
80
81 let bits_per_pixel = NonZeroU32::new(reader.read_be_u32()?);
83
84 let indexed_colours_enc = reader.read_be_u32()?;
87
88 let color_mode = match indexed_colours_enc {
89 0 => Some(ColorMode::Discrete),
90 _ => Some(ColorMode::Indexed(NonZeroU32::new(indexed_colours_enc).unwrap())),
91 };
92
93 let data_len = reader.read_be_u32()? as usize;
95 let data = reader.read_boxed_slice_exact(data_len)?;
96
97 metadata.add_visual(Visual {
98 media_type,
99 dimensions,
100 bits_per_pixel,
101 color_mode,
102 usage: id3v2::util::apic_picture_type_to_visual_key(type_enc),
103 tags,
104 data,
105 });
106
107 Ok(())
108}