futucli/cmd/trade_ext/
parsers.rs1use anyhow::{Context, Result, bail};
2use futu_trd::types::{ModifyOrderOp, OrderType, TrdSide};
3
4pub(crate) fn parse_trd_side(s: &str) -> Result<TrdSide> {
5 futu_trd::parsing::parse_trd_side(s).ok_or_else(|| {
6 anyhow::anyhow!(
7 "unknown trd side {:?} ({})",
8 s.trim().to_ascii_uppercase(),
9 futu_trd::parsing::TRD_SIDE_PARSE_CHOICES
10 )
11 })
12}
13
14pub(crate) fn parse_order_type(s: &str) -> Result<OrderType> {
15 futu_trd::parsing::parse_order_type(s).ok_or_else(|| {
16 anyhow::anyhow!(
17 "unknown order type {:?} ({})",
18 s.trim().to_ascii_uppercase(),
19 futu_trd::parsing::ORDER_TYPE_PARSE_CHOICES
20 )
21 })
22}
23
24pub(crate) fn parse_modify_op(s: &str) -> Result<ModifyOrderOp> {
25 futu_trd::parsing::parse_modify_op(s).ok_or_else(|| {
26 anyhow::anyhow!(
27 "unknown modify op {:?} ({})",
28 s.trim().to_ascii_uppercase(),
29 futu_trd::parsing::MODIFY_OP_PARSE_CHOICES
30 )
31 })
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub(crate) struct ResolvedOrderIdArg {
36 pub(crate) order_id: u64,
37 pub(crate) order_id_ex: Option<String>,
38 pub(crate) idempotency_component: String,
39}
40
41pub(crate) fn resolve_order_id_arg(raw: &str) -> Result<ResolvedOrderIdArg> {
42 let trimmed = raw.trim();
43 if trimmed.is_empty() {
44 bail!("--order-id must not be empty");
45 }
46
47 if trimmed.bytes().all(|b| b.is_ascii_digit()) {
51 let order_id = trimmed
52 .parse::<u64>()
53 .with_context(|| format!("invalid numeric --order-id {trimmed:?}"))?;
54 return Ok(ResolvedOrderIdArg {
55 order_id,
56 order_id_ex: None,
57 idempotency_component: trimmed.to_string(),
58 });
59 }
60
61 Ok(ResolvedOrderIdArg {
62 order_id: 0,
63 order_id_ex: Some(trimmed.to_string()),
64 idempotency_component: trimmed.to_string(),
65 })
66}
67
68pub(crate) fn parse_numeric_order_id_arg(raw: &str, field: &str) -> Result<u64> {
69 let trimmed = raw.trim();
70 if trimmed.is_empty() {
71 bail!("{field} must not be empty");
72 }
73 if !trimmed.bytes().all(|b| b.is_ascii_digit()) {
74 bail!(
75 "{field} for reconfirm-order must be numeric FTAPI order_id; \
76 orderIDEx is not supported by Trd_ReconfirmOrder"
77 );
78 }
79 trimmed
80 .parse::<u64>()
81 .with_context(|| format!("invalid {field} {trimmed:?}"))
82}