use time::OffsetDateTime;
use super::builder::ValidationError;
use super::common::encoders;
use super::ExerciseAction;
use crate::contracts::Contract;
use crate::orders::OrderId;
use crate::Error;
#[must_use = "ExerciseOptionsBuilder does nothing until you call .submit()"]
pub struct ExerciseOptionsBuilder<'a, C> {
client: &'a C,
contract: &'a Contract,
action: Option<(ExerciseAction, i32)>,
account: Option<String>,
override_natural_action: bool,
manual_order_time: Option<OffsetDateTime>,
}
impl<'a, C> ExerciseOptionsBuilder<'a, C> {
pub(crate) fn new(client: &'a C, contract: &'a Contract) -> Self {
Self {
client,
contract,
action: None,
account: None,
override_natural_action: false,
manual_order_time: None,
}
}
pub fn exercise(mut self, quantity: i32) -> Self {
self.action = Some((ExerciseAction::Exercise, quantity));
self
}
pub fn lapse(mut self, quantity: i32) -> Self {
self.action = Some((ExerciseAction::Lapse, quantity));
self
}
pub fn account(mut self, account: impl Into<String>) -> Self {
self.account = Some(account.into());
self
}
pub fn override_natural_action(mut self) -> Self {
self.override_natural_action = true;
self
}
pub fn manual_order_time(mut self, time: OffsetDateTime) -> Self {
self.manual_order_time = Some(time);
self
}
fn encode(&self, next_order_id: impl FnOnce() -> i32) -> Result<(OrderId, Vec<u8>), Error> {
let (action, quantity) = self.action.ok_or(ValidationError::MissingRequiredField("exercise or lapse"))?;
if quantity <= 0 {
return Err(ValidationError::InvalidQuantity(f64::from(quantity)).into());
}
let order_id = OrderId::from(next_order_id()).checked()?;
let request = encoders::encode_exercise_options(
order_id.value(),
self.contract,
action,
quantity,
self.account.as_deref().unwrap_or_default(),
self.override_natural_action,
self.manual_order_time,
)?;
Ok((order_id, request))
}
}
#[cfg(feature = "sync")]
impl ExerciseOptionsBuilder<'_, crate::client::sync::Client> {
pub fn submit(self) -> Result<crate::subscriptions::sync::Subscription<super::ExerciseOptions>, Error> {
let (order_id, request) = self.encode(|| self.client.next_order_id())?;
let subscription = self.client.send_order(order_id, request)?;
Ok(crate::subscriptions::sync::Subscription::new(
std::sync::Arc::clone(&self.client.message_bus),
subscription,
self.client.decoder_context(),
))
}
}
#[cfg(feature = "async")]
impl ExerciseOptionsBuilder<'_, crate::client::r#async::Client> {
pub async fn submit(self) -> Result<crate::subscriptions::r#async::Subscription<super::ExerciseOptions>, Error> {
let (order_id, request) = self.encode(|| self.client.next_order_id())?;
let internal_subscription = self.client.send_order(order_id, request).await?;
Ok(crate::subscriptions::Subscription::new_from_internal_simple(
internal_subscription,
self.client.message_bus.clone(),
self.client.decoder_context(),
))
}
}
#[cfg(test)]
#[path = "exercise_options_builder_tests.rs"]
mod tests;