added awards selections
This commit is contained in:
parent
e4b543e9d9
commit
eade8d6967
|
@ -1,7 +1,8 @@
|
||||||
[package]
|
[package]
|
||||||
name = "torn-api"
|
name = "torn-api"
|
||||||
version = "0.6.4"
|
version = "0.6.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
rust-version = "1.75.0"
|
||||||
authors = ["Pyrit [2111649]"]
|
authors = ["Pyrit [2111649]"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/TotallyNot/torn-api.rs.git"
|
repository = "https://github.com/TotallyNot/torn-api.rs.git"
|
||||||
|
@ -29,7 +30,7 @@ __common = []
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1", features = [ "derive" ] }
|
serde = { version = "1", features = [ "derive" ] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
chrono = { version = "0.4", features = [ "serde" ], default-features = false }
|
chrono = { version = "0.4.31", features = [ "serde" ], default-features = false }
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
|
|
@ -11,9 +11,7 @@ where
|
||||||
C: ApiClient,
|
C: ApiClient,
|
||||||
E: RequestExecutor<C>,
|
E: RequestExecutor<C>,
|
||||||
{
|
{
|
||||||
#[allow(dead_code)]
|
|
||||||
client: &'a C,
|
client: &'a C,
|
||||||
#[allow(dead_code)]
|
|
||||||
executor: E,
|
executor: E,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@ use serde::{
|
||||||
de::{self, MapAccess, Visitor},
|
de::{self, MapAccess, Visitor},
|
||||||
Deserialize, Deserializer,
|
Deserialize, Deserializer,
|
||||||
};
|
};
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::{
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
|
iter::zip,
|
||||||
|
};
|
||||||
|
|
||||||
use torn_api_macros::{ApiCategory, IntoOwned};
|
use torn_api_macros::{ApiCategory, IntoOwned};
|
||||||
|
|
||||||
|
@ -30,6 +33,10 @@ pub enum UserSelection {
|
||||||
Attacks,
|
Attacks,
|
||||||
#[api(type = "HashMap<Icon, &str>", field = "icons")]
|
#[api(type = "HashMap<Icon, &str>", field = "icons")]
|
||||||
Icons,
|
Icons,
|
||||||
|
#[api(type = "Awards<Medals>", flatten)]
|
||||||
|
Medals,
|
||||||
|
#[api(type = "Awards<Honors>", flatten)]
|
||||||
|
Honors,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Selection = UserSelection;
|
pub type Selection = UserSelection;
|
||||||
|
@ -586,6 +593,137 @@ pub struct EmploymentStatus {
|
||||||
pub company: Company,
|
pub company: Company,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Award {
|
||||||
|
pub award_time: chrono::DateTime<chrono::Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AwardMarker {
|
||||||
|
fn award_key() -> &'static str;
|
||||||
|
fn time_key() -> &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Awards<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
pub inner: BTreeMap<i32, Award>,
|
||||||
|
marker: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for Awards<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
type Target = BTreeMap<i32, Award>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::DerefMut for Awards<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Awards<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
pub fn into_inner(self) -> BTreeMap<i32, Award> {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Medals;
|
||||||
|
|
||||||
|
impl AwardMarker for Medals {
|
||||||
|
#[inline(always)]
|
||||||
|
fn award_key() -> &'static str {
|
||||||
|
"medals_awarded"
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn time_key() -> &'static str {
|
||||||
|
"medals_time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Honors;
|
||||||
|
|
||||||
|
impl AwardMarker for Honors {
|
||||||
|
#[inline(always)]
|
||||||
|
fn award_key() -> &'static str {
|
||||||
|
"honors_awarded"
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn time_key() -> &'static str {
|
||||||
|
"honors_time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, T> Deserialize<'de> for Awards<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct AwardVisitor<T>(std::marker::PhantomData<T>)
|
||||||
|
where
|
||||||
|
T: AwardMarker;
|
||||||
|
|
||||||
|
impl<'de, T> Visitor<'de> for AwardVisitor<T>
|
||||||
|
where
|
||||||
|
T: AwardMarker,
|
||||||
|
{
|
||||||
|
type Value = Awards<T>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("struct awards")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut awards: Option<Vec<i32>> = None;
|
||||||
|
let mut times: Option<Vec<_>> = None;
|
||||||
|
|
||||||
|
while let Some(key) = map.next_key::<&'de str>()? {
|
||||||
|
if key == T::award_key() {
|
||||||
|
awards = map.next_value()?;
|
||||||
|
} else if key == T::time_key() {
|
||||||
|
times = map.next_value()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let awards = awards.ok_or_else(|| de::Error::missing_field(T::award_key()))?;
|
||||||
|
let times = times.ok_or_else(|| de::Error::missing_field(T::time_key()))?;
|
||||||
|
|
||||||
|
Ok(Awards {
|
||||||
|
inner: zip(
|
||||||
|
awards,
|
||||||
|
times.into_iter().map(|t| Award {
|
||||||
|
award_time: chrono::DateTime::from_timestamp(t, 0).unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.collect(),
|
||||||
|
marker: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_map(AwardVisitor(Default::default()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -605,6 +743,8 @@ mod tests {
|
||||||
Selection::PersonalStats,
|
Selection::PersonalStats,
|
||||||
Selection::Crimes,
|
Selection::Crimes,
|
||||||
Selection::Attacks,
|
Selection::Attacks,
|
||||||
|
Selection::Medals,
|
||||||
|
Selection::Honors,
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -617,6 +757,8 @@ mod tests {
|
||||||
response.crimes().unwrap();
|
response.crimes().unwrap();
|
||||||
response.attacks().unwrap();
|
response.attacks().unwrap();
|
||||||
response.attacks_full().unwrap();
|
response.attacks_full().unwrap();
|
||||||
|
response.medals().unwrap();
|
||||||
|
response.honors().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_test]
|
#[async_test]
|
||||||
|
|
Loading…
Reference in a new issue