//! cTrader Open API error types. use std::fmt; /// Errors from the cTrader Open API client. #[derive(Debug, thiserror::Error)] pub enum CTraderError { /// TCP or TLS connection failed. #[error("connection failed: {0}")] ConnectionFailed(String), /// TLS handshake error. #[error("TLS error: {0}")] TlsError(String), /// OAuth2 token exchange failed. #[error("OAuth error: {0}")] OAuthError(String), /// Application-level authentication rejected. #[error("application auth failed: {0}")] AppAuthFailed(String), /// Account-level authentication rejected. #[error("account auth failed: {0}")] AccountAuthFailed(String), /// Protobuf encode/decode error. #[error("protocol error: {0}")] ProtocolError(String), /// Codec framing error. #[error("codec error: {0}")] CodecError(String), /// Rate limit exceeded (50 req/s or 5 req/s for historical). #[error("rate limit exceeded for {bucket}")] RateLimitExceeded { /// Which bucket was exhausted. bucket: RateLimitBucket, }, /// Request timed out waiting for a response. #[error("request timed out after {0:?}")] Timeout(std::time::Duration), /// Server returned an error payload. #[error("server error {code}: {description}")] ServerError { /// cTrader error code. code: String, /// Human-readable description. description: String, }, /// Client is not connected. #[error("not connected")] NotConnected, /// Symbol not found in the cached symbol list. #[error("unknown symbol: {0}")] UnknownSymbol(String), /// I/O error (required by `tokio_util::codec`). #[error("io error: {0}")] Io(String), } impl From for CTraderError { fn from(e: std::io::Error) -> Self { Self::Io(e.to_string()) } } impl From for CTraderError { fn from(e: prost::DecodeError) -> Self { Self::ProtocolError(format!("protobuf decode error: {e}")) } } /// Rate-limit bucket categories. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RateLimitBucket { /// Standard messages: 50 per second. NonHistorical, /// Historical data requests: 5 per second. Historical, } impl fmt::Display for RateLimitBucket { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NonHistorical => f.write_str("non-historical (50/s)"), Self::Historical => f.write_str("historical (5/s)"), } } } /// Convenience alias used throughout the crate. pub type Result = std::result::Result;