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
This commit is contained in:
parent
5a6ca7a9f5
commit
2db99df934
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -90,7 +90,7 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itunesdb"
|
name = "itunesdb"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "itunesdb"
|
name = "itunesdb"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["alterwain"]
|
authors = ["alterwain"]
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
|
|||||||
let ds: DataSet = bincode::deserialize(&data[i..i+u]).unwrap();
|
let ds: DataSet = bincode::deserialize(&data[i..i+u]).unwrap();
|
||||||
info!("DataSet: {:?}", ds);
|
info!("DataSet: {:?}", ds);
|
||||||
last_type = ds.data_type;
|
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
|
4 => XSomeList::AlbumList(Vec::new()), // Album List
|
||||||
1 => XSomeList::TrackList(Vec::new()), // Track List
|
1 => XSomeList::TrackList(Vec::new()), // Track List
|
||||||
_ => XSomeList::Playlists(Vec::new()) // Playlist List 3
|
_ => XSomeList::Playlists(Vec::new()) // Playlist List 3
|
||||||
@ -55,7 +55,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
|
|||||||
info!("val: {:?}", ai);
|
info!("val: {:?}", ai);
|
||||||
info!("AlbumItem: {}", u);
|
info!("AlbumItem: {}", u);
|
||||||
if let XSomeList::AlbumList(albums) = &mut xdb.find_dataset(4).child {
|
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 => {
|
ChunkType::TrackList => {
|
||||||
@ -68,7 +68,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
|
|||||||
let ti: TrackItem = bincode::deserialize(&data[i..i+u]).unwrap();
|
let ti: TrackItem = bincode::deserialize(&data[i..i+u]).unwrap();
|
||||||
info!("val: {:?}", ti);
|
info!("val: {:?}", ti);
|
||||||
if let XSomeList::TrackList(tracks) = &mut xdb.find_dataset(1).child {
|
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 => {
|
ChunkType::SongReference => {
|
||||||
@ -123,16 +123,13 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
|
|||||||
h += 4;
|
h += 4;
|
||||||
}
|
}
|
||||||
//info!("Indexes: {:?}", v);
|
//info!("Indexes: {:?}", v);
|
||||||
match &mut xdb.find_dataset(last_type).child {
|
if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child {
|
||||||
XSomeList::Playlists(playlists) => {
|
|
||||||
if playlists.last().unwrap().elems.is_empty() {
|
if playlists.last().unwrap().elems.is_empty() {
|
||||||
playlists.last_mut().unwrap().args.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v}));
|
playlists.last_mut().unwrap().args.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v}));
|
||||||
} else {
|
} else {
|
||||||
playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v}));
|
playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
53 => {
|
53 => {
|
||||||
let entry: LetterJumpEntry = bincode::deserialize(&data[i..i+28]).unwrap();
|
let entry: LetterJumpEntry = bincode::deserialize(&data[i..i+28]).unwrap();
|
||||||
@ -144,29 +141,23 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
|
|||||||
h += 12;
|
h += 12;
|
||||||
}
|
}
|
||||||
info!("Indexes: {:?}", v);
|
info!("Indexes: {:?}", v);
|
||||||
match &mut xdb.find_dataset(last_type).child {
|
if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child {
|
||||||
XSomeList::Playlists(playlists) => {
|
|
||||||
if playlists.last().unwrap().elems.is_empty() {
|
if playlists.last().unwrap().elems.is_empty() {
|
||||||
playlists.last_mut().unwrap().args.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v }));
|
playlists.last_mut().unwrap().args.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v }));
|
||||||
} else {
|
} else {
|
||||||
playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v }));
|
playlists.last_mut().unwrap().elems.last_mut().unwrap().1.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
100 | 102 | 50 | 51 => {
|
100 | 102 | 50 | 51 => {
|
||||||
info!("Entry #100,102 fetched");
|
info!("Entry #100,102 fetched");
|
||||||
match &mut xdb.find_dataset(last_type).child {
|
if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child {
|
||||||
XSomeList::Playlists(playlists) => {
|
|
||||||
if playlists.last().unwrap().elems.is_empty() {
|
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()));
|
playlists.last_mut().unwrap().args.push(XPlArgument::RawArgument(data[i-12..i+(header.children_count as usize)-12].to_vec()));
|
||||||
} else {
|
} 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()));
|
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)
|
_ => 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();
|
let playlist: Playlist = bincode::deserialize(&data[i..i+u]).unwrap();
|
||||||
info!("playlist: {:?}", playlist);
|
info!("playlist: {:?}", playlist);
|
||||||
if let XSomeList::Playlists(playlists) = &mut xdb.find_dataset(last_type).child { // 3
|
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"); }
|
_ => { u = 1; info!("Unknown stuff happened"); }
|
||||||
|
@ -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 objects;
|
||||||
pub mod xobjects;
|
pub mod xobjects;
|
||||||
|
@ -11,7 +11,7 @@ pub enum ChunkType {
|
|||||||
PlaylistList,
|
PlaylistList,
|
||||||
Playlist,
|
Playlist,
|
||||||
SongReference,
|
SongReference,
|
||||||
Unknown
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<[u8; 4]> for ChunkType {
|
impl From<[u8; 4]> for ChunkType {
|
||||||
@ -27,7 +27,7 @@ impl From<[u8; 4]> for ChunkType {
|
|||||||
[0x6D, 0x68, 0x69, 0x70] => ChunkType::SongReference,
|
[0x6D, 0x68, 0x69, 0x70] => ChunkType::SongReference,
|
||||||
[0x6D, 0x68, 0x6C, 0x70] => ChunkType::PlaylistList,
|
[0x6D, 0x68, 0x6C, 0x70] => ChunkType::PlaylistList,
|
||||||
[0x6D, 0x68, 0x79, 0x70] => ChunkType::Playlist,
|
[0x6D, 0x68, 0x79, 0x70] => ChunkType::Playlist,
|
||||||
_ => ChunkType::Unknown
|
_ => ChunkType::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ impl From<ChunkType> for [u8; 4] {
|
|||||||
ChunkType::StringTypes => [0x6D, 0x68, 0x6F, 0x64],
|
ChunkType::StringTypes => [0x6D, 0x68, 0x6F, 0x64],
|
||||||
ChunkType::PlaylistList => [0x6D, 0x68, 0x6C, 0x70],
|
ChunkType::PlaylistList => [0x6D, 0x68, 0x6C, 0x70],
|
||||||
ChunkType::Playlist => [0x6D, 0x68, 0x79, 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<ChunkType> for [u8; 4] {
|
|||||||
pub struct ChunkHeader {
|
pub struct ChunkHeader {
|
||||||
pub chunk_type: [u8; 4],
|
pub chunk_type: [u8; 4],
|
||||||
pub end_of_chunk: u32,
|
pub end_of_chunk: u32,
|
||||||
pub children_count: u32
|
pub children_count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@ -69,12 +69,12 @@ pub struct Database {
|
|||||||
hash: [u8; 20],
|
hash: [u8; 20],
|
||||||
unk: [u8; 30],
|
unk: [u8; 30],
|
||||||
unk1: [u8; 32],
|
unk1: [u8; 32],
|
||||||
unk2: [u8; 20]
|
unk2: [u8; 20],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
|
||||||
pub struct DataSet {
|
pub struct DataSet {
|
||||||
pub data_type: u32
|
pub data_type: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@ -83,7 +83,7 @@ pub struct AlbumItem {
|
|||||||
unknown: u16,
|
unknown: u16,
|
||||||
album_id_for_track: u16,
|
album_id_for_track: u16,
|
||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
unknown1: u32
|
unknown1: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
|
||||||
@ -91,24 +91,24 @@ 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,
|
pub unique_id: u32,
|
||||||
visible: u32,
|
visible: u32,
|
||||||
filetype: u32,
|
pub filetype: u32,
|
||||||
type1: u8,
|
type1: u8,
|
||||||
type2: u8,
|
type2: u8,
|
||||||
compilation_flag: u8,
|
compilation_flag: u8,
|
||||||
stars: u8,
|
pub stars: u8,
|
||||||
last_modified_time: u32,
|
pub last_modified_time: u32,
|
||||||
size: u32,
|
pub size: u32,
|
||||||
length: u32,
|
pub length: u32,
|
||||||
track_number: u32,
|
track_number: u32,
|
||||||
total_tracks: u32,
|
total_tracks: u32,
|
||||||
year: u32,
|
pub year: u32,
|
||||||
bitrate: u32,
|
pub bitrate: u32,
|
||||||
sample_rate: u32,
|
pub sample_rate: u32,
|
||||||
volume: u32,
|
volume: u32,
|
||||||
start_time: u32,
|
start_time: u32,
|
||||||
stop_time: u32,
|
stop_time: u32,
|
||||||
soundcheck: u32,
|
soundcheck: u32,
|
||||||
play_count: u32,
|
pub play_count: u32,
|
||||||
play_count2: u32,
|
play_count2: u32,
|
||||||
last_played_time: u32,
|
last_played_time: u32,
|
||||||
disc_number: u32,
|
disc_number: u32,
|
||||||
@ -119,7 +119,7 @@ pub struct TrackItem {
|
|||||||
pub dbid: u64,
|
pub dbid: u64,
|
||||||
checked: u8,
|
checked: u8,
|
||||||
application_rating: u8,
|
application_rating: u8,
|
||||||
bpm: u16,
|
pub bpm: u16,
|
||||||
artwork_count: u16,
|
artwork_count: u16,
|
||||||
unk9: u16,
|
unk9: u16,
|
||||||
artwork_size: u32,
|
artwork_size: u32,
|
||||||
@ -129,9 +129,9 @@ pub struct TrackItem {
|
|||||||
unk14: u32,
|
unk14: u32,
|
||||||
unk15: u32,
|
unk15: u32,
|
||||||
unk16: u32,
|
unk16: u32,
|
||||||
skip_count: u32,
|
pub skip_count: u32,
|
||||||
last_skipped: u32,
|
last_skipped: u32,
|
||||||
has_artwork: u8,
|
pub has_artwork: u8,
|
||||||
skip_when_shuffling: u8,
|
skip_when_shuffling: u8,
|
||||||
remember_playback_position: u8,
|
remember_playback_position: u8,
|
||||||
flag4: u8,
|
flag4: u8,
|
||||||
@ -146,7 +146,7 @@ pub struct TrackItem {
|
|||||||
unk25: u32,
|
unk25: u32,
|
||||||
postgap: u32,
|
postgap: u32,
|
||||||
unk27: u32,
|
unk27: u32,
|
||||||
media_type: u32,
|
pub media_type: u32,
|
||||||
season_number: u32,
|
season_number: u32,
|
||||||
episode_number: u32,
|
episode_number: u32,
|
||||||
unk31: [u8; 28],
|
unk31: [u8; 28],
|
||||||
@ -164,22 +164,24 @@ pub struct TrackItem {
|
|||||||
unk3: [u8; 32],
|
unk3: [u8; 32],
|
||||||
unk4: [u8; 32],
|
unk4: [u8; 32],
|
||||||
unk5: [u8; 32],
|
unk5: [u8; 32],
|
||||||
unk6: [u8; 32]
|
unk6: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
pub struct StringEntry { // mhod
|
pub struct StringEntry {
|
||||||
|
// mhod
|
||||||
pub entry_type: u32,
|
pub entry_type: u32,
|
||||||
pub unk1: u32,
|
pub unk1: u32,
|
||||||
pub unk2: u32,
|
pub unk2: u32,
|
||||||
pub position: u32,
|
pub position: u32,
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
pub unknown: u32,
|
pub unknown: u32,
|
||||||
pub unk4: u32
|
pub unk4: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct PlaylistIndexEntry { // mhod
|
pub struct PlaylistIndexEntry {
|
||||||
|
// mhod
|
||||||
entry_type: u32,
|
entry_type: u32,
|
||||||
unk1: u32,
|
unk1: u32,
|
||||||
unk2: u32,
|
unk2: u32,
|
||||||
@ -189,7 +191,7 @@ pub struct PlaylistIndexEntry { // mhod
|
|||||||
null_padding1: u64,
|
null_padding1: u64,
|
||||||
null_padding2: u64,
|
null_padding2: u64,
|
||||||
null_padding3: u64,
|
null_padding3: u64,
|
||||||
null_padding4: u64
|
null_padding4: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||||
@ -199,14 +201,14 @@ pub struct LetterJumpEntry {
|
|||||||
unk2: u32,
|
unk2: u32,
|
||||||
index_type: u32,
|
index_type: u32,
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
null_padding: u64
|
null_padding: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||||
pub struct JumpTable {
|
pub struct JumpTable {
|
||||||
letter: u32, // UTF-16 LE Uppercase with two padding null bytes
|
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.
|
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.
|
count: u32, // the count of entries starting with this letter in the corresponding MHOD52.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@ -235,5 +237,5 @@ pub struct PlaylistItem {
|
|||||||
timestamp: u32,
|
timestamp: u32,
|
||||||
podcast_grouping_reference: u32,
|
podcast_grouping_reference: u32,
|
||||||
unk: [u8; 30],
|
unk: [u8; 30],
|
||||||
unk1: [u8; 10]
|
unk1: [u8; 10],
|
||||||
}
|
}
|
@ -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<u8> {
|
fn string_to_ipod16(str: &str) -> Vec<u8> {
|
||||||
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<XArgument>) -> Vec<u8> {
|
fn x_args_to_bytes(args: &Vec<XArgument>) -> Vec<u8> {
|
||||||
args.iter()
|
args.iter()
|
||||||
.filter(|arg| arg.arg_type <= 15)
|
.filter(|arg| arg.arg_type <= 15)
|
||||||
.map(serialize_string_arg)
|
.flat_map(serialize_string_arg)
|
||||||
.flatten()
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +44,7 @@ fn serialize_string_arg(xarg: &XArgument) -> Vec<u8> {
|
|||||||
children_count: 16 + 0x18 + s.len() as u32
|
children_count: 16 + 0x18 + s.len() as u32
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
b = [h, b, s].concat();
|
b = [h, b, s].concat();
|
||||||
return b;
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_index_entry(xpl: &XPlaylistIndexEntry) -> Vec<u8> {
|
fn serialize_index_entry(xpl: &XPlaylistIndexEntry) -> Vec<u8> {
|
||||||
@ -61,7 +59,7 @@ fn serialize_index_entry(xpl: &XPlaylistIndexEntry) -> Vec<u8> {
|
|||||||
children_count: 12 + (v.len() + b.len()) as u32
|
children_count: 12 + (v.len() + b.len()) as u32
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
b = [h, b, v].concat();
|
b = [h, b, v].concat();
|
||||||
return b;
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_x_letter(xjump: &XLetterJump) -> Vec<u8> {
|
fn serialize_x_letter(xjump: &XLetterJump) -> Vec<u8> {
|
||||||
@ -76,18 +74,17 @@ fn serialize_x_letter(xjump: &XLetterJump) -> Vec<u8> {
|
|||||||
children_count: 12 + (v.len() + b.len()) as u32
|
children_count: 12 + (v.len() + b.len()) as u32
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
b = [h, b, v].concat();
|
b = [h, b, v].concat();
|
||||||
return b;
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_arguments(pl: &Vec<XPlArgument>) -> Vec<u8> {
|
fn serialize_arguments(pl: &Vec<XPlArgument>) -> Vec<u8> {
|
||||||
pl.iter()
|
pl.iter()
|
||||||
.map(|arg| match arg {
|
.flat_map(|arg| match arg {
|
||||||
XPlArgument::String(xarg) => serialize_string_arg(xarg),
|
XPlArgument::String(xarg) => serialize_string_arg(xarg),
|
||||||
XPlArgument::IndexEntry(xpl) => serialize_index_entry(xpl),
|
XPlArgument::IndexEntry(xpl) => serialize_index_entry(xpl),
|
||||||
XPlArgument::LetterJumpEntry(xjump) => serialize_x_letter(xjump),
|
XPlArgument::LetterJumpEntry(xjump) => serialize_x_letter(xjump),
|
||||||
XPlArgument::RawArgument(raw_arg) => raw_arg.to_vec()
|
XPlArgument::RawArgument(raw_arg) => raw_arg.to_vec()
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl XDatabase {
|
|||||||
fn add_track_to_playlists(&mut self, n: u32, track: &XTrackItem) {
|
fn add_track_to_playlists(&mut self, n: u32, track: &XTrackItem) {
|
||||||
if let XSomeList::Playlists(playlists) = &mut self.find_dataset(n).child {
|
if let XSomeList::Playlists(playlists) = &mut self.find_dataset(n).child {
|
||||||
let playlist = playlists.last_mut().unwrap();
|
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 elem = playlist.elems.last().unwrap();
|
||||||
let mut pl_item = elem.0.clone();
|
let mut pl_item = elem.0.clone();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user