use std::num::NonZeroU32;
use symphonia_core::errors::{decode_error, Result};
use symphonia_core::io::ReadBytes;
use symphonia_core::meta::{ColorMode, MetadataBuilder, Size, StandardTagKey, Tag, Value, Visual};
use crate::{id3v2, vorbis};
fn printable_ascii_to_string(bytes: &[u8]) -> Option<String> {
let mut result = String::with_capacity(bytes.len());
for c in bytes {
match c {
0x00 => break,
0x20..=0x7e => result.push(char::from(*c)),
_ => return None,
}
}
Some(result)
}
pub fn read_comment_block<B: ReadBytes>(
reader: &mut B,
metadata: &mut MetadataBuilder,
) -> Result<()> {
vorbis::read_comment_no_framing(reader, metadata)
}
pub fn read_picture_block<B: ReadBytes>(
reader: &mut B,
metadata: &mut MetadataBuilder,
) -> Result<()> {
let type_enc = reader.read_be_u32()?;
let media_type_len = reader.read_be_u32()? as usize;
let mut media_type_buf = vec![0u8; media_type_len];
reader.read_buf_exact(&mut media_type_buf)?;
let media_type = match printable_ascii_to_string(&media_type_buf) {
Some(s) => s,
None => return decode_error("meta (flac): picture mime-type contains invalid characters"),
};
let desc_len = reader.read_be_u32()? as usize;
let mut desc_buf = vec![0u8; desc_len];
reader.read_buf_exact(&mut desc_buf)?;
let desc = String::from_utf8_lossy(&desc_buf);
let tags = vec![Tag::new(Some(StandardTagKey::Description), "DESCRIPTION", Value::from(desc))];
let width = reader.read_be_u32()?;
let height = reader.read_be_u32()?;
let dimensions = if width > 0 && height > 0 { Some(Size { width, height }) } else { None };
let bits_per_pixel = NonZeroU32::new(reader.read_be_u32()?);
let indexed_colours_enc = reader.read_be_u32()?;
let color_mode = match indexed_colours_enc {
0 => Some(ColorMode::Discrete),
_ => Some(ColorMode::Indexed(NonZeroU32::new(indexed_colours_enc).unwrap())),
};
let data_len = reader.read_be_u32()? as usize;
let data = reader.read_boxed_slice_exact(data_len)?;
metadata.add_visual(Visual {
media_type,
dimensions,
bits_per_pixel,
color_mode,
usage: id3v2::util::apic_picture_type_to_visual_key(type_enc),
tags,
data,
});
Ok(())
}