use serde::Deserialize;
use base64::prelude::*;
const DEVELOPER_DISK_IMAGE_REPO_TREE_URL: &str = "https://api.github.com/repos/doronz88/DeveloperDiskImage/git/trees/main?recursive=true";
pub struct DeveloperDiskImage {
pub image: Vec<u8>,
pub signature: Vec<u8>,
}
pub struct PersonalizedImage {
pub image: Vec<u8>,
pub build_manifest: Vec<u8>,
pub trustcache: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct DeveloperDiskImageRepository {
pub path_urls: std::collections::HashMap<String, String>,
}
#[derive(Debug, Deserialize)]
struct DevelopDiskRepoItem {
pub url: String,
pub path: String,
}
#[derive(Debug, Deserialize)]
struct DevelopDiskImageRepoTreeParse {
pub tree: Vec<DevelopDiskRepoItem>
}
#[derive(Debug, Deserialize)]
pub struct GitHubBlob {
pub content: String,
}
impl DeveloperDiskImageRepository {
pub fn new() -> Result<DeveloperDiskImageRepository, reqwest::Error> {
Ok(DeveloperDiskImageRepository::new_tree(match DeveloperDiskImageRepository::query() {
Ok(r) => r,
Err(r) => return Err(r)
}))
}
fn new_tree(tree: DevelopDiskImageRepoTreeParse) -> DeveloperDiskImageRepository {
let mut path_urls = std::collections::HashMap::new();
for item in tree.tree {
path_urls.insert(item.path, item.url);
}
DeveloperDiskImageRepository {
path_urls
}
}
fn query() -> Result<DevelopDiskImageRepoTreeParse, reqwest::Error> {
let res: DevelopDiskImageRepoTreeParse = match match reqwest::blocking::get(DEVELOPER_DISK_IMAGE_REPO_TREE_URL){
Ok(r) => r,
Err(e) => return Err(e)
}.json() {
Ok(r) => r,
Err(e) => return Err(e)
};
Ok(res)
}
pub fn downloaddmg(url: String) -> Result<GitHubBlob, reqwest::Error> {
let res: GitHubBlob = match match reqwest::blocking::get(url) {
Ok(r) => r,
Err(e) => return Err(e)
}.json() {
Ok(r) => r,
Err(e) => return Err(e)
};
Ok(res)
}
pub fn get_developer_disk_image(self: &DeveloperDiskImageRepository, version: String) -> Option<DeveloperDiskImage> {
let image = self.get_blob(format!("DeveloperDiskImages/{version}/DeveloperDiskImage.dmg"));
let signature = self.get_blob(format!("DeveloperDiskImages/{version}/DeveloperDiskImage.dmg.signature"));
if image.is_none() {
return None;
}
Some(DeveloperDiskImage {
image: image.unwrap(),
signature: signature.unwrap()
})
}
pub fn get_personalized_disk_image(self: &DeveloperDiskImageRepository) -> PersonalizedImage {
let image = self.get_blob("PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg".to_owned());
let build_manifest = self.get_blob("PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist".to_owned());
let trustcache = self.get_blob("PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache".to_owned());
PersonalizedImage {
image: image.unwrap(),
build_manifest: build_manifest.unwrap(),
trustcache: trustcache.unwrap()
}
}
pub fn get_blob(self: &DeveloperDiskImageRepository, path: String) -> Option<Vec<u8>> {
let url = self.path_urls.get(&path);
if url.is_none() {
return None;
}
Some(BASE64_STANDARD.decode(DeveloperDiskImageRepository::downloaddmg(url.unwrap().to_string()).unwrap().content).unwrap())
}
}