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::path::Path;
|
||||
use futures::executor::block_on;
|
||||
|
||||
mod queries;
|
||||
use queries::*;
|
||||
|
@ -24,7 +26,6 @@ fn get_auth_key(config_dir: &Path) -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut config_dir = dirs::config_dir().unwrap();
|
||||
config_dir.push("ggelo");
|
||||
|
@ -34,13 +35,16 @@ fn main() {
|
|||
let mut search = String::new();
|
||||
print!("Search for game: ");
|
||||
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(
|
||||
run_query::<VideogameSearch,_>(VideogameSearchVars { name: search }, &auth_key)).data {
|
||||
for maybe_game in response.videogames.unwrap().nodes.unwrap().into_iter() {
|
||||
let game = maybe_game.unwrap();
|
||||
println!("{:?} - {}", game.id.unwrap(), game.name.unwrap());
|
||||
if let Some(response) = block_on(run_query::<VideogameSearch, _>(
|
||||
VideogameSearchVars { name: search },
|
||||
&auth_key,
|
||||
)) {
|
||||
for game in response.into_iter() {
|
||||
println!("{} - {}", game.id, game.name);
|
||||
}
|
||||
} else {
|
||||
println!("No response");
|
||||
|
|
|
@ -1,22 +1,36 @@
|
|||
use cynic::QueryBuilder;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use cynic::{GraphQlResponse, QueryBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod search_games;
|
||||
|
||||
use schema::schema;
|
||||
|
||||
/// 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
|
||||
/// new scalar type that serializes to u64.
|
||||
#[derive(cynic::Scalar, Debug)]
|
||||
pub struct ID(u64);
|
||||
// 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
|
||||
// new scalar type that serializes to u64.
|
||||
#[derive(cynic::Scalar, Debug, Copy, Clone)]
|
||||
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>
|
||||
where Builder: QueryBuilder<Vars>,
|
||||
pub trait QueryUnwrap<Vars>: 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,
|
||||
for<'de> Builder: Deserialize<'de>
|
||||
|
||||
for<'de> Builder: Deserialize<'de>,
|
||||
{
|
||||
use cynic::http::SurfExt;
|
||||
|
||||
|
@ -27,5 +41,5 @@ pub async fn run_query<Builder: 'static, Vars>(vars: Vars, auth: &str) -> cynic:
|
|||
.run_graphql(query)
|
||||
.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 super::ID;
|
||||
|
||||
// VARIABLES
|
||||
// Query
|
||||
|
||||
#[derive(cynic::QueryVariables)]
|
||||
pub struct VideogameSearchVars {
|
||||
pub name: String
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
// QUERY
|
||||
// Query
|
||||
|
||||
#[derive(cynic::QueryFragment, Debug)]
|
||||
#[cynic(graphql_type = "Query", variables = "VideogameSearchVars")]
|
||||
|
@ -28,3 +28,34 @@ pub struct Videogame {
|
|||
pub id: Option<ID>,
|
||||
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