Skip to main content

tvscreener/mcp/
resolve.rs

1// Copyright 2026 tvscreener-rs contributors
2// SPDX-License-Identifier: Apache-2.0
3
4//! Token parsing and wire-value resolution for screener parameters.
5
6use crate::error::{Result, TvscreenerError};
7use crate::field::Asset;
8
9pub use crate::resolve::{
10    apply_stock_index_markets, parse_csv_tokens, resolve_country_wires, resolve_exchange_wires,
11    resolve_index_wires, resolve_industry_wires, resolve_market_wires, resolve_sector_wires,
12};
13
14/// Parses an optional `"min,max"` range string into `(min, max)` floats.
15///
16/// Empty sides become `None`. Invalid numbers are ignored for that side.
17#[must_use]
18pub fn parse_f64_range(raw: Option<&str>) -> (Option<f64>, Option<f64>) {
19    let Some(raw) = raw.map(str::trim).filter(|s| !s.is_empty()) else {
20        return (None, None);
21    };
22    let mut parts = raw.splitn(2, ',');
23    let min = parts
24        .next()
25        .map(str::trim)
26        .filter(|s| !s.is_empty())
27        .and_then(|s| s.parse().ok());
28    let max = parts
29        .next()
30        .map(str::trim)
31        .filter(|s| !s.is_empty())
32        .and_then(|s| s.parse().ok());
33    (min, max)
34}
35
36/// Parses an asset type string into [`Asset`].
37///
38/// # Errors
39///
40/// Returns [`TvscreenerError::InvalidRequest`] for unknown asset types.
41pub fn parse_asset(asset_type: &str) -> Result<Asset> {
42    Asset::parse(asset_type.trim().to_ascii_lowercase().as_str()).ok_or_else(|| {
43        TvscreenerError::InvalidRequest(format!(
44            "unknown asset_type `{asset_type}` (use stock|crypto|forex|bond|futures|coin)"
45        ))
46    })
47}
48
49#[cfg(test)]
50mod tests {
51    use super::parse_f64_range;
52
53    #[test]
54    fn parse_f64_range_sides() {
55        assert_eq!(parse_f64_range(None), (None, None));
56        assert_eq!(parse_f64_range(Some("")), (None, None));
57        assert_eq!(parse_f64_range(Some("10,20")), (Some(10.0), Some(20.0)));
58        assert_eq!(parse_f64_range(Some("10,")), (Some(10.0), None));
59        assert_eq!(parse_f64_range(Some(",20")), (None, Some(20.0)));
60        assert_eq!(parse_f64_range(Some("x,20")), (None, Some(20.0)));
61        assert_eq!(parse_f64_range(Some("10,y")), (Some(10.0), None));
62    }
63}