uvm_core 0.13.1

The core functionality for the unity version manager commandline client.
Documentation
use crate::error::*;
use crate::platform::Platform;
use crate::unity::version::{Version, VersionType};
use reqwest::Url;
use std::convert::Into;
use std::ops::Deref;

const BASE_URL: &str = "https://download.unity3d.com/download_unity/";
const BETA_BASE_URL: &str = "https://beta.unity3d.com/download/";

#[derive(Debug)]
pub struct DownloadURL(Url);

impl Deref for DownloadURL {
    type Target = Url;

    fn deref(&self) -> &Url {
        &self.0
    }
}

impl Into<Url> for DownloadURL {
    fn into(self) -> Url {
        self.into_url()
    }
}

impl DownloadURL {
    pub fn new<V: AsRef<Version>>(version: V) -> Result<DownloadURL> {
        let version = version.as_ref();
        let mut url = match version.release_type() {
            VersionType::Final => Url::parse(BASE_URL),
            _ => Url::parse(BETA_BASE_URL),
        }
        .map_err(|err| UvmError::with_chain(err, "failed to parse download url"))?;

        let hash = version.version_hash().map_err(|err| {
            warn!("{}", err);
            UvmError::with_chain(
                err,
                format!("No hash value for version: {} available", version),
            )
        })?;
        url = url
            .join(&format!("{}/", hash))
            .map_err(|err| UvmError::with_chain(err, "failed to parse hash url"))?;
        Ok(DownloadURL(url))
    }

    pub fn into_url(self) -> Url {
        self.0
    }
}

pub struct IniUrlBuilder {
    platform: Platform,
}

impl IniUrlBuilder {
    pub fn new() -> Self {
        Self {
            platform: Platform::default(),
        }
    }

    pub fn platform(&mut self, platform: Platform) -> &mut Self {
        self.platform = platform;
        self
    }

    pub fn build<V: AsRef<Version>>(&self, version: V) -> Result<IniUrl> {
        let version = version.as_ref();
        let download_url = DownloadURL::new(version)?;

        let url = download_url
            .join(&format!(
                "unity-{}-{}.ini",
                version.to_string(),
                self.platform
            ))
            .map_err(|err| UvmError::with_chain(err, "failed to parse ini url"))?;
        Ok(IniUrl(url))
    }
}

#[derive(Debug)]
pub struct IniUrl(Url);

impl Deref for IniUrl {
    type Target = Url;

    fn deref(&self) -> &Url {
        &self.0
    }
}

impl Into<Url> for IniUrl {
    fn into(self) -> Url {
        self.into_url()
    }
}

impl IniUrl {
    #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
    pub fn new<V: AsRef<Version>>(version: V) -> Result<IniUrl> {
        IniUrlBuilder::new().build(version)
    }

    #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
    pub fn new<V: AsRef<Version>>(version: V) -> Result<IniUrl> {
        unimplemented!()
    }

    pub fn into_url(self) -> Url {
        self.0
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ini_url_new_uses_default_platform() {
        let v = Version::f(2017, 1, 1, 1);
        let platform = Platform::default();
        let url: IniUrl = IniUrl::new(&v).unwrap();

        assert!(url
            .to_string()
            .as_str()
            .contains(&format!("unity-{}-{}.ini", &v, platform)));
    }

    #[test]
    fn ini_url_builder_uses_default_platform() {
        let v = Version::f(2017, 1, 1, 1);
        let platform = Platform::default();
        let url: IniUrl = IniUrlBuilder::new().build(&v).unwrap();

        assert!(url
            .to_string()
            .as_str()
            .contains(&format!("unity-{}-{}.ini", &v, platform)));
    }

    fn get_test_platform() -> Platform {
        match Platform::default() {
            Platform::MacOs => Platform::Win,
            Platform::Win => Platform::Linux,
            Platform::Linux => Platform::MacOs,
        }
    }

    #[test]
    fn ini_url_builder_can_set_platform() {
        let v = Version::f(2017, 1, 1, 1);
        let platform = get_test_platform();
        let url: IniUrl = IniUrlBuilder::new().platform(platform).build(&v).unwrap();

        assert!(url
            .to_string()
            .as_str()
            .contains(&format!("unity-{}-{}.ini", &v, platform)));
    }
}