1use thiserror::Error;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum TransportFailureReason {
11 PeerEof,
12 CodecError,
13 Shutdown,
14 UnmatchedSerial,
15 ResponseTimeout,
16 SendError,
17}
18
19impl TransportFailureReason {
20 #[must_use]
21 pub const fn as_str(self) -> &'static str {
22 match self {
23 Self::PeerEof => "peer_eof",
24 Self::CodecError => "codec_error",
25 Self::Shutdown => "shutdown",
26 Self::UnmatchedSerial => "unmatched_serial",
27 Self::ResponseTimeout => "response_timeout",
28 Self::SendError => "send_error",
29 }
30 }
31}
32
33impl std::fmt::Display for TransportFailureReason {
34 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 formatter.write_str(self.as_str())
36 }
37}
38
39#[derive(Debug, Error)]
44#[non_exhaustive]
45pub enum FutuError {
46 #[error("网络错误: {0}")]
47 Network(#[from] std::io::Error),
48
49 #[error("协议解析错误: {0}")]
50 Codec(String),
51
52 #[error("Protobuf 解码失败: {0}")]
53 Proto(#[from] prost::DecodeError),
54
55 #[error("服务端返回错误, ret_type={ret_type}, msg={msg}")]
56 ServerError { ret_type: i32, msg: String },
57
58 #[error("连接超时")]
59 Timeout,
60
61 #[error("传输失败 ({reason}): {detail}")]
64 TransportFailure {
65 reason: TransportFailureReason,
66 detail: String,
67 },
68
69 #[error("未初始化")]
70 NotInitialized,
71
72 #[error("已缓存的 SMS 验证仍在等待验证码输入")]
73 SmsVerificationCodeRequired,
74
75 #[error("加密错误: {0}")]
76 Encryption(String),
77
78 #[error("SHA1 校验失败")]
79 Sha1Mismatch,
80
81 #[error("无效的协议帧头")]
82 InvalidHeader,
83}
84
85pub type Result<T> = std::result::Result<T, FutuError>;