use crate::models::MarketStatus;
#[derive(Debug, Clone)]
pub struct ExchangeManifest {
pub id: &'static str,
pub name: &'static str,
pub base_url: &'static str,
pub markets_endpoint: &'static str,
pub pagination: PaginationConfig,
pub rate_limit: RateLimitConfig,
pub field_mappings: &'static [FieldMapping],
pub status_map: &'static [(&'static str, MarketStatus)],
}
impl ExchangeManifest {
pub fn map_status(&self, exchange_status: &str) -> Option<MarketStatus> {
self.status_map
.iter()
.find(|(s, _)| s.eq_ignore_ascii_case(exchange_status))
.map(|(_, status)| *status)
}
pub fn get_field_mapping(&self, unified_field: &str) -> Option<&FieldMapping> {
self.field_mappings
.iter()
.find(|m| m.unified_field == unified_field)
}
}
#[derive(Debug, Clone, Copy)]
pub struct PaginationConfig {
pub style: PaginationStyle,
pub max_page_size: usize,
pub limit_param: &'static str,
pub cursor_param: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PaginationStyle {
Cursor,
Offset,
PageNumber,
None,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum RateLimitCategory {
Read = 0,
Write = 1,
Bulk = 2,
}
impl RateLimitCategory {
pub const COUNT: usize = 3;
pub const ALL: [RateLimitCategory; 3] = [
RateLimitCategory::Read,
RateLimitCategory::Write,
RateLimitCategory::Bulk,
];
}
#[derive(Debug, Clone, Copy)]
pub struct EndpointRateLimit {
pub category: RateLimitCategory,
pub requests_per_second: u32,
pub burst: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct RateLimitConfig {
pub default_rps: u32,
pub default_burst: u32,
pub limits: &'static [EndpointRateLimit],
}
impl RateLimitConfig {
pub const fn get(&self, category: RateLimitCategory) -> (u32, u32) {
let mut i = 0;
while i < self.limits.len() {
if self.limits[i].category as u8 == category as u8 {
return (self.limits[i].requests_per_second, self.limits[i].burst);
}
i += 1;
}
(self.default_rps, self.default_burst)
}
pub const fn rps(&self, category: RateLimitCategory) -> u32 {
self.get(category).0
}
pub const fn requests_per_second(&self) -> u32 {
self.default_rps
}
}
#[derive(Debug, Clone)]
pub struct FieldMapping {
pub unified_field: &'static str,
pub source_paths: &'static [&'static str],
pub transform: Transform,
pub nullable: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Transform {
Direct,
CentsToDollars,
UnixSecsToDateTime,
UnixMillisToDateTime,
Iso8601ToDateTime,
ParseInt,
ParseFloat,
JsonArrayIndex(usize),
NestedPath,
}