Files
foxhunt/crates/ctrader-openapi/src/error.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00

101 lines
2.6 KiB
Rust

//! 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<std::io::Error> for CTraderError {
fn from(e: std::io::Error) -> Self {
Self::Io(e.to_string())
}
}
impl From<prost::DecodeError> 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<T> = std::result::Result<T, CTraderError>;