#[cfg(feature = "websocket")]
mod block;
#[cfg(feature = "websocket")]
use block::Block as BlockWorker;
#[cfg(feature = "async-websocket")]
mod r#async;
#[cfg(feature = "async-websocket")]
use r#async::Async as AsyncWorker;
#[cfg(feature = "websocket")]
use std::sync::mpsc::{channel, Receiver};
#[cfg(feature = "async-websocket")]
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use crate::schema::{ChartResponse, MetaResponse, QuoteResponse, Result};
const INTRADAY_CHART: &str = "wss://api.fugle.tw/realtime/v0.3/intraday/chart";
const INTRADAY_QUOTE: &str = "wss://api.fugle.tw/realtime/v0.3/intraday/quote";
const INTRADAY_META: &str = "wss://api.fugle.tw/realtime/v0.3/intraday/meta";
pub struct IntradayBuilder<'a> {
token: &'a str,
symbol_id: &'a str,
is_odd_lot: bool,
}
impl<'a> Default for IntradayBuilder<'a> {
fn default() -> IntradayBuilder<'a> {
IntradayBuilder::new()
}
}
impl<'a> IntradayBuilder<'a> {
pub fn new() -> IntradayBuilder<'a> {
IntradayBuilder {
token: "demo",
symbol_id: "",
is_odd_lot: false,
}
}
pub fn token(mut self, token: &'a str) -> IntradayBuilder {
self.token = token;
self
}
pub fn symbol_id(mut self, symbol_id: &'a str) -> IntradayBuilder {
self.symbol_id = symbol_id;
self
}
pub fn odd_lot(mut self) -> IntradayBuilder<'a> {
self.is_odd_lot = true;
self
}
pub fn build(self) -> Intraday {
Intraday {
uri: format!(
"symbolId={}&apiToken={}&oddLot={}",
self.symbol_id, self.token, self.is_odd_lot,
),
workers: vec![],
done: Arc::new(AtomicBool::new(false)),
}
}
}
pub struct Intraday {
uri: String,
workers: Vec<Box<dyn Worker>>,
done: Arc<AtomicBool>,
}
impl Intraday {
#[cfg(feature = "websocket")]
pub fn chart(&mut self) -> Result<Receiver<ChartResponse>> {
let (tx, rx) = channel();
let uri = &format!("{}?{}", INTRADAY_CHART, self.uri);
let worker = BlockWorker::new(uri, tx, self.done.clone())?;
self.workers.push(Box::new(worker));
Ok(rx)
}
#[cfg(feature = "async-websocket")]
pub async fn async_chart(&mut self) -> Result<UnboundedReceiver<ChartResponse>> {
let (tx, rx) = unbounded_channel();
let uri = &format!("{}?{}", INTRADAY_CHART, self.uri);
let worker = AsyncWorker::new(uri, tx, self.done.clone()).await?;
self.workers.push(Box::new(worker));
Ok(rx)
}
#[cfg(feature = "websocket")]
pub fn meta(&mut self) -> Result<Receiver<MetaResponse>> {
let (tx, rx) = channel();
let uri = &format!("{}?{}", INTRADAY_META, self.uri);
let worker = BlockWorker::new(uri, tx, self.done.clone())?;
self.workers.push(Box::new(worker));
Ok(rx)
}
#[cfg(feature = "async-websocket")]
pub async fn async_meta(&mut self) -> Result<UnboundedReceiver<MetaResponse>> {
let (tx, rx) = unbounded_channel();
let uri = &format!("{}?{}", INTRADAY_META, self.uri);
let worker = AsyncWorker::new(uri, tx, self.done.clone()).await?;
self.workers.push(Box::new(worker));
Ok(rx)
}
#[cfg(feature = "websocket")]
pub fn quote(&mut self) -> Result<Receiver<QuoteResponse>> {
let (tx, rx) = channel();
let uri = &format!("{}?{}", INTRADAY_QUOTE, self.uri);
let worker = BlockWorker::new(uri, tx, self.done.clone())?;
self.workers.push(Box::new(worker));
Ok(rx)
}
#[cfg(feature = "async-websocket")]
pub async fn async_quote(&mut self) -> Result<UnboundedReceiver<QuoteResponse>> {
let (tx, rx) = unbounded_channel();
let uri = &format!("{}?{}", INTRADAY_QUOTE, self.uri);
let worker = AsyncWorker::new(uri, tx, self.done.clone()).await?;
self.workers.push(Box::new(worker));
Ok(rx)
}
}
impl Drop for Intraday {
fn drop(&mut self) {
self.done.store(true, Ordering::SeqCst);
for worker in self.workers.iter_mut() {
worker.stop();
}
}
}
pub(crate) trait Worker: Send {
fn stop(&mut self);
}