From 2db99df934c29f03b842a43245f1e93d7d4ade27 Mon Sep 17 00:00:00 2001 From: "alterwain@protonmail.com" Date: Wed, 12 Feb 2025 06:03:43 +0300 Subject: [PATCH] modified: Cargo.lock modified: Cargo.toml modified: src/deserializer.rs modified: src/lib.rs modified: src/objects.rs modified: src/serializer.rs modified: src/xobjects.rs --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/deserializer.rs | 47 +++++++++++++------------------- src/lib.rs | 5 ---- src/objects.rs | 66 +++++++++++++++++++++++---------------------- src/serializer.rs | 17 +++++------- src/xobjects.rs | 2 +- 7 files changed, 63 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 849bc37..0add175 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,7 +90,7 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "itunesdb" -version = "0.1.1" +version = "0.1.2" dependencies = [ "bincode", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 7a4369f..fc30445 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "itunesdb" -version = "0.1.1" +version = "0.1.2" edition = "2021" authors = ["alterwain"] diff --git a/src/deserializer.rs b/src/deserializer.rs index ca8f8d3..ee00a85 100644 --- a/src/deserializer.rs +++ b/src/deserializer.rs @@ -38,7 +38,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { let ds: DataSet = bincode::deserialize(&data[i..i+u]).unwrap(); info!("DataSet: {:?}", ds); last_type = ds.data_type; - xdb.children.push(XDataSet { header: header, data: ds.clone(), child: match ds.data_type { + xdb.children.push(XDataSet { header, data: ds, child: match ds.data_type { 4 => XSomeList::AlbumList(Vec::new()), // Album List 1 => XSomeList::TrackList(Vec::new()), // Track List _ => XSomeList::Playlists(Vec::new()) // Playlist List 3 @@ -55,7 +55,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { info!("val: {:?}", ai); info!("AlbumItem: {}", u); if let XSomeList::AlbumList(albums) = &mut xdb.find_dataset(4).child { - albums.push(XAlbumItem {header: header, data: ai,args: Vec::new()}); + albums.push(XAlbumItem {header, data: ai,args: Vec::new()}); } }, ChunkType::TrackList => { @@ -68,7 +68,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { let ti: TrackItem = bincode::deserialize(&data[i..i+u]).unwrap(); info!("val: {:?}", ti); if let XSomeList::TrackList(tracks) = &mut xdb.find_dataset(1).child { - tracks.push(XTrackItem {header: header, data: ti,args: Vec::new()}); + tracks.push(XTrackItem {header, data: ti,args: Vec::new()}); } }, ChunkType::SongReference => { @@ -123,15 +123,12 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { h += 4; } //info!("Indexes: {:?}", v); - match &mut xdb.find_dataset(last_type).child { - XSomeList::Playlists(playlists) => { - if playlists.last().unwrap().elems.is_empty() { - playlists.last_mut().unwrap().args.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v})); - } else { - playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v})); - } + if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child { + if playlists.last().unwrap().elems.is_empty() { + playlists.last_mut().unwrap().args.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v})); + } else { + playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v})); } - _ => {} } }, 53 => { @@ -144,28 +141,22 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { h += 12; } info!("Indexes: {:?}", v); - match &mut xdb.find_dataset(last_type).child { - XSomeList::Playlists(playlists) => { - if playlists.last().unwrap().elems.is_empty() { - playlists.last_mut().unwrap().args.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v })); - } else { - playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v })); - } + if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child { + if playlists.last().unwrap().elems.is_empty() { + playlists.last_mut().unwrap().args.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v })); + } else { + playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v })); } - _ => {} } }, 100 | 102 | 50 | 51 => { info!("Entry #100,102 fetched"); - match &mut xdb.find_dataset(last_type).child { - XSomeList::Playlists(playlists) => { - if playlists.last().unwrap().elems.is_empty() { - playlists.last_mut().unwrap().args.push(XPlArgument::RawArgument(data[i-12..i+(header.children_count as usize)-12].to_vec())); - } else { - playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::RawArgument(data[i-12..i+(header.children_count as usize)-12].to_vec())); - } + if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child { + if playlists.last().unwrap().elems.is_empty() { + playlists.last_mut().unwrap().args.push(XPlArgument::RawArgument(data[i-12..i+(header.children_count as usize)-12].to_vec())); + } else { + playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::RawArgument(data[i-12..i+(header.children_count as usize)-12].to_vec())); } - _ => {} } }, _ => warn!("Unknown entry: {}", entry_type) @@ -181,7 +172,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { let playlist: Playlist = bincode::deserialize(&data[i..i+u]).unwrap(); info!("playlist: {:?}", playlist); if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child { // 3 - playlists.push(XPlaylist {header: header, data: playlist,args: Vec::new(), elems: Vec::new()}); + playlists.push(XPlaylist {header, data: playlist,args: Vec::new(), elems: Vec::new()}); } }, _ => { u = 1; info!("Unknown stuff happened"); } diff --git a/src/lib.rs b/src/lib.rs index c5e048b..02d9bfc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,3 @@ -use std::{fs::File, io::{Read, Write}}; -use env_logger::Builder; -use log::{error, info, LevelFilter}; -use rand::Rng; -use xobjects::{XArgument, XPlArgument, XSomeList}; pub mod objects; pub mod xobjects; diff --git a/src/objects.rs b/src/objects.rs index b07517d..351cbc7 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -11,7 +11,7 @@ pub enum ChunkType { PlaylistList, Playlist, SongReference, - Unknown + Unknown, } impl From<[u8; 4]> for ChunkType { @@ -27,7 +27,7 @@ impl From<[u8; 4]> for ChunkType { [0x6D, 0x68, 0x69, 0x70] => ChunkType::SongReference, [0x6D, 0x68, 0x6C, 0x70] => ChunkType::PlaylistList, [0x6D, 0x68, 0x79, 0x70] => ChunkType::Playlist, - _ => ChunkType::Unknown + _ => ChunkType::Unknown, } } } @@ -45,7 +45,7 @@ impl From for [u8; 4] { ChunkType::StringTypes => [0x6D, 0x68, 0x6F, 0x64], ChunkType::PlaylistList => [0x6D, 0x68, 0x6C, 0x70], ChunkType::Playlist => [0x6D, 0x68, 0x79, 0x70], - ChunkType::Unknown => [0x00, 0x00, 0x00, 0x00] + ChunkType::Unknown => [0x00, 0x00, 0x00, 0x00], } } } @@ -54,7 +54,7 @@ impl From for [u8; 4] { pub struct ChunkHeader { pub chunk_type: [u8; 4], pub end_of_chunk: u32, - pub children_count: u32 + pub children_count: u32, } #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -69,12 +69,12 @@ pub struct Database { hash: [u8; 20], unk: [u8; 30], unk1: [u8; 32], - unk2: [u8; 20] + unk2: [u8; 20], } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] pub struct DataSet { - pub data_type: u32 + pub data_type: u32, } #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -83,32 +83,32 @@ pub struct AlbumItem { unknown: u16, album_id_for_track: u16, timestamp: u64, - unknown1: u32 + unknown1: u32, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] pub struct TrackItem { - pub number_of_strings: u32, // number of mhod's count + pub number_of_strings: u32, // number of mhod's count pub unique_id: u32, visible: u32, - filetype: u32, + pub filetype: u32, type1: u8, type2: u8, compilation_flag: u8, - stars: u8, - last_modified_time: u32, - size: u32, - length: u32, + pub stars: u8, + pub last_modified_time: u32, + pub size: u32, + pub length: u32, track_number: u32, total_tracks: u32, - year: u32, - bitrate: u32, - sample_rate: u32, + pub year: u32, + pub bitrate: u32, + pub sample_rate: u32, volume: u32, start_time: u32, stop_time: u32, soundcheck: u32, - play_count: u32, + pub play_count: u32, play_count2: u32, last_played_time: u32, disc_number: u32, @@ -119,7 +119,7 @@ pub struct TrackItem { pub dbid: u64, checked: u8, application_rating: u8, - bpm: u16, + pub bpm: u16, artwork_count: u16, unk9: u16, artwork_size: u32, @@ -129,9 +129,9 @@ pub struct TrackItem { unk14: u32, unk15: u32, unk16: u32, - skip_count: u32, + pub skip_count: u32, last_skipped: u32, - has_artwork: u8, + pub has_artwork: u8, skip_when_shuffling: u8, remember_playback_position: u8, flag4: u8, @@ -146,7 +146,7 @@ pub struct TrackItem { unk25: u32, postgap: u32, unk27: u32, - media_type: u32, + pub media_type: u32, season_number: u32, episode_number: u32, unk31: [u8; 28], @@ -164,22 +164,24 @@ pub struct TrackItem { unk3: [u8; 32], unk4: [u8; 32], unk5: [u8; 32], - unk6: [u8; 32] + unk6: [u8; 32], } #[derive(Serialize, Deserialize, PartialEq, Debug)] -pub struct StringEntry { // mhod +pub struct StringEntry { + // mhod pub entry_type: u32, pub unk1: u32, pub unk2: u32, pub position: u32, pub length: u32, pub unknown: u32, - pub unk4: u32 + pub unk4: u32, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct PlaylistIndexEntry { // mhod +pub struct PlaylistIndexEntry { + // mhod entry_type: u32, unk1: u32, unk2: u32, @@ -189,7 +191,7 @@ pub struct PlaylistIndexEntry { // mhod null_padding1: u64, null_padding2: u64, null_padding3: u64, - null_padding4: u64 + null_padding4: u64, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] @@ -199,14 +201,14 @@ pub struct LetterJumpEntry { unk2: u32, index_type: u32, pub count: u32, - null_padding: u64 + null_padding: u64, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct JumpTable { - letter: u32, // UTF-16 LE Uppercase with two padding null bytes - entry_num: u32, // the number of the first entry in the corresponding MHOD52 index starting with this letter. Zero-based and incremented by one for each entry, not 4. - count: u32 // the count of entries starting with this letter in the corresponding MHOD52. + letter: u32, // UTF-16 LE Uppercase with two padding null bytes + entry_num: u32, // the number of the first entry in the corresponding MHOD52 index starting with this letter. Zero-based and incremented by one for each entry, not 4. + count: u32, // the count of entries starting with this letter in the corresponding MHOD52. } #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -235,5 +237,5 @@ pub struct PlaylistItem { timestamp: u32, podcast_grouping_reference: u32, unk: [u8; 30], - unk1: [u8; 10] -} \ No newline at end of file + unk1: [u8; 10], +} diff --git a/src/serializer.rs b/src/serializer.rs index 0da8f06..9217e60 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -1,17 +1,15 @@ -use log::info; -use crate::{objects::{ChunkHeader, ChunkType, PlaylistItem, StringEntry}, xobjects::{XArgument, XDatabase, XLetterJump, XPlArgument, XPlaylistIndexEntry, XSomeList}}; +use crate::{objects::{ChunkHeader, ChunkType, StringEntry}, xobjects::{XArgument, XDatabase, XLetterJump, XPlArgument, XPlaylistIndexEntry, XSomeList}}; fn string_to_ipod16(str: &str) -> Vec { - str.encode_utf16().map(|f| [f as u8, (f >> 8) as u8]).flatten().collect() + str.encode_utf16().flat_map(|f| [f as u8, (f >> 8) as u8]).collect() } fn x_args_to_bytes(args: &Vec) -> Vec { args.iter() .filter(|arg| arg.arg_type <= 15) - .map(serialize_string_arg) - .flatten() + .flat_map(serialize_string_arg) .collect() } @@ -46,7 +44,7 @@ fn serialize_string_arg(xarg: &XArgument) -> Vec { children_count: 16 + 0x18 + s.len() as u32 }).unwrap(); b = [h, b, s].concat(); - return b; + b } fn serialize_index_entry(xpl: &XPlaylistIndexEntry) -> Vec { @@ -61,7 +59,7 @@ fn serialize_index_entry(xpl: &XPlaylistIndexEntry) -> Vec { children_count: 12 + (v.len() + b.len()) as u32 }).unwrap(); b = [h, b, v].concat(); - return b; + b } fn serialize_x_letter(xjump: &XLetterJump) -> Vec { @@ -76,18 +74,17 @@ fn serialize_x_letter(xjump: &XLetterJump) -> Vec { children_count: 12 + (v.len() + b.len()) as u32 }).unwrap(); b = [h, b, v].concat(); - return b; + b } fn serialize_arguments(pl: &Vec) -> Vec { pl.iter() - .map(|arg| match arg { + .flat_map(|arg| match arg { XPlArgument::String(xarg) => serialize_string_arg(xarg), XPlArgument::IndexEntry(xpl) => serialize_index_entry(xpl), XPlArgument::LetterJumpEntry(xjump) => serialize_x_letter(xjump), XPlArgument::RawArgument(raw_arg) => raw_arg.to_vec() }) - .flatten() .collect() } diff --git a/src/xobjects.rs b/src/xobjects.rs index e345c13..3ce5265 100644 --- a/src/xobjects.rs +++ b/src/xobjects.rs @@ -107,7 +107,7 @@ impl XDatabase { fn add_track_to_playlists(&mut self, n: u32, track: &XTrackItem) { if let XSomeList::Playlists(playlists) = &mut self.find_dataset(n).child { let playlist = playlists.last_mut().unwrap(); - playlist.data.playlist_item_count = playlist.data.playlist_item_count + 1; + playlist.data.playlist_item_count += 1; let elem = playlist.elems.last().unwrap(); let mut pl_item = elem.0.clone();