id3/stream/frame/
v2.rs

1use crate::frame::Frame;
2use crate::stream::encoding::Encoding;
3use crate::stream::frame;
4use crate::tag::Version;
5use crate::{Error, ErrorKind};
6use byteorder::{BigEndian, WriteBytesExt};
7use std::io;
8
9pub fn decode(mut reader: impl io::Read) -> crate::Result<Option<(usize, Frame)>> {
10    let mut frame_header = [0; 6];
11    let nread = reader.read(&mut frame_header)?;
12    if nread < frame_header.len() || frame_header[0] == 0x00 {
13        return Ok(None);
14    }
15    let id = frame::str_from_utf8(&frame_header[0..3])?;
16    let sizebytes = &frame_header[3..6];
17    let read_size =
18        (u32::from(sizebytes[0]) << 16) | (u32::from(sizebytes[1]) << 8) | u32::from(sizebytes[2]);
19    let (content, encoding) =
20        super::content::decode(id, Version::Id3v22, reader.take(u64::from(read_size)))?;
21    let frame = Frame::with_content(id, content).set_encoding(encoding);
22    Ok(Some((6 + read_size as usize, frame)))
23}
24
25pub fn encode(mut writer: impl io::Write, frame: &Frame) -> crate::Result<usize> {
26    let mut content_buf = Vec::new();
27    frame::content::encode(
28        &mut content_buf,
29        frame.content(),
30        Version::Id3v22,
31        frame.encoding().unwrap_or(Encoding::UTF16),
32    )?;
33    assert_ne!(0, content_buf.len());
34    let id = frame.id_for_version(Version::Id3v22).ok_or_else(|| {
35        Error::new(
36            ErrorKind::InvalidInput,
37            "Unable to downgrade frame ID to ID3v2.2",
38        )
39    })?;
40    assert_eq!(3, id.len());
41    writer.write_all(id.as_bytes())?;
42    writer.write_u24::<BigEndian>(content_buf.len() as u32)?;
43    writer.write_all(&content_buf)?;
44    Ok(6 + content_buf.len())
45}