Skip to main content

fume_core/
lib.rs

1/// This crate describes steam web apis including its interface,
2/// method, version, parameters and response type and etc
3/// we separate the definition from http client impl to attempts
4/// multiple http client backend support and async/blocking support
5use serde::{Deserialize, Serialize, de::DeserializeOwned};
6use serde_repr::{Deserialize_repr, Serialize_repr};
7
8pub mod app;
9pub mod player;
10pub mod user;
11pub mod util;
12
13/// this trait describes a specific steam web api
14/// a steam web api endpoint usually defines as follow
15/// {HTTP_METHOD} https://{host}/{interface}/{method}/{version}?{queries}
16/// the `key` parameter is not treated as part of endpoint itself,
17/// but rather an authencation parameter hence not include here
18pub trait Api {
19    // TODO: HTTP method get/post
20    /// steam web api interface such as "ISteamWebAPIUtil"
21    fn interface() -> &'static str;
22    /// steam web api method such as "GetSteamLevel"
23    fn method() -> &'static str;
24    /// steam web api version
25    fn version() -> &'static str;
26
27    type Response: DeserializeOwned;
28    // TODO: maybe return &str && &[]?
29    fn parameters(&self) -> impl Iterator<Item = (&str, String)>;
30}
31
32pub trait Param {
33    /// url query name
34    fn name() -> &'static str;
35    /// url query value
36    fn value(&self) -> String;
37    /// url query pair
38    fn param(&self) -> (&'static str, String) {
39        (Self::name(), self.value())
40    }
41}
42
43/// A generic response type
44#[derive(Clone, Debug, Deserialize, Serialize)]
45#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
46pub struct Response<T> {
47    pub response: T,
48}
49
50/// A generic response status type
51#[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
52#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
53#[repr(u8)]
54pub enum ResponseResult {
55    Success = 1,
56    Failure = 42,
57}
58
59// some integer types steam wep api returns may be quoted
60#[macro_export]
61macro_rules! quoted_number {
62    ($name:ident) => {
63        #[derive(Copy, Clone, Debug, serde::Serialize)]
64        #[serde(transparent)]
65        pub struct $name(pub u64);
66
67        impl<'de> serde::Deserialize<'de> for $name {
68            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69            where
70                D: serde::Deserializer<'de>,
71            {
72                struct _CustomVisitor;
73
74                impl<'de> serde::de::Visitor<'de> for _CustomVisitor {
75                    type Value = $name;
76
77                    fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78                        fmt.write_str("integer or string")
79                    }
80
81                    fn visit_u64<E>(self, val: u64) -> Result<Self::Value, E>
82                    where
83                        E: serde::de::Error,
84                    {
85                        Ok($name(val))
86                    }
87
88                    fn visit_str<E>(self, val: &str) -> Result<Self::Value, E>
89                    where
90                        E: serde::de::Error,
91                    {
92                        val.parse::<u64>()
93                            .map_err(|_| E::custom(concat!("failed to parse ", stringify!($name))))
94                            .map($name)
95                    }
96                }
97
98                deserializer.deserialize_any(_CustomVisitor)
99            }
100        }
101    };
102}