use std::marker::PhantomData;
use std::str::FromStr;
use serde::{Deserialize, Serialize, Deserializer};
use serde::de::{self, Visitor, MapAccess};
extern crate void;
use void::Void;
use std::fmt;
use crate::message::common::command_trait::CommandConversion;
use std::any::Any;
use crate::base::base_config::{CURRENCY};
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Amount {
#[serde(rename="value")]
pub value: String,
#[serde(rename="currency")]
pub currency: Option<String>,
#[serde(rename="issuer")]
pub issuer: Option<String>, }
impl Amount {
pub fn new(currency: Option<String>, value: String, issuer: Option<String>) -> Self {
Amount {
value : value,
currency: currency,
issuer : issuer,
}
}
pub fn is_string(&self) -> bool {
let mut ret = false;
if let Some(x) = &self.currency {
if *x == CURRENCY.to_string() && self.issuer.is_none() {
ret = true;
}
}
ret
}
pub fn is_native(&self) -> bool {
if let Some(x) = &self.currency {
if *x == "SWT".to_string() {
return true;
}
}
false
}
pub fn mul_million(value: &String) -> String {
let mut ret = 0f64;
if let Ok(x) = value.parse::<f64>() {
ret = x * 1_000_000f64;
}
(ret as u64).to_string()
}
}
impl FromStr for Amount {
type Err = Void;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(
Amount {
value: s.to_string(),
currency: Some("SWT".to_string()),
issuer: None,
}
)
}
}
pub fn string_or_struct<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: Deserialize<'de> + FromStr<Err = Void>,
D: Deserializer<'de>,
{
struct StringOrStruct<T>(PhantomData<fn() -> T>);
impl<'de, T> Visitor<'de> for StringOrStruct<T>
where
T: Deserialize<'de> + FromStr<Err = Void>,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string")
}
fn visit_str<E>(self, value: &str) -> Result<T, E>
where
E: de::Error,
{
Ok(FromStr::from_str(value).unwrap())
}
fn visit_map<M>(self, map: M) -> Result<T, M::Error>
where
M: MapAccess<'de>,
{
Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))
}
}
deserializer.deserialize_any(StringOrStruct(PhantomData))
}
impl CommandConversion for Amount {
type T = Amount;
fn to_string(&self) -> Result<String, serde_json::error::Error> {
let j = serde_json::to_string(&self)?;
Ok(j)
}
fn box_to_raw(&self) -> &dyn Any {
self
}
}