use std::{
borrow::Cow,
io,
ops::{Deref, DerefMut},
};
use hyper::client::HttpConnector;
use hyper::{self, Client};
use hyper_tls::HttpsConnector;
use crate::{
error::Error, Api, FoundUserRank, LeaderboardPage, LeaderboardSeason, LeaderboardType,
MapStats, MyInfo, RecentPvp, RecentPvpDetails, RegistrationDetails, RegistrationSuccess,
RoomOverview, RoomStatus, RoomTerrain, ShardInfo, Token, WorldStartRoom,
};
type TokioRuntime = tokio::runtime::current_thread::Runtime;
mod error {
use std::{fmt, io};
#[derive(Debug)]
pub enum SyncError {
Io(io::Error),
Url(url::ParseError),
Tls(hyper_tls::Error),
}
impl From<io::Error> for SyncError {
fn from(e: io::Error) -> Self {
SyncError::Io(e)
}
}
impl From<url::ParseError> for SyncError {
fn from(e: url::ParseError) -> Self {
SyncError::Url(e)
}
}
impl From<hyper_tls::Error> for SyncError {
fn from(e: hyper_tls::Error) -> Self {
SyncError::Tls(e)
}
}
impl fmt::Display for SyncError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SyncError::Io(ref e) => e.fmt(f),
SyncError::Url(ref e) => e.fmt(f),
SyncError::Tls(ref e) => e.fmt(f),
}
}
}
impl ::std::error::Error for SyncError {
fn description(&self) -> &str {
match *self {
SyncError::Io(ref e) => e.description(),
SyncError::Url(ref e) => e.description(),
SyncError::Tls(ref e) => e.description(),
}
}
fn cause(&self) -> Option<&::std::error::Error> {
match *self {
SyncError::Io(ref e) => Some(e),
SyncError::Url(ref e) => Some(e),
SyncError::Tls(ref e) => Some(e),
}
}
}
}
pub use self::error::SyncError;
#[derive(Debug)]
pub struct SyncApi<C: hyper::client::connect::Connect = HttpsConnector<HttpConnector>> {
runtime: TokioRuntime,
client: Api<C, Client<C>>,
}
impl SyncApi<HttpsConnector<HttpConnector>> {
pub fn new() -> Result<Self, SyncError> {
Ok(Self::new_with_connector(HttpsConnector::new(4)?)?)
}
}
impl<C: hyper::client::connect::Connect + 'static> SyncApi<C> {
pub fn new_with_connector(connector: C) -> Result<Self, io::Error> {
let runtime = TokioRuntime::new()?;
let hyper = Client::builder().build(connector);
Ok(SyncApi {
runtime,
client: Api::new(hyper),
})
}
}
impl<C: hyper::client::connect::Connect> Deref for SyncApi<C> {
type Target = Api<C, Client<C>>;
fn deref(&self) -> &Self::Target {
&self.client
}
}
impl<C: hyper::client::connect::Connect> DerefMut for SyncApi<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.client
}
}
impl<C: hyper::client::connect::Connect + 'static> SyncApi<C> {
#[inline]
pub fn with_url<U: AsRef<str>>(mut self, url: U) -> Result<Self, url::ParseError> {
self.set_url(url)?;
Ok(self)
}
#[inline]
pub fn with_token<T: Into<Token>>(mut self, token: T) -> Self {
self.set_token(token.into());
self
}
pub fn login<'b, U, V>(&mut self, username: U, password: V) -> Result<(), Error>
where
U: Into<Cow<'b, str>>,
V: Into<Cow<'b, str>>,
{
let result = self
.runtime
.block_on(self.client.login(username, password))?;
result.return_to(&self.client.auth_token);
Ok(())
}
pub fn register(&mut self, details: RegistrationDetails) -> Result<RegistrationSuccess, Error> {
self.runtime.block_on(self.client.register(details))
}
pub fn my_info(&mut self) -> Result<MyInfo, Error> {
self.runtime.block_on(self.client.my_info()?)
}
pub fn world_start_room(&mut self) -> Result<WorldStartRoom, Error> {
self.runtime.block_on(self.client.world_start_room()?)
}
pub fn shard_start_room<'b, U>(&mut self, shard: U) -> Result<WorldStartRoom, Error>
where
U: Into<Cow<'b, str>>,
{
self.runtime.block_on(self.client.shard_start_room(shard)?)
}
pub fn map_stats<'a, U, V>(&mut self, shard: &'a str, rooms: &'a V) -> Result<MapStats, Error>
where
U: AsRef<str>,
&'a V: IntoIterator<Item = U>,
{
self.runtime.block_on(self.client.map_stats(shard, rooms)?)
}
pub fn room_overview<'b, U, V>(
&mut self,
shard: U,
room_name: V,
request_interval: u32,
) -> Result<RoomOverview, Error>
where
U: Into<Cow<'b, str>>,
V: Into<Cow<'b, str>>,
{
self.runtime.block_on(
self.client
.room_overview(shard, room_name, request_interval)?,
)
}
pub fn room_terrain<'b, U, V>(
&mut self,
shard: Option<U>,
room_name: V,
) -> Result<RoomTerrain, Error>
where
U: Into<Cow<'b, str>>,
V: Into<Cow<'b, str>>,
{
self.runtime
.block_on(self.client.room_terrain(shard, room_name))
}
pub fn shard_list(&mut self) -> Result<Vec<ShardInfo>, Error> {
self.runtime.block_on(self.client.shard_list())
}
pub fn room_status<'b, U>(&mut self, room_name: U) -> Result<RoomStatus, Error>
where
U: Into<Cow<'b, str>>,
{
self.runtime.block_on(self.client.room_status(room_name)?)
}
pub fn recent_pvp(&mut self, details: RecentPvpDetails) -> Result<RecentPvp, Error> {
self.runtime.block_on(self.client.recent_pvp(details))
}
pub fn leaderboard_season_list(&mut self) -> Result<Vec<LeaderboardSeason>, Error> {
self.runtime
.block_on(self.client.leaderboard_season_list()?)
}
pub fn find_season_leaderboard_rank<'b, U, V>(
&mut self,
leaderboard_type: LeaderboardType,
username: U,
season: V,
) -> Result<FoundUserRank, Error>
where
U: Into<Cow<'b, str>>,
V: Into<Cow<'b, str>>,
{
self.runtime
.block_on(self.client.find_season_leaderboard_rank(
leaderboard_type,
username,
season,
)?)
}
pub fn find_leaderboard_ranks<'b, U>(
&mut self,
leaderboard_type: LeaderboardType,
username: U,
) -> Result<Vec<FoundUserRank>, Error>
where
U: Into<Cow<'b, str>>,
{
self.runtime.block_on(
self.client
.find_leaderboard_ranks(leaderboard_type, username)?,
)
}
pub fn leaderboard_page<'b, U>(
&mut self,
leaderboard_type: LeaderboardType,
season: U,
limit: u32,
offset: u32,
) -> Result<LeaderboardPage, Error>
where
U: Into<Cow<'b, str>>,
{
self.runtime.block_on(self.client.leaderboard_page(
leaderboard_type,
season,
limit,
offset,
)?)
}
}