1use crate::error::*;
2use crate::platform::Platform;
3use crate::unity::version::{Version, VersionType};
4use reqwest::Url;
5use std::convert::Into;
6use std::ops::Deref;
7
8const BASE_URL: &str = "https://download.unity3d.com/download_unity/";
9const BETA_BASE_URL: &str = "https://beta.unity3d.com/download/";
10
11#[derive(Debug)]
12pub struct DownloadURL(Url);
13
14impl Deref for DownloadURL {
15 type Target = Url;
16
17 fn deref(&self) -> &Url {
18 &self.0
19 }
20}
21
22impl Into<Url> for DownloadURL {
23 fn into(self) -> Url {
24 self.into_url()
25 }
26}
27
28impl DownloadURL {
29 pub fn new<V: AsRef<Version>>(version: V) -> Result<DownloadURL> {
30 let version = version.as_ref();
31 let mut url = match version.release_type() {
32 VersionType::Final => Url::parse(BASE_URL),
33 _ => Url::parse(BETA_BASE_URL),
34 }
35 .map_err(|err| UvmError::with_chain(err, "failed to parse download url"))?;
36
37 let hash = version.version_hash().map_err(|err| {
38 warn!("{}", err);
39 UvmError::with_chain(
40 err,
41 format!("No hash value for version: {} available", version),
42 )
43 })?;
44 url = url
45 .join(&format!("{}/", hash))
46 .map_err(|err| UvmError::with_chain(err, "failed to parse hash url"))?;
47 Ok(DownloadURL(url))
48 }
49
50 pub fn into_url(self) -> Url {
51 self.0
52 }
53}
54
55pub struct IniUrlBuilder {
56 platform: Platform,
57}
58
59impl IniUrlBuilder {
60 pub fn new() -> Self {
61 Self {
62 platform: Platform::default(),
63 }
64 }
65
66 pub fn platform(&mut self, platform: Platform) -> &mut Self {
67 self.platform = platform;
68 self
69 }
70
71 pub fn build<V: AsRef<Version>>(&self, version: V) -> Result<IniUrl> {
72 let version = version.as_ref();
73 let download_url = DownloadURL::new(version)?;
74
75 let url = download_url
76 .join(&format!(
77 "unity-{}-{}.ini",
78 version.to_string(),
79 self.platform
80 ))
81 .map_err(|err| UvmError::with_chain(err, "failed to parse ini url"))?;
82 Ok(IniUrl(url))
83 }
84}
85
86#[derive(Debug)]
87pub struct IniUrl(Url);
88
89impl Deref for IniUrl {
90 type Target = Url;
91
92 fn deref(&self) -> &Url {
93 &self.0
94 }
95}
96
97impl Into<Url> for IniUrl {
98 fn into(self) -> Url {
99 self.into_url()
100 }
101}
102
103impl IniUrl {
104 #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
105 pub fn new<V: AsRef<Version>>(version: V) -> Result<IniUrl> {
106 IniUrlBuilder::new().build(version)
107 }
108
109 #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
110 pub fn new<V: AsRef<Version>>(version: V) -> Result<IniUrl> {
111 unimplemented!()
112 }
113
114 pub fn into_url(self) -> Url {
115 self.0
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn ini_url_new_uses_default_platform() {
125 let v = Version::f(2017, 1, 1, 1);
126 let platform = Platform::default();
127 let url: IniUrl = IniUrl::new(&v).unwrap();
128
129 assert!(url
130 .to_string()
131 .as_str()
132 .contains(&format!("unity-{}-{}.ini", &v, platform)));
133 }
134
135 #[test]
136 fn ini_url_builder_uses_default_platform() {
137 let v = Version::f(2017, 1, 1, 1);
138 let platform = Platform::default();
139 let url: IniUrl = IniUrlBuilder::new().build(&v).unwrap();
140
141 assert!(url
142 .to_string()
143 .as_str()
144 .contains(&format!("unity-{}-{}.ini", &v, platform)));
145 }
146
147 fn get_test_platform() -> Platform {
148 match Platform::default() {
149 Platform::MacOs => Platform::Win,
150 Platform::Win => Platform::Linux,
151 Platform::Linux => Platform::MacOs,
152 }
153 }
154
155 #[test]
156 fn ini_url_builder_can_set_platform() {
157 let v = Version::f(2017, 1, 1, 1);
158 let platform = get_test_platform();
159 let url: IniUrl = IniUrlBuilder::new().platform(platform).build(&v).unwrap();
160
161 assert!(url
162 .to_string()
163 .as_str()
164 .contains(&format!("unity-{}-{}.ini", &v, platform)));
165 }
166}