1use std::{fmt::Display, str::FromStr};
2
3use num_traits::FromPrimitive;
4use serde::{de::Visitor, Deserialize, Serialize};
5use tpex::PlayerId;
6use base64::prelude::*;
7
8#[repr(u8)]
9#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
10#[derive(num_derive::FromPrimitive)]
11pub enum TokenLevel {
12 ReadOnly = 0,
14 ProxyOne = 1,
16 ProxyAll = 2,
18}
19impl Serialize for TokenLevel {
20 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21 where S: serde::Serializer {
22 serializer.serialize_u64(*self as u64)
23 }
24}
25impl<'de> Deserialize<'de> for TokenLevel {
26 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27 where D: serde::Deserializer<'de> {
28 struct Inner;
29 impl Visitor<'_> for Inner {
30 type Value = TokenLevel;
31
32 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
33 write!(formatter, "an integer TokenLevel")
34 }
35
36 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
37 where E: serde::de::Error, {
38 TokenLevel::from_u64(v).ok_or(E::invalid_value(serde::de::Unexpected::Unsigned(v), &Self))
39 }
40 }
41 deserializer.deserialize_u64(Inner)
42 }
43}
44
45#[derive(PartialEq, Eq, Debug, Clone, Copy)]
46pub struct Token(pub [u8;16]);
47impl Token {
48 #[cfg(feature = "server")]
49 pub fn generate() -> Token {
50 let mut ret = Token(Default::default());
51 getrandom::fill(&mut ret.0).expect("Could not generate token");
52 ret
53 }
54}
55
56impl FromStr for Token {
57 type Err = base64::DecodeSliceError;
58
59 fn from_str(s: &str) -> Result<Self, Self::Err> {
60 let mut ret = Token(Default::default());
61 let len = BASE64_STANDARD_NO_PAD.decode_slice(s, &mut ret.0)?;
62 if len != ret.0.len() {
63 Err(base64::DecodeSliceError::OutputSliceTooSmall)
65 }
66 else {
67 Ok(ret)
68 }
69 }
70}
71impl Display for Token {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 write!(f, "{}", BASE64_STANDARD_NO_PAD.encode(self.0))
74 }
75}
76impl Serialize for Token {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: serde::Serializer {
80 serializer.serialize_str(&self.to_string())
81 }
82}
83impl<'de> Deserialize<'de> for Token {
84 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85 where D: serde::Deserializer<'de> {
86 struct Inner;
87 impl Visitor<'_> for Inner {
88 type Value = Token;
89
90 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
91 write!(formatter, "a base64-encoded token")
92 }
93
94 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
95 where
96 E: serde::de::Error, {
97 v.parse().map_err(E::custom)
98 }
99 }
100 deserializer.deserialize_str(Inner)
101 }
102}
103
104#[derive(PartialEq, Eq, Debug, Clone)]
105#[derive(serde::Serialize, serde::Deserialize)]
106pub struct TokenInfo {
107 pub token: Token,
108 pub user: PlayerId,
109 pub level: TokenLevel
110}
111
112#[derive(Debug, Clone)]
113#[derive(serde::Serialize, serde::Deserialize)]
114pub struct TokenPostArgs {
115 pub level: TokenLevel,
116 pub user: PlayerId
117}
118
119#[derive(Default, Debug, Clone)]
120#[derive(serde::Serialize, serde::Deserialize)]
121pub struct TokenDeleteArgs {
122 pub token: Option<Token>
123}
124
125#[derive(Default, Debug, Clone)]
126#[derive(serde::Serialize, serde::Deserialize)]
127pub struct StateGetArgs {
128 pub from: Option<u64>
129}
130
131#[derive(Default, Debug, Clone)]
132#[derive(serde::Serialize, serde::Deserialize)]
133pub struct StatePatchArgs {
134 pub id: Option<u64>
135}
136#[derive(Default, Debug, Clone)]
137#[derive(serde::Serialize, serde::Deserialize)]
138pub struct ErrorInfo {
139 pub error: String
140}
141#[derive(Default, Debug, Clone)]
142#[derive(serde::Serialize, serde::Deserialize)]
143pub struct InspectBalanceGetArgs {
144 pub player: PlayerId
145}
146#[derive(Default, Debug, Clone)]
147#[derive(serde::Serialize, serde::Deserialize)]
148pub struct InspectAssetsGetArgs {
149 pub player: PlayerId
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
153pub enum PriceChangeCause {
154 Buy,
155 Sell,
156 Cancel
157}
158
159#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
160pub struct PriceSummary {
161 pub time: chrono::DateTime<chrono::Utc>,
162 pub best_buy: Option<tpex::Coins>,
163 pub n_buy: u64,
164 pub best_sell: Option<tpex::Coins>,
165 pub n_sell: u64
166}
167impl PriceSummary {
168 #[allow(unused)]
169 pub const fn mid_market(&self) -> Option<tpex::Coins> {
170 match (self.best_buy, self.best_sell) {
171 (Some(best_buy), Some(best_sell)) => Some(tpex::Coins::from_millicoins(best_buy.millicoins().saturating_add(best_sell.millicoins()) / 2)),
172 (None, Some(x)) |
173 (Some(x), None) => Some(x),
174 (None, None) => None
175 }
176 }
177 #[allow(unused)]
178 pub fn cause(&self, prev: &PriceSummary) -> PriceChangeCause {
179 match (self.n_buy > prev.n_buy, self.n_sell > prev.n_sell) {
180 (true, true) => panic!("Passed invalid previous value to tpex_api::PriceSummary::cause"),
182 (false, false) => PriceChangeCause::Cancel,
184 (true , false) => PriceChangeCause::Buy,
185 (false, true ) => PriceChangeCause::Sell
186 }
187 }
188 #[allow(unused)]
189 pub fn same_prices_as(&self, other: &PriceSummary) -> bool {
191 self.best_buy == other.best_buy && self.n_buy == other.n_buy && self.best_sell == other.best_sell && self.n_sell == other.n_sell
192 }
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct PriceHistoryArgs {
197 pub asset: tpex::AssetId,
198}