use serde::{Deserialize, Serialize};
use std::{borrow::Cow, fmt};
#[derive(
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash,
)]
pub struct Asset<'a>(Cow<'a, str>);
impl<'a> fmt::Display for Asset<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'a> From<&'a str> for Asset<'a> {
fn from(asset: &'a str) -> Self {
Self(asset.into())
}
}
impl<'a> From<String> for Asset<'a> {
fn from(asset: String) -> Self {
Self(asset.into())
}
}
impl<'a> Asset<'a> {
pub fn new(asset: impl Into<Cow<'a, str>>) -> Self {
Self(asset.into())
}
pub fn pair(self, quote: impl Into<Self>) -> AssetPair<'a> {
AssetPair {
base: self,
quote: quote.into(),
}
}
}
#[derive(
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash,
)]
pub struct AssetPair<'a> {
pub base: Asset<'a>,
pub quote: Asset<'a>,
}
impl<'a> fmt::Display for AssetPair<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", self.base, self.quote)
}
}
impl<'a> From<(Asset<'a>, Asset<'a>)> for AssetPair<'a> {
fn from((base, quote): (Asset<'a>, Asset<'a>)) -> Self {
Self { base, quote }
}
}
impl<'a> From<AssetPair<'a>> for (Asset<'a>, Asset<'a>) {
fn from(asset_pair: AssetPair<'a>) -> Self {
(asset_pair.base, asset_pair.quote)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{api, client, Client, Response};
use anyhow::Result;
use std::collections::HashMap;
#[tokio::test]
async fn asset_pairs() -> Result<()> {
let client = Client::new(client::user_agent())?;
type AssetPairs<'a> = HashMap<String, AssetPair<'a>>;
let api = api::public::asset_pairs();
let resp: Response<AssetPairs> = client.send(api).await?;
assert!(resp.is_success());
println!("{:#?}", resp.result);
let asset_pairs = resp.result.expect("No asset pairs in response");
for (_, asset_pair) in asset_pairs {
let (base, quote): (Asset, Asset) = asset_pair.clone().into();
assert_eq!(AssetPair::from((base, quote)), asset_pair);
}
Ok(())
}
#[test]
fn asset_deserialize() -> Result<()> {
let xbt: Asset = serde_json::from_str(r#""XXBT""#)?;
assert_eq!(Asset::new("XXBT"), xbt);
assert_eq!(xbt.to_string(), "XXBT".to_string());
let eur: Asset = serde_json::from_str(r#""ZEUR""#)?;
assert_eq!(Asset::new("ZEUR"), eur);
assert_eq!(eur.to_string(), "ZEUR".to_string());
let kfee: Asset = serde_json::from_str(r#""KFEE""#)?;
assert_eq!(Asset::new("KFEE"), kfee);
assert_eq!(kfee.to_string(), "KFEE".to_string());
Ok(())
}
}