From b7bc68933e4de602583049beb282455828d32b96 Mon Sep 17 00:00:00 2001 From: "alterwain@protonmail.com" Date: Sat, 15 Feb 2025 19:23:52 +0300 Subject: [PATCH] 0.1.20 upd --- Cargo.toml | 2 +- src/artworkdb.rs | 214 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 3 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/artworkdb.rs diff --git a/Cargo.toml b/Cargo.toml index abddeb9..332f0ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "itunesdb" -version = "0.1.19" +version = "0.1.20" edition = "2021" authors = ["alterwain"] diff --git a/src/artworkdb.rs b/src/artworkdb.rs new file mode 100644 index 0000000..42977ca --- /dev/null +++ b/src/artworkdb.rs @@ -0,0 +1,214 @@ +pub mod deserializer { + use log::info; + use crate::artworkdb::aobjects::{ADataSet, ADatabase, AImageItem, ASomeList}; + use crate::artworkdb::objects::{ChunkHeader, ChunkType, DataSet, Database, ImageItem, ImageName}; + + enum ChunkState { + Header, + Data + } + + pub fn parse_bytes(data: &[u8]) -> ADatabase { + let mut adb = ADatabase {data: None, header: None, children: Vec::new() }; + let mut state = ChunkState::Header; + let mut chunk_header: Option = None; + let mut last_type: u32 = 0; + let mut i = 0; + while i < data.len() { + state = match state { + ChunkState::Header => { + if i + 12 >= data.len() { break; } + chunk_header = Some(bincode::deserialize(&data[i..i + 12]).unwrap()); + i += 12; + ChunkState::Data + }, + ChunkState::Data => { + let mut u = 0; + let header = chunk_header.unwrap(); + match ChunkType::from(header.chunk_type) { + ChunkType::ArtworkDB => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let db: Database = bincode::deserialize(&data[i..i+u]).unwrap(); + info!("val: {:?}", db); + adb.data = Some(db); + adb.header = Some(header); + }, + ChunkType::DataSet => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let ds: DataSet = bincode::deserialize(&data[i..i + u]).unwrap(); + last_type = ds.data_type; + adb.children.push(ADataSet { header, data: ds, child: match ds.data_type { + _ => ASomeList::Images(Vec::new()), // 1 + }}); + }, + ChunkType::ImageList => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + }, + ChunkType::ImageItem => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let ai: ImageItem = bincode::deserialize(&data[i..i+u]).unwrap(); + if let ASomeList::Images(images) = &mut adb.find_dataset(1).child { + images.push(AImageItem { data: ai, name: None }); + } + }, + ChunkType::LocationTag => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + }, + ChunkType::ImageName => { + u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let ds: ImageName = bincode::deserialize(&data[i..i + u]).unwrap(); + if let ASomeList::Images(images) = &mut adb.find_dataset(1).child { + images.last_mut().unwrap().name = Some(ds); + } + }, + _ => { u = 1; info!("Unknown stuff happened"); } + } + i += u; + chunk_header = None; + ChunkState::Header + } + } + } + adb + } +} + +pub mod aobjects { + use crate::artworkdb::objects::{ChunkHeader, DataSet, Database, ImageItem, ImageName}; + + #[derive(Debug, serde::Serialize)] + pub struct ADatabase { + pub header: Option, + pub data: Option, + pub children: Vec + } + + impl ADatabase { + pub(crate) fn find_dataset(&mut self, p0: u32) -> &mut ADataSet { + self.children.iter_mut().find(|d| d.data.data_type == p0).unwrap() + } + } + + #[derive(Debug, serde::Serialize)] + pub struct ADataSet { + pub header: ChunkHeader, + pub data: DataSet, + pub child: ASomeList + } + + #[derive(Debug, serde::Serialize)] + pub enum ASomeList { + Images(Vec), // 1 + Albums, // 2 + Files, // 3 + } + + #[derive(Debug, serde::Serialize)] + pub struct AImageItem { + pub data: ImageItem, + pub name: Option, + } +} + +pub mod objects { + use serde::{Deserialize, Serialize}; + + pub enum ChunkType { + ArtworkDB, + DataSet, + ImageList, + ImageItem, + LocationTag, + ImageName, + Unknown, + } + + impl From<[u8; 4]> for ChunkType { + fn from(value: [u8; 4]) -> Self { + match value { + [0x6D, 0x68, 0x66, 0x64] => ChunkType::ArtworkDB, + [0x6D, 0x68, 0x73, 0x64] => ChunkType::DataSet, + [0x6D, 0x68, 0x6C, 0x69] => ChunkType::ImageList, + [0x6D, 0x68, 0x69, 0x69] => ChunkType::ImageItem, + [0x6D, 0x68, 0x6F, 0x64] => ChunkType::LocationTag, + [0x6D, 0x68, 0x6E, 0x69] => ChunkType::ImageName, + _ => ChunkType::Unknown, + } + } + } + + impl From for [u8; 4] { + fn from(value: ChunkType) -> Self { + match value { + ChunkType::ArtworkDB => [0x6D, 0x68, 0x66, 0x64], + ChunkType::DataSet => [0x6D, 0x68, 0x73, 0x64], + ChunkType::Unknown => [0x00, 0x00, 0x00, 0x00], + ChunkType::ImageList => [0x6D, 0x68, 0x6C, 0x69], + ChunkType::ImageItem => [0x6D, 0x68, 0x69, 0x69], + ChunkType::LocationTag => [0x6D, 0x68, 0x6F, 0x64], + ChunkType::ImageName => [0x6D, 0x68, 0x6E, 0x69], + } + } + } + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] + pub struct ChunkHeader { + pub chunk_type: [u8; 4], + pub end_of_chunk: u32, + pub children_count: u32, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + pub struct Database { + unknown1: u32, + unknown2: u32, + number_of_children: u32, + unknown3: u32, + next_id_for_mhii: u32, + unknown5: u64, + unknown6: u64, + unknown7: u32, + unknown8: u32, + unknown9: u32, + unknown10: u64 + } + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] + pub struct DataSet { + pub data_type: u32, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] + pub struct LocationTag { + tag_type: u32, + unk1: u32, + unk2: u32, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + pub struct ImageItem { + number_of_children: u32, + id: u32, + song_dbid: u64, + unknown4: u32, + rating: u32, + unknown6: u32, + original_date: u32, + digitized_date: u32, + source_image_size: u32 + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + pub struct ImageName { + number_of_children: u32, + correlation_id: u32, + ithmb_offset: u32, + image_size: u32, + vertical_padding: u16, + horizontal_padding: u16, + image_height: u16, + image_width: u16, + unknown: u32, + image_size_n: u32, + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 02d9bfc..aa83aeb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ pub mod objects; pub mod xobjects; pub mod deserializer; pub mod serializer; - +mod artworkdb; /* [lib] crate-type = ["staticlib", "cdylib", "lib"]