Skip to content

Commit

Permalink
Drop trait aliases feature and switch to Rust stable.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arnavion committed Aug 16, 2020
1 parent 0c73d77 commit a905063
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 61 deletions.
13 changes: 11 additions & 2 deletions ci/run.sh
Expand Up @@ -2,10 +2,19 @@

set -euo pipefail


# CI VMs have rustup and stable pre-installed, but they're not necessarily the latest.
# So expect them to exist but update them.

rustup self update

rustup toolchain install --component clippy --profile minimal nightly
rustup default nightly
rustup set profile minimal

rustup update --no-self-update stable
rustup default stable

rustup component add clippy


case "$OP" in
'build')
Expand Down
25 changes: 5 additions & 20 deletions factorio-mods-web/src/api.rs
Expand Up @@ -26,7 +26,7 @@ impl API {
}

/// Searches for mods matching the given criteria.
pub fn search<'a>(&'a self, query: &str) -> SearchResponse<'a> {
pub fn search<'a>(&'a self, query: &str) -> impl futures_core::Stream<Item = Result<crate::SearchResponseMod, crate::Error>> + 'a {
let query = query.to_lowercase();

let mut next_page_url = self.mods_url.clone();
Expand Down Expand Up @@ -67,7 +67,7 @@ impl API {
}

