Skip to main content

tvscreener/
error.rs

1// Copyright 2026 tvscreener-rs contributors
2// SPDX-License-Identifier: Apache-2.0
3
4//! Error types for HTTP, JSON, and request construction failures.
5
6use thiserror::Error;
7
8/// Crate-wide result alias.
9pub type Result<T> = std::result::Result<T, TvscreenerError>;
10
11/// Errors produced by payload building, HTTP, or response parsing.
12///
13/// Wraps network / JSON failures from `reqwest` / `serde_json`.
14#[derive(Debug, Error)]
15pub enum TvscreenerError {
16    /// `TradingView` (or proxy) returned a non-success HTTP status.
17    #[error("HTTP {status}: {body}")]
18    HttpStatus {
19        /// Response status code.
20        status: u16,
21        /// Response body (truncated when longer than 4 KiB).
22        body: String,
23    },
24
25    /// Request timed out.
26    #[error("request timed out")]
27    Timeout,
28
29    /// Underlying network / transport failure.
30    #[error("network error: {0}")]
31    Network(#[source] reqwest::Error),
32
33    /// Response body was not valid JSON or did not match the expected shape.
34    #[error("JSON error: {0}")]
35    Json(String),
36
37    /// Caller built an invalid filter, range, or column set.
38    #[error("invalid request: {0}")]
39    InvalidRequest(String),
40
41    /// Filter `left` is not in the allowed field set for this screener.
42    #[error("invalid field name: {0}")]
43    InvalidFieldName(String),
44}
45
46impl From<reqwest::Error> for TvscreenerError {
47    fn from(err: reqwest::Error) -> Self {
48        if err.is_timeout() {
49            Self::Timeout
50        } else {
51            Self::Network(err)
52        }
53    }
54}
55
56impl From<serde_json::Error> for TvscreenerError {
57    fn from(err: serde_json::Error) -> Self {
58        Self::Json(err.to_string())
59    }
60}