mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-12 21:52:33 +00:00
Add tests for reading individual tag formats
This commit is contained in:
parent
f7bb543f36
commit
5638326ff2
22 changed files with 418 additions and 23 deletions
|
@ -5,6 +5,7 @@ use crate::types::tag::TagType;
|
|||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ApeItem {
|
||||
pub read_only: bool,
|
||||
pub(crate) key: String,
|
||||
|
|
|
@ -10,8 +10,9 @@ use crate::types::tag::{Tag, TagType};
|
|||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug, PartialEq)]
|
||||
/// An APE tag
|
||||
pub struct ApeTag {
|
||||
pub read_only: bool,
|
||||
|
@ -33,6 +34,13 @@ impl ApeTag {
|
|||
}
|
||||
|
||||
impl ApeTag {
|
||||
pub fn read_from<R>(reader: &mut R) -> Result<Self>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
Ok(read::read_ape_tag(reader, false)?.0)
|
||||
}
|
||||
|
||||
pub fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
Into::<ApeTagRef>::into(self).write_to(file)
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ pub fn parse_id3v1(reader: [u8; 128]) -> Id3v1Tag {
|
|||
tag.album = decode_text(&reader[60..90]);
|
||||
tag.year = decode_text(&reader[90..94]);
|
||||
|
||||
let range = if reader[119] == 0 && reader[122] != 0 {
|
||||
tag.track_number = Some(reader[122]);
|
||||
let range = if reader[119] == 0 && reader[123] != 0 {
|
||||
tag.track_number = Some(reader[123]);
|
||||
|
||||
94_usize..123
|
||||
94_usize..122
|
||||
} else {
|
||||
94..124
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::types::tag::{Tag, TagType};
|
|||
|
||||
use std::fs::File;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Default, Debug, PartialEq)]
|
||||
/// An ID3v1 tag
|
||||
///
|
||||
/// ID3v1 is a severely limited format, with each field
|
||||
|
@ -59,6 +59,10 @@ impl Id3v1Tag {
|
|||
&& self.genre.is_none()
|
||||
}
|
||||
|
||||
pub fn read_from(tag: [u8; 128]) -> Self {
|
||||
super::read::parse_id3v1(tag)
|
||||
}
|
||||
|
||||
pub fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
Into::<Id3v1TagRef>::into(self).write_to(file)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@ use std::io::Read;
|
|||
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
|
||||
pub(crate) fn parse_id3v2(bytes: &mut &[u8]) -> Result<Id3v2Tag> {
|
||||
pub(crate) fn parse_id3v2<R>(bytes: &mut R) -> Result<Id3v2Tag>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
let mut header = [0; 10];
|
||||
bytes.read_exact(&mut header)?;
|
||||
|
||||
|
|
|
@ -11,9 +11,11 @@ use crate::types::tag::{Tag, TagType};
|
|||
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Id3v2Tag {
|
||||
flags: Id3v2TagFlags,
|
||||
pub(super) original_version: Id3v2Version,
|
||||
|
@ -80,6 +82,13 @@ impl Id3v2Tag {
|
|||
}
|
||||
|
||||
impl Id3v2Tag {
|
||||
pub fn read_from<R>(reader: &mut R) -> Result<Self>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
super::read::parse_id3v2(reader)
|
||||
}
|
||||
|
||||
pub fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
Into::<Id3v2TagRef>::into(self).write_to(file)
|
||||
}
|
||||
|
@ -156,7 +165,7 @@ impl From<Tag> for Id3v2Tag {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
/// Flags that apply to the entire tag
|
||||
pub struct Id3v2TagFlags {
|
||||
|
|
|
@ -27,7 +27,7 @@ impl<B: ByteOrder> Chunks<B> {
|
|||
|
||||
pub fn next<R>(&mut self, data: &mut R) -> Result<()>
|
||||
where
|
||||
R: Read + Seek,
|
||||
R: Read,
|
||||
{
|
||||
data.read_exact(&mut self.fourcc)?;
|
||||
self.size = data.read_u32::<B>()?;
|
||||
|
@ -37,7 +37,7 @@ impl<B: ByteOrder> Chunks<B> {
|
|||
|
||||
pub fn content<R>(&mut self, data: &mut R) -> Result<Vec<u8>>
|
||||
where
|
||||
R: Read + Seek,
|
||||
R: Read,
|
||||
{
|
||||
let mut content = vec![0; self.size as usize];
|
||||
data.read_exact(&mut content)?;
|
||||
|
|
|
@ -6,8 +6,9 @@ use crate::types::item::{ItemKey, ItemValue, TagItem};
|
|||
use crate::types::tag::{Tag, TagType};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug, PartialEq)]
|
||||
/// A RIFF INFO LIST
|
||||
pub struct RiffInfoList {
|
||||
/// A collection of chunk-value pairs
|
||||
|
@ -15,8 +16,12 @@ pub struct RiffInfoList {
|
|||
}
|
||||
|
||||
impl RiffInfoList {
|
||||
pub fn push(&mut self, key: String, value: String) {
|
||||
pub fn insert(&mut self, key: String, value: String) {
|
||||
if valid_key(key.as_str()) {
|
||||
self.items
|
||||
.iter()
|
||||
.position(|(k, _)| k == &key)
|
||||
.map(|p| self.items.remove(p));
|
||||
self.items.push((key, value))
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +39,17 @@ impl RiffInfoList {
|
|||
}
|
||||
|
||||
impl RiffInfoList {
|
||||
pub fn read_from<R>(reader: &mut R, end: u64) -> Result<Self>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let mut tag = Self::default();
|
||||
|
||||
read::parse_riff_info(reader, end, &mut tag)?;
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
pub fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
Into::<RiffInfoListRef>::into(self).write_to(file)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::time::Duration;
|
|||
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
|
||||
|
||||
fn read_properties(
|
||||
mut first_frame: (Header, u64),
|
||||
first_frame: (Header, u64),
|
||||
last_frame: (Header, u64),
|
||||
xing_header: Option<XingHeader>,
|
||||
file_length: u64,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::error::{LoftyError, Result};
|
||||
use crate::logic::mp4::ilst::AtomIdent;
|
||||
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
use crate::mp4::AtomIdent;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
|
||||
pub(crate) struct AtomInfo {
|
||||
|
|
|
@ -1,19 +1,48 @@
|
|||
pub(in crate::logic::mp4) mod read;
|
||||
pub(in crate::logic) mod write;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::types::item::{ItemKey, ItemValue, TagItem};
|
||||
use crate::types::picture::{Picture, PictureType};
|
||||
use crate::types::tag::{Tag, TagType};
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::io::Read;
|
||||
|
||||
#[cfg(feature = "mp4_atoms")]
|
||||
#[derive(Default)]
|
||||
#[derive(Default, PartialEq, Debug)]
|
||||
/// An Mp4
|
||||
pub struct Ilst {
|
||||
pub(crate) atoms: Vec<Atom>,
|
||||
}
|
||||
|
||||
impl Ilst {
|
||||
pub fn atom(&self, ident: &AtomIdent) -> Option<&Atom> {
|
||||
self.atoms.iter().find(|a| &a.ident == ident)
|
||||
}
|
||||
|
||||
pub fn insert_atom(&mut self, atom: Atom) {
|
||||
self.remove_atom(&atom.ident);
|
||||
self.atoms.push(atom);
|
||||
}
|
||||
|
||||
pub fn remove_atom(&mut self, ident: &AtomIdent) {
|
||||
self.atoms
|
||||
.iter()
|
||||
.position(|a| &a.ident == ident)
|
||||
.map(|p| self.atoms.remove(p));
|
||||
}
|
||||
}
|
||||
|
||||
impl Ilst {
|
||||
pub fn read_from<R>(reader: &mut R, len: u64) -> Result<Self>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
read::parse_ilst(reader, len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mp4_atoms")]
|
||||
impl From<Ilst> for Tag {
|
||||
fn from(input: Ilst) -> Self {
|
||||
|
@ -80,11 +109,18 @@ impl From<Tag> for Ilst {
|
|||
}
|
||||
|
||||
#[cfg(feature = "mp4_atoms")]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Atom {
|
||||
ident: AtomIdent,
|
||||
data: AtomData,
|
||||
}
|
||||
|
||||
impl Atom {
|
||||
pub fn new(ident: AtomIdent, data: AtomData) -> Self {
|
||||
Self { ident, data }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum AtomIdent {
|
||||
/// A four byte identifier
|
||||
|
@ -109,6 +145,7 @@ pub enum AtomIdent {
|
|||
}
|
||||
|
||||
#[cfg(feature = "mp4_atoms")]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// The data of an atom
|
||||
///
|
||||
/// NOTES:
|
||||
|
|
|
@ -10,12 +10,12 @@ use std::io::{Cursor, Read, Seek, SeekFrom};
|
|||
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
pub(crate) fn parse_ilst<R>(data: &mut R, len: u64) -> Result<Option<Ilst>>
|
||||
pub(crate) fn parse_ilst<R>(reader: &mut R, len: u64) -> Result<Ilst>
|
||||
where
|
||||
R: Read + Seek,
|
||||
R: Read,
|
||||
{
|
||||
let mut contents = vec![0; len as usize];
|
||||
data.read_exact(&mut contents)?;
|
||||
reader.read_exact(&mut contents)?;
|
||||
|
||||
let mut cursor = Cursor::new(contents);
|
||||
|
||||
|
@ -71,7 +71,7 @@ where
|
|||
tag.atoms.push(Atom { ident, data })
|
||||
}
|
||||
|
||||
Ok(Some(tag))
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
fn parse_data<R>(data: &mut R) -> Result<AtomData>
|
||||
|
|
|
@ -111,7 +111,7 @@ where
|
|||
|
||||
#[cfg(feature = "mp4_atoms")]
|
||||
if islt.0 {
|
||||
return parse_ilst(data, islt.1 - 8);
|
||||
return parse_ilst(data, islt.1 - 8).map(Some);
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
|
|
|
@ -8,19 +8,67 @@ use crate::types::picture::PictureInformation;
|
|||
use crate::types::tag::{Tag, TagType};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, PartialEq, Debug)]
|
||||
/// Vorbis comments
|
||||
pub struct VorbisComments {
|
||||
/// An identifier for the encoding software
|
||||
pub vendor: String,
|
||||
pub(crate) vendor: String,
|
||||
/// A collection of key-value pairs
|
||||
pub items: Vec<(String, String)>,
|
||||
pub(crate) items: Vec<(String, String)>,
|
||||
/// A collection of all pictures
|
||||
pub pictures: Vec<(Picture, PictureInformation)>,
|
||||
pub(crate) pictures: Vec<(Picture, PictureInformation)>,
|
||||
}
|
||||
|
||||
impl VorbisComments {
|
||||
pub fn vendor(&self) -> &str {
|
||||
&self.vendor
|
||||
}
|
||||
|
||||
pub fn set_vendor(&mut self, vendor: String) {
|
||||
self.vendor = vendor
|
||||
}
|
||||
|
||||
pub fn items(&self) -> &[(String, String)] {
|
||||
&self.items
|
||||
}
|
||||
|
||||
pub fn get_item(&self, key: &str) -> Option<&str> {
|
||||
self.items
|
||||
.iter()
|
||||
.find(|(k, _)| k == key)
|
||||
.map(|(_, v)| v.as_str())
|
||||
}
|
||||
|
||||
pub fn insert_item(&mut self, key: String, value: String, replace_all: bool) {
|
||||
if replace_all {
|
||||
self.items
|
||||
.iter()
|
||||
.position(|(k, _)| k == &key)
|
||||
.map(|p| self.items.remove(p));
|
||||
}
|
||||
|
||||
self.items.push((key, value))
|
||||
}
|
||||
|
||||
pub fn remove_key(&mut self, key: &str) {
|
||||
self.items.retain(|(k, _)| k != key);
|
||||
}
|
||||
}
|
||||
|
||||
impl VorbisComments {
|
||||
pub fn read_from<R>(reader: &mut R) -> Result<Self>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
let mut tag = Self::default();
|
||||
|
||||
super::read::read_comments(reader, &mut tag)?;
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
pub fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
Into::<VorbisCommentsRef>::into(self).write_to(file)
|
||||
}
|
||||
|
|
BIN
tests/tags/assets/test.apev2
Normal file
BIN
tests/tags/assets/test.apev2
Normal file
Binary file not shown.
BIN
tests/tags/assets/test.id3v1
Normal file
BIN
tests/tags/assets/test.id3v1
Normal file
Binary file not shown.
BIN
tests/tags/assets/test.id3v2
Normal file
BIN
tests/tags/assets/test.id3v2
Normal file
Binary file not shown.
BIN
tests/tags/assets/test.ilst
Normal file
BIN
tests/tags/assets/test.ilst
Normal file
Binary file not shown.
BIN
tests/tags/assets/test.riff
Normal file
BIN
tests/tags/assets/test.riff
Normal file
Binary file not shown.
BIN
tests/tags/assets/test.vorbis
Normal file
BIN
tests/tags/assets/test.vorbis
Normal file
Binary file not shown.
1
tests/tags/main.rs
Normal file
1
tests/tags/main.rs
Normal file
|
@ -0,0 +1 @@
|
|||
mod read;
|
268
tests/tags/read.rs
Normal file
268
tests/tags/read.rs
Normal file
|
@ -0,0 +1,268 @@
|
|||
use lofty::ape::{ApeItem, ApeTag};
|
||||
use lofty::id3::v1::Id3v1Tag;
|
||||
use lofty::id3::v2::{Frame, FrameFlags, FrameValue, Id3v2Tag, LanguageFrame, TextEncoding};
|
||||
use lofty::iff::RiffInfoList;
|
||||
use lofty::mp4::{Atom, AtomData, AtomIdent, Ilst};
|
||||
use lofty::ogg::VorbisComments;
|
||||
use lofty::ItemValue;
|
||||
|
||||
const APE: [u8; 209] = *include_bytes!("assets/test.apev2");
|
||||
const ID3V1: [u8; 128] = *include_bytes!("assets/test.id3v1");
|
||||
const ID3V2: [u8; 1168] = *include_bytes!("assets/test.id3v2");
|
||||
const ILST: [u8; 1024] = *include_bytes!("assets/test.ilst");
|
||||
const RIFF_INFO: [u8; 100] = *include_bytes!("assets/test.riff");
|
||||
const VORBIS_COMMENTS: [u8; 152] = *include_bytes!("assets/test.vorbis");
|
||||
|
||||
#[test]
|
||||
fn read_ape() {
|
||||
let mut expected_tag = ApeTag::default();
|
||||
|
||||
let title_item = ApeItem::new(
|
||||
String::from("TITLE"),
|
||||
ItemValue::Text(String::from("Foo title")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let artist_item = ApeItem::new(
|
||||
String::from("ARTIST"),
|
||||
ItemValue::Text(String::from("Bar artist")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let album_item = ApeItem::new(
|
||||
String::from("ALBUM"),
|
||||
ItemValue::Text(String::from("Baz album")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let comment_item = ApeItem::new(
|
||||
String::from("COMMENT"),
|
||||
ItemValue::Text(String::from("Qux comment")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let year_item =
|
||||
ApeItem::new(String::from("YEAR"), ItemValue::Text(String::from("1984"))).unwrap();
|
||||
|
||||
let track_number_item =
|
||||
ApeItem::new(String::from("TRACK"), ItemValue::Text(String::from("1"))).unwrap();
|
||||
|
||||
let genre_item = ApeItem::new(
|
||||
String::from("GENRE"),
|
||||
ItemValue::Text(String::from("Classical")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
expected_tag.push_item(title_item);
|
||||
expected_tag.push_item(artist_item);
|
||||
expected_tag.push_item(album_item);
|
||||
expected_tag.push_item(comment_item);
|
||||
expected_tag.push_item(year_item);
|
||||
expected_tag.push_item(track_number_item);
|
||||
expected_tag.push_item(genre_item);
|
||||
|
||||
let parsed_tag = ApeTag::read_from(&mut std::io::Cursor::new(APE)).unwrap();
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_id3v1() {
|
||||
let expected_tag = Id3v1Tag {
|
||||
title: Some(String::from("Foo title")),
|
||||
artist: Some(String::from("Bar artist")),
|
||||
album: Some(String::from("Baz album")),
|
||||
year: Some(String::from("1984")),
|
||||
comment: Some(String::from("Qux comment")),
|
||||
track_number: Some(1),
|
||||
genre: Some(32),
|
||||
};
|
||||
|
||||
let parsed_tag = Id3v1Tag::read_from(ID3V1);
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_id3v2() {
|
||||
let mut expected_tag = Id3v2Tag::default();
|
||||
|
||||
let encoding = TextEncoding::Latin1;
|
||||
let flags = FrameFlags::default();
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TPE1",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("Bar artist"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TIT2",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("Foo title"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TALB",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("Baz album"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"COMM",
|
||||
FrameValue::Comment(LanguageFrame {
|
||||
encoding,
|
||||
language: String::from("eng"),
|
||||
description: String::new(),
|
||||
content: String::from("Qux comment"),
|
||||
}),
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TDRC",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("1984"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TRCK",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("1"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
expected_tag.insert(
|
||||
Frame::new(
|
||||
"TCON",
|
||||
FrameValue::Text {
|
||||
encoding,
|
||||
value: String::from("Classical"),
|
||||
},
|
||||
flags,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let parsed_tag = Id3v2Tag::read_from(&mut &ID3V2[..]).unwrap();
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_mp4_ilst() {
|
||||
let mut expected_tag = Ilst::default();
|
||||
|
||||
// The track number is stored with a code 0,
|
||||
// meaning the there is no need to indicate the type,
|
||||
// which is `u64` in this case
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"trkn"),
|
||||
AtomData::Unknown {
|
||||
code: 0,
|
||||
data: vec![0, 0, 0, 1, 0, 0, 0, 0],
|
||||
},
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9ART"),
|
||||
AtomData::UTF8(String::from("Bar artist")),
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9alb"),
|
||||
AtomData::UTF8(String::from("Baz album")),
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9cmt"),
|
||||
AtomData::UTF8(String::from("Qux comment")),
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9day"),
|
||||
AtomData::UTF8(String::from("1984")),
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9gen"),
|
||||
AtomData::UTF8(String::from("Classical")),
|
||||
));
|
||||
|
||||
expected_tag.insert_atom(Atom::new(
|
||||
AtomIdent::Fourcc(*b"\xa9nam"),
|
||||
AtomData::UTF8(String::from("Foo title")),
|
||||
));
|
||||
|
||||
let parsed_tag = Ilst::read_from(&mut &ILST[..], ILST.len() as u64).unwrap();
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_riff_info() {
|
||||
let mut expected_tag = RiffInfoList::default();
|
||||
|
||||
expected_tag.insert(String::from("IART"), String::from("Bar artist"));
|
||||
expected_tag.insert(String::from("ICMT"), String::from("Qux comment"));
|
||||
expected_tag.insert(String::from("ICRD"), String::from("1984"));
|
||||
expected_tag.insert(String::from("INAM"), String::from("Foo title"));
|
||||
expected_tag.insert(String::from("IPRD"), String::from("Baz album"));
|
||||
expected_tag.insert(String::from("IPRT"), String::from("1"));
|
||||
|
||||
let mut reader = std::io::Cursor::new(&RIFF_INFO[..]);
|
||||
let parsed_tag = RiffInfoList::read_from(&mut reader, (RIFF_INFO.len() - 1) as u64).unwrap();
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_vorbis_comments() {
|
||||
let mut expected_tag = VorbisComments::default();
|
||||
|
||||
expected_tag.set_vendor(String::from("Lavf58.76.100"));
|
||||
|
||||
expected_tag.insert_item(String::from("ALBUM"), String::from("Baz album"), false);
|
||||
expected_tag.insert_item(String::from("ARTIST"), String::from("Bar artist"), false);
|
||||
expected_tag.insert_item(String::from("COMMENT"), String::from("Qux comment"), false);
|
||||
expected_tag.insert_item(String::from("DATE"), String::from("1984"), false);
|
||||
expected_tag.insert_item(String::from("GENRE"), String::from("Classical"), false);
|
||||
expected_tag.insert_item(String::from("TITLE"), String::from("Foo title"), false);
|
||||
expected_tag.insert_item(String::from("TRACKNUMBER"), String::from("1"), false);
|
||||
|
||||
let parsed_tag = VorbisComments::read_from(&mut &VORBIS_COMMENTS[..]).unwrap();
|
||||
|
||||
assert_eq!(expected_tag, parsed_tag);
|
||||
}
|
Loading…
Reference in a new issue