/// Gets information about the specified mod.
pub fn get(&self, mod_name: &factorio_mods_common::ModName) -> GetResponse {
pub fn get(&self, mod_name: &factorio_mods_common::ModName) -> impl std::future::Future<Output = Result<crate::Mod, crate::Error>> {
let mut mod_url = self.mods_url.clone();
mod_url.path_segments_mut().unwrap().push(&mod_name.0);
let future = self.client.get_object(mod_url);
Expand All @@ -83,7 +83,7 @@ impl API {
&self,
username: factorio_mods_common::ServiceUsername,
password: &str,
) -> LoginResponse {
) -> impl std::future::Future<Output = Result<factorio_mods_common::UserCredentials, crate::Error>> {
let future = self.client.post_object(self.login_url.clone(), &[("username", &*username.0), ("password", password)]);

async {
Expand All @@ -97,7 +97,7 @@ impl API {
&self,
release: &crate::ModRelease,
user_credentials: &factorio_mods_common::UserCredentials,
) -> GetFilesizeResponse {
) -> impl std::future::Future<Output = Result<u64, crate::Error>> {
let download_url = match self.base_url.join(&release.download_url.0) {
Ok(mut download_url) => {
download_url.query_pairs_mut()
Expand Down Expand Up @@ -138,7 +138,7 @@ impl API {
release: &crate::ModRelease,
user_credentials: &factorio_mods_common::UserCredentials,
range: Option<&str>,
) -> DownloadResponse {
) -> impl futures_core::Stream<Item = Result<bytes::Bytes, crate::Error>> {
let download_url = match self.base_url.join(&release.download_url.0) {
Ok(mut download_url) => {
download_url.query_pairs_mut()
Expand Down Expand Up @@ -180,21 +180,6 @@ impl API {
}
}

/// A [`futures_core::Stream`] of a downloaded mod's bytes.
pub type DownloadResponse = impl futures_core::Stream<Item = Result<bytes::Bytes, crate::Error>> + 'static;

/// A [`std::future::Future`] of a mod's information.
pub type GetResponse = impl std::future::Future<Output = Result<crate::Mod, crate::Error>> + 'static;

/// A [`std::future::Future`] of a mod release's file size.
pub type GetFilesizeResponse = impl std::future::Future<Output = Result<u64, crate::Error>> + 'static;

/// A [`std::future::Future`] of an attempt to login to the web API.
pub type LoginResponse = impl std::future::Future<Output = Result<factorio_mods_common::UserCredentials, crate::Error>> + 'static;

/// A [`futures_core::Stream`] of search results.
pub type SearchResponse<'a> = impl futures_core::Stream<Item = Result<crate::SearchResponseMod, crate::Error>> + Unpin + 'a;

/// A single page of a paged response.
#[derive(Debug, serde_derive::Deserialize)]
struct PagedResponse<T> {
Expand Down
35 changes: 13 additions & 22 deletions factorio-mods-web/src/client.rs
Expand Up @@ -32,7 +32,10 @@ impl Client {
}

/// GETs the given URL using the given client, and deserializes the response as a JSON object.
pub(crate) fn get_object<T>(&self, url: reqwest::Url) -> GetObjectFuture<T> where T: serde::de::DeserializeOwned + 'static {
pub(crate) fn get_object<T>(&self, url: reqwest::Url) -> impl std::future::Future<Output = Result<(T, reqwest::Url), crate::Error>>
where
T: serde::de::DeserializeOwned + 'static,
{
let builder =
self.inner.get(url.clone())
.header(reqwest::header::ACCEPT, APPLICATION_JSON.clone());
Expand All @@ -44,12 +47,10 @@ impl Client {
}

/// GETs the given URL using the given client, and returns an application/zip response.
pub(crate) fn get_zip(&self, url: reqwest::Url, range: Option<&str>) -> GetZipFuture {
pub(crate) fn get_zip(&self, url: reqwest::Url, range: Option<&str>) -> impl std::future::Future<Output = Result<(reqwest::Response, reqwest::Url), crate::Error>> {
let (builder, is_range_request) = {
let builder = self.inner.get(url.clone());

// TODO: Suppress bad clippy lint. Ref: https://github.com/rust-lang/rust-clippy/issues/5822
#[allow(clippy::option_if_let_else)]
let (builder, is_range_request) =
if let Some(range) = range {
(builder.header(reqwest::header::RANGE, range), true)
Expand All @@ -69,7 +70,7 @@ impl Client {
}

/// HEADs the given URL using the given client, and returns an application/zip response.
pub(crate) fn head_zip(&self, url: reqwest::Url) -> HeadZipFuture {
pub(crate) fn head_zip(&self, url: reqwest::Url) -> impl std::future::Future<Output = Result<(reqwest::Response, reqwest::Url), crate::Error>> {
let builder =
self.inner.head(url.clone())
.header(reqwest::header::ACCEPT, APPLICATION_ZIP.clone());
Expand All @@ -81,16 +82,15 @@ impl Client {
}
}

// TODO: Would like to return `impl std::future::Future<Output = Result<(T, reqwest::Url), crate::Error>>`,
// but https://github.com/rust-lang/rust/issues/42940 prevents it.
/// POSTs the given URL using the given client and request body, and deserializes the response as a JSON object.
pub(crate) fn post_object<B, T>(&self, url: reqwest::Url, body: &B) -> PostObjectFuture<T>
pub(crate) fn post_object<B, T>(&self, url: reqwest::Url, body: &B) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(T, reqwest::Url), crate::Error>>>>
where B: serde::Serialize, T: serde::de::DeserializeOwned + 'static
{
// Separate inner fn so that the impl-trait type alias is independent of B
async fn post_object_inner<T>(
builder: reqwest::RequestBuilder,
body: Result<String, serde_urlencoded::ser::Error>,
url: reqwest::Url,
) -> Result<(T, reqwest::Url), crate::Error> where T: serde::de::DeserializeOwned + 'static {
let builder = self.inner.post(url.clone());
let body = serde_urlencoded::to_string(body);
Box::pin(async move {
let body = match body {
Ok(body) => body,
Err(err) => return Err(crate::ErrorKind::Serialize(url, err).into()),
Expand All @@ -104,11 +104,7 @@ impl Client {

let (response, url) = send(builder, url, false).await?;
Ok(json(response, url).await?)
}

let builder = self.inner.post(url.clone());
let body = serde_urlencoded::to_string(body);
post_object_inner(builder, body, url)
})
}
}

Expand All @@ -129,11 +125,6 @@ static APPLICATION_ZIP: once_cell::sync::Lazy<reqwest::header::HeaderValue> =
static WWW_FORM_URL_ENCODED: once_cell::sync::Lazy<reqwest::header::HeaderValue> =
once_cell::sync::Lazy::new(|| reqwest::header::HeaderValue::from_static("application/x-www-form-urlencoded"));

pub(crate) type GetObjectFuture<T> = impl std::future::Future<Output = Result<(T, reqwest::Url), crate::Error>> + 'static;
pub(crate) type GetZipFuture = impl std::future::Future<Output = Result<(reqwest::Response, reqwest::Url), crate::Error>> + 'static;
pub(crate) type HeadZipFuture = impl std::future::Future<Output = Result<(reqwest::Response, reqwest::Url), crate::Error>> + 'static;
pub(crate) type PostObjectFuture<T> = impl std::future::Future<Output = Result<(T, reqwest::Url), crate::Error>> + 'static;

/// A login failure response.
#[derive(Debug, serde_derive::Deserialize)]
struct LoginFailureResponse {
Expand Down
7 changes: 2 additions & 5 deletions factorio-mods-web/src/lib.rs
@@ -1,24 +1,21 @@
//! API to interface with <https://mods.factorio.com/>

#![feature(
type_alias_impl_trait,
)]

#![deny(missing_docs, rust_2018_idioms, warnings)]

#![deny(clippy::all, clippy::pedantic)]
#![allow(
clippy::default_trait_access,
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::type_complexity,
)]

#![recursion_limit = "256"]

pub use reqwest;

mod api;
pub use self::api::{ API, DownloadResponse, GetResponse, LoginResponse, SearchResponse };
pub use self::api::API;

mod client;

Expand Down
18 changes: 7 additions & 11 deletions package/src/lib.rs
Expand Up @@ -299,17 +299,13 @@ pub fn compute_solution<I>(
})
.collect();

// TODO: Suppress bad clippy lint. Ref: https://github.com/rust-lang/rust-clippy/issues/5822
#[allow(clippy::option_if_let_else)]
{
common_conflicts =
if let Some(existing) = common_conflicts {
Some(&existing & &conflicts)
}
else {
Some(conflicts)
};
}
common_conflicts =
if let Some(existing) = common_conflicts {
Some(&existing & &conflicts)
}
else {
Some(conflicts)
};
}

if let Some(common_conflicts) = common_conflicts {
Expand Down
5 changes: 4 additions & 1 deletion src/solve/mod.rs
Expand Up @@ -459,7 +459,10 @@ fn get(
}

enum CacheFuture<'a> {
GetMod(Option<(std::rc::Rc<factorio_mods_common::ModName>, std::pin::Pin<Box<factorio_mods_web::GetResponse>>)>),
GetMod(Option<(
std::rc::Rc<factorio_mods_common::ModName>,
std::pin::Pin<Box<dyn std::future::Future<Output = Result<factorio_mods_web::Mod, factorio_mods_web::Error>>>>,
)>),
GetInfoJson(Option<(
std::rc::Rc<factorio_mods_common::ModName>,
std::rc::Rc<factorio_mods_web::ModRelease>,
Expand Down

0 comments on commit a905063

Please sign in to comment.