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}