#![allow(missing_docs)]
use serde::de::{self, Deserializer, Visitor};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[allow(non_camel_case_types)]
pub enum EdisExchange {
NSE,
BSE,
MCX,
ALL,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[allow(non_camel_case_types)]
pub enum EdisSegment {
EQ,
COMM,
FNO,
}
#[derive(Debug, Clone, Serialize)]
pub struct EdisBulkFormRequest {
pub isin: Vec<String>,
pub exchange: EdisExchange,
pub segment: EdisSegment,
}
impl EdisBulkFormRequest {
pub fn validate(&self) -> std::result::Result<(), &'static str> {
if self.isin.is_empty() {
return Err("bulk eDIS isin cannot be empty");
}
if self.isin.iter().any(|isin| isin.trim().is_empty()) {
return Err("bulk eDIS isin entries cannot be empty");
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize)]
pub struct EdisFormRequest {
pub isin: String,
pub qty: u64,
pub exchange: String,
pub segment: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub bulk: Option<bool>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EdisFormResponse {
pub dhan_client_id: String,
pub edis_form_html: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EdisInquiry {
pub client_id: Option<String>,
pub isin: Option<String>,
#[serde(
default,
deserialize_with = "deserialize_optional_i64_from_integer_or_string"
)]
pub total_qty: Option<i64>,
#[serde(
default,
deserialize_with = "deserialize_optional_i64_from_integer_or_string"
)]
pub aprvd_qty: Option<i64>,
pub status: Option<String>,
pub remarks: Option<String>,
}
fn deserialize_optional_i64_from_integer_or_string<'de, D>(
deserializer: D,
) -> Result<Option<i64>, D::Error>
where
D: Deserializer<'de>,
{
struct QuantityVisitor;
impl<'de> Visitor<'de> for QuantityVisitor {
type Value = Option<i64>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an integer, an integer string, or null")
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Some(value))
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
i64::try_from(value).map(Some).map_err(E::custom)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
value.parse::<i64>().map(Some).map_err(E::custom)
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_str(&value)
}
}
deserializer.deserialize_option(QuantityVisitor)
}