Skip to main content

kiteconnect_rs/models/
error.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct KiteError {
6    pub status: String,
7    pub message: String,
8    pub data: Option<serde_json::Value>,
9    pub error_type: String,
10}
11
12impl fmt::Display for KiteError {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        write!(f, "Kite API Error: {} ({})", self.message, self.error_type)
15    }
16}
17
18impl std::error::Error for KiteError {}
19
20#[derive(Debug)]
21pub struct KiteConnectError {
22    pub kind: KiteConnectErrorKind,
23    pub backtrace: std::backtrace::Backtrace,
24}
25
26#[derive(Debug)]
27pub enum KiteConnectErrorKind {
28    ApiError(KiteError),
29    HttpError(reqwest::Error),
30    SerializationError(serde_json::Error),
31    InvalidHeader(reqwest::header::InvalidHeaderValue),
32    Other(String),
33}
34
35impl fmt::Display for KiteConnectError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match &self.kind {
38            KiteConnectErrorKind::ApiError(e) => write!(f, "{}", e),
39            KiteConnectErrorKind::HttpError(e) => write!(f, "HTTP Error: {}", e),
40            KiteConnectErrorKind::SerializationError(e) => write!(f, "Serialization Error: {}", e),
41            KiteConnectErrorKind::InvalidHeader(e) => write!(f, "Invalid Header: {}", e),
42            KiteConnectErrorKind::Other(e) => write!(f, "Error: {}", e),
43        }
44    }
45}
46
47impl std::error::Error for KiteConnectError {
48    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49        match &self.kind {
50            KiteConnectErrorKind::ApiError(e) => Some(e),
51            KiteConnectErrorKind::HttpError(e) => Some(e),
52            KiteConnectErrorKind::SerializationError(e) => Some(e),
53            KiteConnectErrorKind::InvalidHeader(e) => Some(e),
54            KiteConnectErrorKind::Other(_) => None,
55        }
56    }
57}
58
59impl KiteConnectError {
60    /// Create a new error with the given kind
61    pub fn new(kind: KiteConnectErrorKind) -> Self {
62        KiteConnectError {
63            kind,
64            backtrace: std::backtrace::Backtrace::capture(),
65        }
66    }
67
68    /// Create a new Other error with captured backtrace
69    pub fn other(msg: impl Into<String>) -> Self {
70        Self::new(KiteConnectErrorKind::Other(msg.into()))
71    }
72
73    /// Get the backtrace for this error
74    pub fn backtrace(&self) -> &std::backtrace::Backtrace {
75        &self.backtrace
76    }
77
78    pub fn print_backtrace(&self) {
79        use std::backtrace::BacktraceStatus;
80
81        match self.backtrace.status() {
82            BacktraceStatus::Disabled | BacktraceStatus::Unsupported => {
83                eprintln!("Backtrace disabled (run with RUST_BACKTRACE=1)");
84                return;
85            }
86            BacktraceStatus::Captured => {}
87            _ => return,
88        }
89
90        let trace = self.backtrace.to_string();
91        let mut count = 0;
92
93        for line in trace.lines() {
94            // Print frame number and function
95            if let Some(pos) = line.find(": ") {
96                let frame_num = line[..pos].trim();
97                let content = &line[pos + 2..];
98                eprintln!("  {} → {}", frame_num, content);
99                count += 1;
100            } else if line.trim().starts_with("at ") {
101                eprintln!("       {}", line.trim());
102            }
103        }
104
105        if count == 0 {
106            eprintln!("  (no frames to display)");
107        }
108    }
109}
110
111impl From<reqwest::Error> for KiteConnectError {
112    fn from(error: reqwest::Error) -> Self {
113        Self::new(KiteConnectErrorKind::HttpError(error))
114    }
115}
116
117impl From<serde_json::Error> for KiteConnectError {
118    fn from(error: serde_json::Error) -> Self {
119        Self::new(KiteConnectErrorKind::SerializationError(error))
120    }
121}
122
123impl From<reqwest::header::InvalidHeaderValue> for KiteConnectError {
124    fn from(error: reqwest::header::InvalidHeaderValue) -> Self {
125        Self::new(KiteConnectErrorKind::InvalidHeader(error))
126    }
127}
128
129impl From<KiteError> for KiteConnectError {
130    fn from(error: KiteError) -> Self {
131        Self::new(KiteConnectErrorKind::ApiError(error))
132    }
133}