Create automatic query response unwrapping trait
This commit is contained in:
parent
349d63946c
commit
d5c3a7685f
|
@ -1,6 +1,8 @@
|
||||||
|
#![feature(iterator_try_collect)]
|
||||||
|
|
||||||
|
use futures::executor::block_on;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use futures::executor::block_on;
|
|
||||||
|
|
||||||
mod queries;
|
mod queries;
|
||||||
use queries::*;
|
use queries::*;
|
||||||
|
@ -24,7 +26,6 @@ fn get_auth_key(config_dir: &Path) -> Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut config_dir = dirs::config_dir().unwrap();
|
let mut config_dir = dirs::config_dir().unwrap();
|
||||||
config_dir.push("ggelo");
|
config_dir.push("ggelo");
|
||||||
|
@ -34,13 +35,16 @@ fn main() {
|
||||||
let mut search = String::new();
|
let mut search = String::new();
|
||||||
print!("Search for game: ");
|
print!("Search for game: ");
|
||||||
let _ = io::stdout().flush();
|
let _ = io::stdout().flush();
|
||||||
io::stdin().read_line(&mut search).expect("Error reading from stdin");
|
io::stdin()
|
||||||
|
.read_line(&mut search)
|
||||||
|
.expect("Error reading from stdin");
|
||||||
|
|
||||||
if let Some(response) = block_on(
|
if let Some(response) = block_on(run_query::<VideogameSearch, _>(
|
||||||
run_query::<VideogameSearch,_>(VideogameSearchVars { name: search }, &auth_key)).data {
|
VideogameSearchVars { name: search },
|
||||||
for maybe_game in response.videogames.unwrap().nodes.unwrap().into_iter() {
|
&auth_key,
|
||||||
let game = maybe_game.unwrap();
|
)) {
|
||||||
println!("{:?} - {}", game.id.unwrap(), game.name.unwrap());
|
for game in response.into_iter() {
|
||||||
|
println!("{} - {}", game.id, game.name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("No response");
|
println!("No response");
|
||||||
|
|
|
@ -1,22 +1,36 @@
|
||||||
use cynic::QueryBuilder;
|
use std::fmt::{Display, Formatter};
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
use cynic::{GraphQlResponse, QueryBuilder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod search_games;
|
pub mod search_games;
|
||||||
|
|
||||||
use schema::schema;
|
use schema::schema;
|
||||||
|
|
||||||
/// HACK: Unfortunately, start.gg seems to use integers for its ID type, whereas
|
// HACK: Unfortunately, start.gg seems to use integers for its ID type, whereas
|
||||||
/// cynic always assumes that IDs are strings. To get around that, we define a
|
// cynic always assumes that IDs are strings. To get around that, we define a
|
||||||
/// new scalar type that serializes to u64.
|
// new scalar type that serializes to u64.
|
||||||
#[derive(cynic::Scalar, Debug)]
|
#[derive(cynic::Scalar, Debug, Copy, Clone)]
|
||||||
pub struct ID(u64);
|
pub struct ID(pub u64);
|
||||||
|
|
||||||
|
impl Display for ID {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
<u64 as Display>::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn run_query<Builder: 'static, Vars>(vars: Vars, auth: &str) -> cynic::GraphQlResponse<Builder>
|
pub trait QueryUnwrap<Vars>: QueryBuilder<Vars> {
|
||||||
where Builder: QueryBuilder<Vars>,
|
type Unwrapped;
|
||||||
|
|
||||||
|
fn unwrap_response(response: GraphQlResponse<Self>) -> Option<Self::Unwrapped>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic function for running start.gg queries
|
||||||
|
pub async fn run_query<Builder: 'static, Vars>(vars: Vars, auth: &str) -> Option<Builder::Unwrapped>
|
||||||
|
where
|
||||||
|
Builder: QueryUnwrap<Vars>,
|
||||||
Vars: Serialize,
|
Vars: Serialize,
|
||||||
for<'de> Builder: Deserialize<'de>
|
for<'de> Builder: Deserialize<'de>,
|
||||||
|
|
||||||
{
|
{
|
||||||
use cynic::http::SurfExt;
|
use cynic::http::SurfExt;
|
||||||
|
|
||||||
|
@ -27,5 +41,5 @@ pub async fn run_query<Builder: 'static, Vars>(vars: Vars, auth: &str) -> cynic:
|
||||||
.run_graphql(query)
|
.run_graphql(query)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
response.unwrap()
|
<Builder as QueryUnwrap<Vars>>::unwrap_response(response.unwrap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
|
use super::{QueryUnwrap, ID};
|
||||||
|
use cynic::GraphQlResponse;
|
||||||
use schema::schema;
|
use schema::schema;
|
||||||
use super::ID;
|
|
||||||
|
|
||||||
// VARIABLES
|
// Query
|
||||||
|
|
||||||
#[derive(cynic::QueryVariables)]
|
#[derive(cynic::QueryVariables)]
|
||||||
pub struct VideogameSearchVars {
|
pub struct VideogameSearchVars {
|
||||||
pub name: String
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// QUERY
|
// Query
|
||||||
|
|
||||||
#[derive(cynic::QueryFragment, Debug)]
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
#[cynic(graphql_type = "Query", variables = "VideogameSearchVars")]
|
#[cynic(graphql_type = "Query", variables = "VideogameSearchVars")]
|
||||||
|
@ -28,3 +28,34 @@ pub struct Videogame {
|
||||||
pub id: Option<ID>,
|
pub id: Option<ID>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unwrapping
|
||||||
|
|
||||||
|
pub struct VideogameResponse {
|
||||||
|
pub id: ID,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryUnwrap<VideogameSearchVars> for VideogameSearch {
|
||||||
|
type Unwrapped = Vec<VideogameResponse>;
|
||||||
|
|
||||||
|
fn unwrap_response(
|
||||||
|
response: GraphQlResponse<VideogameSearch>,
|
||||||
|
) -> Option<Vec<VideogameResponse>> {
|
||||||
|
Some(
|
||||||
|
response
|
||||||
|
.data?
|
||||||
|
.videogames?
|
||||||
|
.nodes?
|
||||||
|
.into_iter()
|
||||||
|
.map(|game| {
|
||||||
|
let game_ = game?;
|
||||||
|
Some(VideogameResponse {
|
||||||
|
id: game_.id?,
|
||||||
|
name: game_.name?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.try_collect()?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue